1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : // vim:set ts=2 sts=2 sw=2 et cin:
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Pierre Phaneuf <pp@ludusdesign.com>
25 : * Jacek Piskozub <piskozub@iopan.gda.pl>
26 : * Leon Sha <leon.sha@sun.com>
27 : * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
28 : * Robert O'Callahan <roc+moz@cs.cmu.edu>
29 : * Christian Biesinger <cbiesinger@web.de>
30 : * Josh Aas <josh@mozilla.com>
31 : * Mats Palmgren <matspal@gmail.com>
32 : *
33 : * Alternatively, the contents of this file may be used under the terms of
34 : * either of the GNU General Public License Version 2 or later (the "GPL"),
35 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
36 : * in which case the provisions of the GPL or the LGPL are applicable instead
37 : * of those above. If you wish to allow use of your version of this file only
38 : * under the terms of either the GPL or the LGPL, and not to allow others to
39 : * use your version of this file under the terms of the MPL, indicate your
40 : * decision by deleting the provisions above and replace them with the notice
41 : * and other provisions required by the GPL or the LGPL. If you do not delete
42 : * the provisions above, a recipient may use your version of this file under
43 : * the terms of any one of the MPL, the GPL or the LGPL.
44 : *
45 : * ***** END LICENSE BLOCK ***** */
46 :
47 : #ifdef MOZ_WIDGET_QT
48 : #include <QWidget>
49 : #include <QKeyEvent>
50 : #ifdef MOZ_X11
51 : #include <QX11Info>
52 : #endif
53 : #undef slots
54 : #endif
55 :
56 : #ifdef MOZ_X11
57 : #include <cairo-xlib.h>
58 : #include "gfxXlibSurface.h"
59 : /* X headers suck */
60 : enum { XKeyPress = KeyPress };
61 : #ifdef KeyPress
62 : #undef KeyPress
63 : #endif
64 : #include "mozilla/X11Util.h"
65 : using mozilla::DefaultXDisplay;
66 : #endif
67 :
68 : #include "nsPluginInstanceOwner.h"
69 : #include "nsIRunnable.h"
70 : #include "nsContentUtils.h"
71 : #include "nsRect.h"
72 : #include "nsSize.h"
73 : #include "nsDisplayList.h"
74 : #include "ImageLayers.h"
75 : #include "nsIDOMEventTarget.h"
76 : #include "nsObjectFrame.h"
77 : #include "nsIPluginDocument.h"
78 : #include "nsIStringStream.h"
79 : #include "nsNetUtil.h"
80 : #include "mozilla/Preferences.h"
81 : #include "nsILinkHandler.h"
82 : #include "nsIDocShellTreeItem.h"
83 : #include "nsIWebBrowserChrome.h"
84 : #include "nsLayoutUtils.h"
85 : #include "nsIPrivateDOMEvent.h"
86 : #include "nsIPluginWidget.h"
87 : #include "nsIViewManager.h"
88 : #include "nsIDocShellTreeOwner.h"
89 : #include "nsIDOMHTMLObjectElement.h"
90 : #include "nsIAppShell.h"
91 : #include "nsIDOMHTMLAppletElement.h"
92 : #include "nsAttrName.h"
93 : #include "nsIFocusManager.h"
94 : #include "nsFocusManager.h"
95 : #include "nsIDOMDragEvent.h"
96 : #include "nsIScrollableFrame.h"
97 : #include "nsIImageLoadingContent.h"
98 :
99 : #include "nsContentCID.h"
100 : #include "nsWidgetsCID.h"
101 : static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
102 : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
103 :
104 : #ifdef XP_WIN
105 : #include <wtypes.h>
106 : #include <winuser.h>
107 : #endif
108 :
109 : #ifdef XP_MACOSX
110 : #include <Carbon/Carbon.h>
111 : #include "nsPluginUtilsOSX.h"
112 : #endif
113 :
114 : #ifdef MOZ_WIDGET_GTK2
115 : #include <gdk/gdk.h>
116 : #include <gdk/gdkx.h>
117 : #include <gtk/gtk.h>
118 : #include "gfxXlibNativeRenderer.h"
119 : #endif
120 :
121 : #ifdef MOZ_WIDGET_ANDROID
122 : #include "ANPBase.h"
123 : #include "android_npapi.h"
124 : #include "AndroidBridge.h"
125 : #include "AndroidMediaLayer.h"
126 : using namespace mozilla::dom;
127 :
128 : #include <android/log.h>
129 : #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
130 : #endif
131 :
132 : using namespace mozilla;
133 :
134 : // special class for handeling DOM context menu events because for
135 : // some reason it starves other mouse events if implemented on the
136 : // same class
137 : class nsPluginDOMContextMenuListener : public nsIDOMEventListener
138 : {
139 : public:
140 : nsPluginDOMContextMenuListener();
141 : virtual ~nsPluginDOMContextMenuListener();
142 :
143 : NS_DECL_ISUPPORTS
144 : NS_DECL_NSIDOMEVENTLISTENER
145 :
146 : nsresult Init(nsIContent* aContent);
147 : nsresult Destroy(nsIContent* aContent);
148 :
149 : nsEventStatus ProcessEvent(const nsGUIEvent& anEvent)
150 : {
151 : return nsEventStatus_eConsumeNoDefault;
152 : }
153 : };
154 :
155 : class AsyncPaintWaitEvent : public nsRunnable
156 0 : {
157 : public:
158 0 : AsyncPaintWaitEvent(nsIContent* aContent, bool aFinished) :
159 0 : mContent(aContent), mFinished(aFinished)
160 : {
161 0 : }
162 :
163 0 : NS_IMETHOD Run()
164 : {
165 0 : nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent,
166 0 : mFinished ? NS_LITERAL_STRING("MozPaintWaitFinished") : NS_LITERAL_STRING("MozPaintWait"),
167 0 : true, true);
168 0 : return NS_OK;
169 : }
170 :
171 : private:
172 : nsCOMPtr<nsIContent> mContent;
173 : bool mFinished;
174 : };
175 :
176 : void
177 0 : nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
178 : {
179 : // This is notification for reftests about async plugin paint start
180 0 : if (!mWaitingForPaint && !IsUpToDate() && aBuilder->ShouldSyncDecodeImages()) {
181 0 : nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, false);
182 : // Run this event as soon as it's safe to do so, since listeners need to
183 : // receive it immediately
184 0 : mWaitingForPaint = nsContentUtils::AddScriptRunner(event);
185 : }
186 0 : }
187 :
188 : #ifdef XP_MACOSX
189 : static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
190 : {
191 : nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
192 : if (frame) {
193 : frame->UpdateImageLayer(gfxRect(0,0,0,0));
194 : }
195 : }
196 :
197 : static void OnDestroyImage(void* aPluginInstanceOwner)
198 : {
199 : nsPluginInstanceOwner* owner = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner);
200 : NS_IF_RELEASE(owner);
201 : }
202 : #endif // XP_MACOSX
203 :
204 : already_AddRefed<ImageContainer>
205 0 : nsPluginInstanceOwner::GetImageContainer()
206 : {
207 0 : if (mInstance) {
208 0 : nsRefPtr<ImageContainer> container;
209 : // Every call to nsIPluginInstance::GetImage() creates
210 : // a new image. See nsIPluginInstance.idl.
211 0 : mInstance->GetImageContainer(getter_AddRefs(container));
212 0 : if (container) {
213 : #ifdef XP_MACOSX
214 : AutoLockImage autoLock(container);
215 : Image* image = autoLock.GetImage();
216 : if (image && image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
217 : MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
218 : NS_ADDREF_THIS();
219 : oglImage->SetUpdateCallback(&DrawPlugin, this);
220 : oglImage->SetDestroyCallback(&OnDestroyImage);
221 : }
222 : #endif
223 0 : return container.forget();
224 : }
225 : }
226 0 : return nsnull;
227 : }
228 :
229 : void
230 0 : nsPluginInstanceOwner::SetBackgroundUnknown()
231 : {
232 0 : if (mInstance) {
233 0 : mInstance->SetBackgroundUnknown();
234 : }
235 0 : }
236 :
237 : already_AddRefed<gfxContext>
238 0 : nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
239 : {
240 0 : nsIntRect rect = aRect;
241 0 : nsRefPtr<gfxContext> ctx;
242 0 : if (mInstance &&
243 0 : NS_SUCCEEDED(mInstance->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) {
244 0 : return ctx.forget();
245 : }
246 0 : return nsnull;
247 : }
248 :
249 : void
250 0 : nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext,
251 : const nsIntRect& aRect)
252 : {
253 0 : nsIntRect rect = aRect;
254 0 : if (mInstance) {
255 0 : mInstance->EndUpdateBackground(aContext, &rect);
256 : }
257 0 : }
258 :
259 : bool
260 0 : nsPluginInstanceOwner::UseAsyncRendering()
261 : {
262 : #ifdef XP_MACOSX
263 : if (mUseAsyncRendering) {
264 : return true;
265 : }
266 : #endif
267 :
268 : bool useAsyncRendering;
269 : bool result = (mInstance &&
270 0 : NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
271 : useAsyncRendering
272 : #ifndef XP_MACOSX
273 0 : && (!mPluginWindow ||
274 : mPluginWindow->type == NPWindowTypeDrawable)
275 : #endif
276 0 : );
277 :
278 : #ifdef XP_MACOSX
279 : if (result) {
280 : mUseAsyncRendering = true;
281 : }
282 : #endif
283 :
284 0 : return result;
285 : }
286 :
287 : nsIntSize
288 0 : nsPluginInstanceOwner::GetCurrentImageSize()
289 : {
290 0 : nsIntSize size(0,0);
291 0 : if (mInstance) {
292 0 : mInstance->GetImageSize(&size);
293 : }
294 : return size;
295 : }
296 :
297 0 : nsPluginInstanceOwner::nsPluginInstanceOwner()
298 : {
299 : // create nsPluginNativeWindow object, it is derived from NPWindow
300 : // struct and allows to manipulate native window procedure
301 0 : nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
302 0 : mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
303 0 : if (mPluginHost)
304 0 : mPluginHost->NewPluginNativeWindow(&mPluginWindow);
305 : else
306 0 : mPluginWindow = nsnull;
307 :
308 0 : mObjectFrame = nsnull;
309 0 : mContent = nsnull;
310 0 : mTagText = nsnull;
311 0 : mWidgetCreationComplete = false;
312 : #ifdef XP_MACOSX
313 : memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
314 : #ifndef NP_NO_QUICKDRAW
315 : memset(&mQDPluginPortCopy, 0, sizeof(NP_Port));
316 : #endif
317 : mInCGPaintLevel = 0;
318 : mSentInitialTopLevelWindowEvent = false;
319 : mColorProfile = nsnull;
320 : mPluginPortChanged = false;
321 : #endif
322 0 : mContentFocused = false;
323 0 : mWidgetVisible = true;
324 0 : mPluginWindowVisible = false;
325 0 : mPluginDocumentActiveState = true;
326 0 : mNumCachedAttrs = 0;
327 0 : mNumCachedParams = 0;
328 0 : mCachedAttrParamNames = nsnull;
329 0 : mCachedAttrParamValues = nsnull;
330 :
331 : #ifdef XP_MACOSX
332 : #ifndef NP_NO_QUICKDRAW
333 : mEventModel = NPEventModelCarbon;
334 : #else
335 : mEventModel = NPEventModelCocoa;
336 : #endif
337 : mUseAsyncRendering = false;
338 : #endif
339 :
340 0 : mWaitingForPaint = false;
341 :
342 : #ifdef MOZ_WIDGET_ANDROID
343 : mInverted = false;
344 : mLayer = nsnull;
345 : #endif
346 0 : }
347 :
348 0 : nsPluginInstanceOwner::~nsPluginInstanceOwner()
349 : {
350 : PRInt32 cnt;
351 :
352 0 : if (mWaitingForPaint) {
353 : // We don't care when the event is dispatched as long as it's "soon",
354 : // since whoever needs it will be waiting for it.
355 0 : nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
356 0 : NS_DispatchToMainThread(event);
357 : }
358 :
359 : #ifdef MAC_CARBON_PLUGINS
360 : CancelTimer();
361 : #endif
362 :
363 0 : mObjectFrame = nsnull;
364 :
365 0 : for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
366 0 : if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) {
367 0 : NS_Free(mCachedAttrParamNames[cnt]);
368 0 : mCachedAttrParamNames[cnt] = nsnull;
369 : }
370 :
371 0 : if (mCachedAttrParamValues && mCachedAttrParamValues[cnt]) {
372 0 : NS_Free(mCachedAttrParamValues[cnt]);
373 0 : mCachedAttrParamValues[cnt] = nsnull;
374 : }
375 : }
376 :
377 0 : if (mCachedAttrParamNames) {
378 0 : NS_Free(mCachedAttrParamNames);
379 0 : mCachedAttrParamNames = nsnull;
380 : }
381 :
382 0 : if (mCachedAttrParamValues) {
383 0 : NS_Free(mCachedAttrParamValues);
384 0 : mCachedAttrParamValues = nsnull;
385 : }
386 :
387 0 : if (mTagText) {
388 0 : NS_Free(mTagText);
389 0 : mTagText = nsnull;
390 : }
391 :
392 0 : PLUG_DeletePluginNativeWindow(mPluginWindow);
393 0 : mPluginWindow = nsnull;
394 :
395 : #ifdef MOZ_WIDGET_ANDROID
396 : RemovePluginView();
397 : #endif
398 :
399 0 : if (mInstance) {
400 0 : mInstance->InvalidateOwner();
401 : }
402 0 : }
403 :
404 0 : NS_IMPL_ISUPPORTS3(nsPluginInstanceOwner,
405 : nsIPluginInstanceOwner,
406 : nsIPluginTagInfo,
407 : nsIDOMEventListener)
408 :
409 : nsresult
410 0 : nsPluginInstanceOwner::SetInstance(nsNPAPIPluginInstance *aInstance)
411 : {
412 0 : NS_ASSERTION(!mInstance || !aInstance, "mInstance should only be set or unset!");
413 :
414 : // If we're going to null out mInstance after use, be sure to call
415 : // mInstance->InvalidateOwner() here, since it now won't be called
416 : // from our destructor. This fixes bug 613376.
417 0 : if (mInstance && !aInstance)
418 0 : mInstance->InvalidateOwner();
419 :
420 0 : mInstance = aInstance;
421 :
422 0 : return NS_OK;
423 : }
424 :
425 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetWindow(NPWindow *&aWindow)
426 : {
427 0 : NS_ASSERTION(mPluginWindow, "the plugin window object being returned is null");
428 0 : aWindow = mPluginWindow;
429 0 : return NS_OK;
430 : }
431 :
432 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetMode(PRInt32 *aMode)
433 : {
434 0 : nsCOMPtr<nsIDocument> doc;
435 0 : nsresult rv = GetDocument(getter_AddRefs(doc));
436 0 : nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
437 :
438 0 : if (pDoc) {
439 0 : *aMode = NP_FULL;
440 : } else {
441 0 : *aMode = NP_EMBED;
442 : }
443 :
444 0 : return rv;
445 : }
446 :
447 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(PRUint16& n,
448 : const char*const*& names,
449 : const char*const*& values)
450 : {
451 0 : nsresult rv = EnsureCachedAttrParamArrays();
452 0 : NS_ENSURE_SUCCESS(rv, rv);
453 :
454 0 : n = mNumCachedAttrs;
455 0 : names = (const char **)mCachedAttrParamNames;
456 0 : values = (const char **)mCachedAttrParamValues;
457 :
458 0 : return rv;
459 : }
460 :
461 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char* *result)
462 : {
463 0 : NS_ENSURE_ARG_POINTER(name);
464 0 : NS_ENSURE_ARG_POINTER(result);
465 :
466 0 : nsresult rv = EnsureCachedAttrParamArrays();
467 0 : NS_ENSURE_SUCCESS(rv, rv);
468 :
469 0 : *result = nsnull;
470 :
471 0 : for (int i = 0; i < mNumCachedAttrs; i++) {
472 0 : if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
473 0 : *result = mCachedAttrParamValues[i];
474 0 : return NS_OK;
475 : }
476 : }
477 :
478 0 : return NS_ERROR_FAILURE;
479 : }
480 :
481 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetDOMElement(nsIDOMElement* *result)
482 : {
483 0 : return CallQueryInterface(mContent, result);
484 : }
485 :
486 0 : nsresult nsPluginInstanceOwner::GetInstance(nsNPAPIPluginInstance **aInstance)
487 : {
488 0 : NS_ENSURE_ARG_POINTER(aInstance);
489 :
490 0 : *aInstance = mInstance;
491 0 : NS_IF_ADDREF(*aInstance);
492 0 : return NS_OK;
493 : }
494 :
495 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
496 : const char *aTarget,
497 : nsIInputStream *aPostStream,
498 : void *aHeadersData,
499 : PRUint32 aHeadersDataLen)
500 : {
501 0 : NS_ENSURE_TRUE(mContent, NS_ERROR_NULL_POINTER);
502 :
503 0 : if (mContent->IsEditable()) {
504 0 : return NS_OK;
505 : }
506 :
507 0 : nsIDocument *doc = mContent->GetCurrentDoc();
508 0 : if (!doc) {
509 0 : return NS_ERROR_FAILURE;
510 : }
511 :
512 0 : nsIPresShell *presShell = doc->GetShell();
513 0 : if (!presShell) {
514 0 : return NS_ERROR_FAILURE;
515 : }
516 :
517 0 : nsPresContext *presContext = presShell->GetPresContext();
518 0 : if (!presContext) {
519 0 : return NS_ERROR_FAILURE;
520 : }
521 :
522 : // the container of the pres context will give us the link handler
523 0 : nsCOMPtr<nsISupports> container = presContext->GetContainer();
524 0 : NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);
525 0 : nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
526 0 : NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE);
527 :
528 0 : nsAutoString unitarget;
529 0 : unitarget.AssignASCII(aTarget); // XXX could this be nonascii?
530 :
531 0 : nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
532 :
533 : // Create an absolute URL
534 0 : nsCOMPtr<nsIURI> uri;
535 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
536 :
537 0 : NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
538 :
539 0 : nsCOMPtr<nsIInputStream> headersDataStream;
540 0 : if (aPostStream && aHeadersData) {
541 0 : if (!aHeadersDataLen)
542 0 : return NS_ERROR_UNEXPECTED;
543 :
544 0 : nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1");
545 0 : if (!sis)
546 0 : return NS_ERROR_OUT_OF_MEMORY;
547 :
548 0 : rv = sis->SetData((char *)aHeadersData, aHeadersDataLen);
549 0 : NS_ENSURE_SUCCESS(rv, rv);
550 0 : headersDataStream = do_QueryInterface(sis);
551 : }
552 :
553 : PRInt32 blockPopups =
554 0 : Preferences::GetInt("privacy.popups.disable_from_plugins");
555 0 : nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
556 :
557 0 : rv = lh->OnLinkClick(mContent, uri, unitarget.get(),
558 0 : aPostStream, headersDataStream, true);
559 :
560 0 : return rv;
561 : }
562 :
563 0 : NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg)
564 : {
565 0 : nsresult rv = NS_ERROR_FAILURE;
566 :
567 0 : rv = this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg).get());
568 :
569 0 : return rv;
570 : }
571 :
572 0 : NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const PRUnichar *aStatusMsg)
573 : {
574 0 : nsresult rv = NS_ERROR_FAILURE;
575 :
576 0 : if (!mObjectFrame) {
577 0 : return rv;
578 : }
579 0 : nsCOMPtr<nsISupports> cont = mObjectFrame->PresContext()->GetContainer();
580 0 : if (!cont) {
581 0 : return NS_OK;
582 : }
583 :
584 0 : nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(cont, &rv));
585 0 : if (NS_FAILED(rv) || !docShellItem) {
586 0 : return rv;
587 : }
588 :
589 0 : nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
590 0 : rv = docShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
591 0 : if (NS_FAILED(rv) || !treeOwner) {
592 0 : return rv;
593 : }
594 :
595 0 : nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner, &rv));
596 0 : if (NS_FAILED(rv) || !browserChrome) {
597 0 : return rv;
598 : }
599 0 : rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
600 0 : aStatusMsg);
601 :
602 0 : return rv;
603 : }
604 :
605 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetDocument(nsIDocument* *aDocument)
606 : {
607 0 : if (!aDocument)
608 0 : return NS_ERROR_NULL_POINTER;
609 :
610 : // XXX sXBL/XBL2 issue: current doc or owner doc?
611 : // But keep in mind bug 322414 comment 33
612 0 : NS_IF_ADDREF(*aDocument = mContent->OwnerDoc());
613 0 : return NS_OK;
614 : }
615 :
616 0 : NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
617 : {
618 : // If our object frame has gone away, we won't be able to determine
619 : // up-to-date-ness, so just fire off the event.
620 0 : if (mWaitingForPaint && (!mObjectFrame || IsUpToDate())) {
621 : // We don't care when the event is dispatched as long as it's "soon",
622 : // since whoever needs it will be waiting for it.
623 0 : nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
624 0 : NS_DispatchToMainThread(event);
625 0 : mWaitingForPaint = false;
626 : }
627 :
628 0 : if (!mObjectFrame || !invalidRect || !mWidgetVisible)
629 0 : return NS_ERROR_FAILURE;
630 :
631 : // Each time an asynchronously-drawing plugin sends a new surface to display,
632 : // InvalidateRect is called. We notify reftests that painting is up to
633 : // date and update our ImageContainer with the new surface.
634 0 : nsRefPtr<ImageContainer> container;
635 0 : mInstance->GetImageContainer(getter_AddRefs(container));
636 0 : gfxIntSize oldSize(0, 0);
637 :
638 : #ifndef XP_MACOSX
639 : // Windowed plugins should not be calling NPN_InvalidateRect, but
640 : // Silverlight does and expects it to "work"
641 0 : if (mWidget) {
642 0 : mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
643 : invalidRect->right - invalidRect->left,
644 0 : invalidRect->bottom - invalidRect->top));
645 0 : return NS_OK;
646 : }
647 : #endif
648 :
649 0 : nsPresContext* presContext = mObjectFrame->PresContext();
650 : nsRect rect(presContext->DevPixelsToAppUnits(invalidRect->left),
651 : presContext->DevPixelsToAppUnits(invalidRect->top),
652 : presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left),
653 0 : presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top));
654 0 : if (container) {
655 0 : gfxIntSize newSize = container->GetCurrentSize();
656 0 : if (newSize != oldSize) {
657 : // The image size has changed - invalidate the old area too, bug 635405.
658 : nsRect oldRect = nsRect(0, 0,
659 : presContext->DevPixelsToAppUnits(oldSize.width),
660 0 : presContext->DevPixelsToAppUnits(oldSize.height));
661 0 : rect.UnionRect(rect, oldRect);
662 : }
663 : }
664 0 : rect.MoveBy(mObjectFrame->GetContentRectRelativeToSelf().TopLeft());
665 0 : mObjectFrame->InvalidateLayer(rect, nsDisplayItem::TYPE_PLUGIN);
666 0 : return NS_OK;
667 : }
668 :
669 0 : NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
670 : {
671 0 : return NS_ERROR_NOT_IMPLEMENTED;
672 : }
673 :
674 : NS_IMETHODIMP
675 0 : nsPluginInstanceOwner::RedrawPlugin()
676 : {
677 0 : if (mObjectFrame) {
678 0 : mObjectFrame->InvalidateLayer(mObjectFrame->GetContentRectRelativeToSelf(), nsDisplayItem::TYPE_PLUGIN);
679 : }
680 0 : return NS_OK;
681 : }
682 :
683 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
684 : {
685 0 : if (!mObjectFrame) {
686 0 : NS_WARNING("plugin owner has no owner in getting doc's window handle");
687 0 : return NS_ERROR_FAILURE;
688 : }
689 :
690 : #if defined(XP_WIN) || defined(XP_OS2)
691 : void** pvalue = (void**)value;
692 : nsIViewManager* vm = mObjectFrame->PresContext()->GetPresShell()->GetViewManager();
693 : if (!vm)
694 : return NS_ERROR_FAILURE;
695 : #if defined(XP_WIN)
696 : // This property is provided to allow a "windowless" plugin to determine the window it is drawing
697 : // in, so it can translate mouse coordinates it receives directly from the operating system
698 : // to coordinates relative to itself.
699 :
700 : // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
701 : // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc
702 :
703 : // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
704 : // determines the window handle of the mozilla window containing the "windowless" plugin.
705 :
706 : // Given that this HWND may not be that of the document's window, there is a slight risk
707 : // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
708 : // does not suggest this HWND IS that of the document window, rather that of the window
709 : // the plugin is drawn in, this seems like a safe fix.
710 :
711 : // we only attempt to get the nearest window if this really is a "windowless" plugin so as not
712 : // to change any behaviour for the much more common windowed plugins,
713 : // though why this method would even be being called for a windowed plugin escapes me.
714 : if (mPluginWindow && mPluginWindow->type == NPWindowTypeDrawable) {
715 : // it turns out that flash also uses this window for determining focus, and is currently
716 : // unable to show a caret correctly if we return the enclosing window. Therefore for
717 : // now we only return the enclosing window when there is an actual offset which
718 : // would otherwise cause coordinates to be offset incorrectly. (i.e.
719 : // if the enclosing window if offset from the document window)
720 : //
721 : // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
722 : // does not seem to be possible without a change to the flash plugin
723 :
724 : nsIWidget* win = mObjectFrame->GetNearestWidget();
725 : if (win) {
726 : nsIView *view = nsIView::GetViewFor(win);
727 : NS_ASSERTION(view, "No view for widget");
728 : nsPoint offset = view->GetOffsetTo(nsnull);
729 :
730 : if (offset.x || offset.y) {
731 : // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
732 : // so that mouse co-ordinates are not messed up.
733 : *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW);
734 : if (*pvalue)
735 : return NS_OK;
736 : }
737 : }
738 : }
739 : #endif
740 : // simply return the topmost document window
741 : nsCOMPtr<nsIWidget> widget;
742 : nsresult rv = vm->GetRootWidget(getter_AddRefs(widget));
743 : if (widget) {
744 : *pvalue = (void*)widget->GetNativeData(NS_NATIVE_WINDOW);
745 : } else {
746 : NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle");
747 : }
748 :
749 : return rv;
750 : #elif defined(MOZ_WIDGET_GTK2) || defined(MOZ_WIDGET_QT)
751 : // X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
752 0 : nsIWidget* win = mObjectFrame->GetNearestWidget();
753 0 : if (!win)
754 0 : return NS_ERROR_FAILURE;
755 0 : *static_cast<Window*>(value) = (long unsigned int)win->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW);
756 0 : return NS_OK;
757 : #else
758 : return NS_ERROR_NOT_IMPLEMENTED;
759 : #endif
760 : }
761 :
762 0 : NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(PRInt32 eventModel)
763 : {
764 : #ifdef XP_MACOSX
765 : mEventModel = static_cast<NPEventModel>(eventModel);
766 : return NS_OK;
767 : #else
768 0 : return NS_ERROR_NOT_IMPLEMENTED;
769 : #endif
770 : }
771 :
772 0 : NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
773 : {
774 0 : if (!menu || !event)
775 0 : return NPERR_GENERIC_ERROR;
776 :
777 : #ifdef XP_MACOSX
778 : if (GetEventModel() != NPEventModelCocoa)
779 : return NPERR_INCOMPATIBLE_VERSION_ERROR;
780 :
781 : return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu), mWidget,
782 : static_cast<NPCocoaEvent*>(event));
783 : #else
784 0 : return NPERR_INCOMPATIBLE_VERSION_ERROR;
785 : #endif
786 : }
787 :
788 0 : NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
789 : double *destX, double *destY, NPCoordinateSpace destSpace)
790 : {
791 : #ifdef XP_MACOSX
792 : if (!mWidget)
793 : return false;
794 :
795 : return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET),
796 : sourceX, sourceY, sourceSpace, destX, destY, destSpace);
797 : #else
798 : // we should implement this for all platforms
799 0 : return false;
800 : #endif
801 : }
802 :
803 0 : NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format,
804 : void *initData, NPAsyncSurface *surface)
805 : {
806 0 : return NPERR_INCOMPATIBLE_VERSION_ERROR;
807 : }
808 :
809 0 : NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *)
810 : {
811 0 : return NPERR_INCOMPATIBLE_VERSION_ERROR;
812 : }
813 :
814 0 : void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*)
815 : {
816 0 : }
817 :
818 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
819 : {
820 0 : NS_ENSURE_ARG_POINTER(result);
821 :
822 0 : *result = nsPluginTagType_Unknown;
823 :
824 0 : nsIAtom *atom = mContent->Tag();
825 :
826 0 : if (atom == nsGkAtoms::applet)
827 0 : *result = nsPluginTagType_Applet;
828 0 : else if (atom == nsGkAtoms::embed)
829 0 : *result = nsPluginTagType_Embed;
830 0 : else if (atom == nsGkAtoms::object)
831 0 : *result = nsPluginTagType_Object;
832 :
833 0 : return NS_OK;
834 : }
835 :
836 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetTagText(const char* *result)
837 : {
838 0 : NS_ENSURE_ARG_POINTER(result);
839 0 : if (nsnull == mTagText) {
840 : nsresult rv;
841 0 : nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent, &rv));
842 0 : if (NS_FAILED(rv))
843 0 : return rv;
844 :
845 0 : nsCOMPtr<nsIDocument> document;
846 0 : rv = GetDocument(getter_AddRefs(document));
847 0 : if (NS_FAILED(rv))
848 0 : return rv;
849 :
850 0 : nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
851 0 : NS_ASSERTION(domDoc, "Need a document");
852 :
853 0 : nsCOMPtr<nsIDocumentEncoder> docEncoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html", &rv));
854 0 : if (NS_FAILED(rv))
855 0 : return rv;
856 0 : rv = docEncoder->Init(domDoc, NS_LITERAL_STRING("text/html"), nsIDocumentEncoder::OutputEncodeBasicEntities);
857 0 : if (NS_FAILED(rv))
858 0 : return rv;
859 :
860 0 : nsRefPtr<nsRange> range = new nsRange();
861 0 : rv = range->SelectNode(node);
862 0 : if (NS_FAILED(rv))
863 0 : return rv;
864 :
865 0 : docEncoder->SetRange(range);
866 0 : nsString elementHTML;
867 0 : rv = docEncoder->EncodeToString(elementHTML);
868 0 : if (NS_FAILED(rv))
869 0 : return rv;
870 :
871 0 : mTagText = ToNewUTF8String(elementHTML);
872 0 : if (!mTagText)
873 0 : return NS_ERROR_OUT_OF_MEMORY;
874 : }
875 0 : *result = mTagText;
876 0 : return NS_OK;
877 : }
878 :
879 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(PRUint16& n, const char*const*& names, const char*const*& values)
880 : {
881 0 : nsresult rv = EnsureCachedAttrParamArrays();
882 0 : NS_ENSURE_SUCCESS(rv, rv);
883 :
884 0 : n = mNumCachedParams;
885 0 : if (n) {
886 0 : names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
887 0 : values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
888 : } else
889 0 : names = values = nsnull;
890 :
891 0 : return rv;
892 : }
893 :
894 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char* *result)
895 : {
896 0 : NS_ENSURE_ARG_POINTER(name);
897 0 : NS_ENSURE_ARG_POINTER(result);
898 :
899 0 : nsresult rv = EnsureCachedAttrParamArrays();
900 0 : NS_ENSURE_SUCCESS(rv, rv);
901 :
902 0 : *result = nsnull;
903 :
904 0 : for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
905 0 : if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
906 0 : *result = mCachedAttrParamValues[i];
907 0 : return NS_OK;
908 : }
909 : }
910 :
911 0 : return NS_ERROR_FAILURE;
912 : }
913 :
914 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentBase(const char* *result)
915 : {
916 0 : NS_ENSURE_ARG_POINTER(result);
917 0 : nsresult rv = NS_OK;
918 0 : if (mDocumentBase.IsEmpty()) {
919 0 : if (!mObjectFrame) {
920 0 : *result = nsnull;
921 0 : return NS_ERROR_FAILURE;
922 : }
923 :
924 0 : nsIDocument* doc = mContent->OwnerDoc();
925 0 : NS_ASSERTION(doc, "Must have an owner doc");
926 0 : rv = doc->GetDocBaseURI()->GetSpec(mDocumentBase);
927 : }
928 0 : if (NS_SUCCEEDED(rv))
929 0 : *result = ToNewCString(mDocumentBase);
930 0 : return rv;
931 : }
932 :
933 : static nsDataHashtable<nsDepCharHashKey, const char *> * gCharsetMap;
934 : typedef struct {
935 : char mozName[16];
936 : char javaName[12];
937 : } moz2javaCharset;
938 :
939 : /* XXX If you add any strings longer than
940 : * {"x-mac-cyrillic", "MacCyrillic"},
941 : * {"x-mac-ukrainian", "MacUkraine"},
942 : * to the following array then you MUST update the
943 : * sizes of the arrays in the moz2javaCharset struct
944 : */
945 :
946 : static const moz2javaCharset charsets[] =
947 : {
948 : {"windows-1252", "Cp1252"},
949 : {"IBM850", "Cp850"},
950 : {"IBM852", "Cp852"},
951 : {"IBM855", "Cp855"},
952 : {"IBM857", "Cp857"},
953 : {"IBM828", "Cp862"},
954 : {"IBM864", "Cp864"},
955 : {"IBM866", "Cp866"},
956 : {"windows-1250", "Cp1250"},
957 : {"windows-1251", "Cp1251"},
958 : {"windows-1253", "Cp1253"},
959 : {"windows-1254", "Cp1254"},
960 : {"windows-1255", "Cp1255"},
961 : {"windows-1256", "Cp1256"},
962 : {"windows-1257", "Cp1257"},
963 : {"windows-1258", "Cp1258"},
964 : {"EUC-JP", "EUC_JP"},
965 : {"EUC-KR", "EUC_KR"},
966 : {"x-euc-tw", "EUC_TW"},
967 : {"gb18030", "GB18030"},
968 : {"gbk", "GBK"},
969 : {"ISO-2022-JP", "ISO2022JP"},
970 : {"ISO-2022-KR", "ISO2022KR"},
971 : {"ISO-8859-2", "ISO8859_2"},
972 : {"ISO-8859-3", "ISO8859_3"},
973 : {"ISO-8859-4", "ISO8859_4"},
974 : {"ISO-8859-5", "ISO8859_5"},
975 : {"ISO-8859-6", "ISO8859_6"},
976 : {"ISO-8859-7", "ISO8859_7"},
977 : {"ISO-8859-8", "ISO8859_8"},
978 : {"ISO-8859-9", "ISO8859_9"},
979 : {"ISO-8859-13", "ISO8859_13"},
980 : {"x-johab", "Johab"},
981 : {"KOI8-R", "KOI8_R"},
982 : {"TIS-620", "MS874"},
983 : {"x-windows-949", "MS949"},
984 : {"x-mac-arabic", "MacArabic"},
985 : {"x-mac-croatian", "MacCroatia"},
986 : {"x-mac-cyrillic", "MacCyrillic"},
987 : {"x-mac-greek", "MacGreek"},
988 : {"x-mac-hebrew", "MacHebrew"},
989 : {"x-mac-icelandic", "MacIceland"},
990 : {"x-mac-roman", "MacRoman"},
991 : {"x-mac-romanian", "MacRomania"},
992 : {"x-mac-ukrainian", "MacUkraine"},
993 : {"Shift_JIS", "SJIS"},
994 : {"TIS-620", "TIS620"}
995 : };
996 :
997 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentEncoding(const char* *result)
998 : {
999 0 : NS_ENSURE_ARG_POINTER(result);
1000 0 : *result = nsnull;
1001 :
1002 : nsresult rv;
1003 : // XXX sXBL/XBL2 issue: current doc or owner doc?
1004 0 : nsCOMPtr<nsIDocument> doc;
1005 0 : rv = GetDocument(getter_AddRefs(doc));
1006 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get document");
1007 0 : if (NS_FAILED(rv))
1008 0 : return rv;
1009 :
1010 0 : const nsCString &charset = doc->GetDocumentCharacterSet();
1011 :
1012 0 : if (charset.IsEmpty())
1013 0 : return NS_OK;
1014 :
1015 : // common charsets and those not requiring conversion first
1016 0 : if (charset.EqualsLiteral("us-ascii")) {
1017 0 : *result = PL_strdup("US_ASCII");
1018 0 : } else if (charset.EqualsLiteral("ISO-8859-1") ||
1019 0 : !nsCRT::strncmp(PromiseFlatCString(charset).get(), "UTF", 3)) {
1020 0 : *result = ToNewCString(charset);
1021 : } else {
1022 0 : if (!gCharsetMap) {
1023 0 : const int NUM_CHARSETS = sizeof(charsets) / sizeof(moz2javaCharset);
1024 0 : gCharsetMap = new nsDataHashtable<nsDepCharHashKey, const char*>();
1025 0 : if (!gCharsetMap || !gCharsetMap->Init(NUM_CHARSETS))
1026 0 : return NS_ERROR_OUT_OF_MEMORY;
1027 :
1028 0 : for (PRUint16 i = 0; i < NUM_CHARSETS; i++) {
1029 0 : gCharsetMap->Put(charsets[i].mozName, charsets[i].javaName);
1030 : }
1031 : }
1032 : // if found mapping, return it; otherwise return original charset
1033 : const char *mapping;
1034 0 : *result = gCharsetMap->Get(charset.get(), &mapping) ? PL_strdup(mapping) :
1035 0 : ToNewCString(charset);
1036 : }
1037 :
1038 0 : return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1039 : }
1040 :
1041 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetAlignment(const char* *result)
1042 : {
1043 0 : return GetAttribute("ALIGN", result);
1044 : }
1045 :
1046 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetWidth(PRUint32 *result)
1047 : {
1048 0 : NS_ENSURE_ARG_POINTER(result);
1049 :
1050 0 : NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
1051 :
1052 0 : *result = mPluginWindow->width;
1053 :
1054 0 : return NS_OK;
1055 : }
1056 :
1057 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetHeight(PRUint32 *result)
1058 : {
1059 0 : NS_ENSURE_ARG_POINTER(result);
1060 :
1061 0 : NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
1062 :
1063 0 : *result = mPluginWindow->height;
1064 :
1065 0 : return NS_OK;
1066 : }
1067 :
1068 :
1069 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetBorderVertSpace(PRUint32 *result)
1070 : {
1071 : nsresult rv;
1072 : const char *vspace;
1073 :
1074 0 : rv = GetAttribute("VSPACE", &vspace);
1075 :
1076 0 : if (NS_OK == rv) {
1077 0 : if (*result != 0)
1078 0 : *result = (PRUint32)atol(vspace);
1079 : else
1080 0 : *result = 0;
1081 : }
1082 : else
1083 0 : *result = 0;
1084 :
1085 0 : return rv;
1086 : }
1087 :
1088 0 : NS_IMETHODIMP nsPluginInstanceOwner::GetBorderHorizSpace(PRUint32 *result)
1089 : {
1090 : nsresult rv;
1091 : const char *hspace;
1092 :
1093 0 : rv = GetAttribute("HSPACE", &hspace);
1094 :
1095 0 : if (NS_OK == rv) {
1096 0 : if (*result != 0)
1097 0 : *result = (PRUint32)atol(hspace);
1098 : else
1099 0 : *result = 0;
1100 : }
1101 : else
1102 0 : *result = 0;
1103 :
1104 0 : return rv;
1105 : }
1106 :
1107 : // Cache the attributes and/or parameters of our tag into a single set
1108 : // of arrays to be compatible with Netscape 4.x. The attributes go first,
1109 : // followed by a PARAM/null and then any PARAM tags. Also, hold the
1110 : // cached array around for the duration of the life of the instance
1111 : // because Netscape 4.x did. See bug 111008.
1112 0 : nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
1113 : {
1114 0 : if (mCachedAttrParamValues)
1115 0 : return NS_OK;
1116 :
1117 0 : NS_PRECONDITION(((mNumCachedAttrs + mNumCachedParams) == 0) &&
1118 : !mCachedAttrParamNames,
1119 : "re-cache of attrs/params not implemented! use the DOM "
1120 : "node directy instead");
1121 :
1122 : // Convert to a 16-bit count. Subtract 2 in case we add an extra
1123 : // "src" or "wmode" entry below.
1124 0 : PRUint32 cattrs = mContent->GetAttrCount();
1125 0 : if (cattrs < 0x0000FFFD) {
1126 0 : mNumCachedAttrs = static_cast<PRUint16>(cattrs);
1127 : } else {
1128 0 : mNumCachedAttrs = 0xFFFD;
1129 : }
1130 :
1131 : // now, we need to find all the PARAM tags that are children of us
1132 : // however, be careful not to include any PARAMs that don't have us
1133 : // as a direct parent. For nested object (or applet) tags, be sure
1134 : // to only round up the param tags that coorespond with THIS
1135 : // instance. And also, weed out any bogus tags that may get in the
1136 : // way, see bug 39609. Then, with any param tag that meet our
1137 : // qualification, temporarly cache them in an nsCOMArray until
1138 : // we can figure out what size to make our fixed char* array.
1139 0 : nsCOMArray<nsIDOMElement> ourParams;
1140 :
1141 : // Get all dependent PARAM tags, even if they are not direct children.
1142 0 : nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent);
1143 0 : NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
1144 :
1145 : // Making DOM method calls can cause our frame to go away.
1146 0 : nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this);
1147 :
1148 0 : nsCOMPtr<nsIDOMNodeList> allParams;
1149 0 : NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
1150 0 : mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
1151 0 : getter_AddRefs(allParams));
1152 0 : if (allParams) {
1153 : PRUint32 numAllParams;
1154 0 : allParams->GetLength(&numAllParams);
1155 0 : for (PRUint32 i = 0; i < numAllParams; i++) {
1156 0 : nsCOMPtr<nsIDOMNode> pnode;
1157 0 : allParams->Item(i, getter_AddRefs(pnode));
1158 0 : nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
1159 0 : if (domelement) {
1160 : // Ignore params without a name attribute.
1161 0 : nsAutoString name;
1162 0 : domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
1163 0 : if (!name.IsEmpty()) {
1164 : // Find the first object or applet parent.
1165 0 : nsCOMPtr<nsIDOMNode> parent;
1166 0 : nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
1167 0 : nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
1168 0 : pnode->GetParentNode(getter_AddRefs(parent));
1169 0 : while (!(domobject || domapplet) && parent) {
1170 0 : domobject = do_QueryInterface(parent);
1171 0 : domapplet = do_QueryInterface(parent);
1172 0 : nsCOMPtr<nsIDOMNode> temp;
1173 0 : parent->GetParentNode(getter_AddRefs(temp));
1174 0 : parent = temp;
1175 : }
1176 0 : if (domapplet || domobject) {
1177 0 : if (domapplet) {
1178 0 : parent = domapplet;
1179 : }
1180 : else {
1181 0 : parent = domobject;
1182 : }
1183 0 : nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
1184 0 : if (parent == mydomNode) {
1185 0 : ourParams.AppendObject(domelement);
1186 : }
1187 : }
1188 : }
1189 : }
1190 : }
1191 : }
1192 :
1193 : // Convert to a 16-bit count.
1194 0 : PRUint32 cparams = ourParams.Count();
1195 0 : if (cparams < 0x0000FFFF) {
1196 0 : mNumCachedParams = static_cast<PRUint16>(cparams);
1197 : } else {
1198 0 : mNumCachedParams = 0xFFFF;
1199 : }
1200 :
1201 0 : PRUint16 numRealAttrs = mNumCachedAttrs;
1202 :
1203 : // Some plugins were never written to understand the "data" attribute of the OBJECT tag.
1204 : // Real and WMP will not play unless they find a "src" attribute, see bug 152334.
1205 : // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
1206 : // look for "data", lets instead copy the "data" attribute and add another entry
1207 : // to the bottom of the array if there isn't already a "src" specified.
1208 0 : nsAutoString data;
1209 0 : if (mContent->Tag() == nsGkAtoms::object &&
1210 0 : !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
1211 0 : mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, data) &&
1212 0 : !data.IsEmpty()) {
1213 0 : mNumCachedAttrs++;
1214 : }
1215 :
1216 : // "plugins.force.wmode" preference is forcing wmode type for plugins
1217 : // possible values - "opaque", "transparent", "windowed"
1218 0 : nsAdoptingCString wmodeType = Preferences::GetCString("plugins.force.wmode");
1219 0 : if (!wmodeType.IsEmpty()) {
1220 0 : mNumCachedAttrs++;
1221 : }
1222 :
1223 0 : mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
1224 0 : NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
1225 0 : mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
1226 0 : NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
1227 :
1228 : // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
1229 : // attribute order. So we want to make sure we give the plugin the
1230 : // attributes in the order they came in in the source, to be compatible with
1231 : // other browsers. Now in HTML, the storage order is the reverse of the
1232 : // source order, while in XML and XHTML it's the same as the source order
1233 : // (see the AddAttributes functions in the HTML and XML content sinks).
1234 : PRInt32 start, end, increment;
1235 0 : if (mContent->IsHTML() &&
1236 0 : mContent->IsInHTMLDocument()) {
1237 : // HTML. Walk attributes in reverse order.
1238 0 : start = numRealAttrs - 1;
1239 0 : end = -1;
1240 0 : increment = -1;
1241 : } else {
1242 : // XHTML or XML. Walk attributes in forward order.
1243 0 : start = 0;
1244 0 : end = numRealAttrs;
1245 0 : increment = 1;
1246 : }
1247 :
1248 : // Set to the next slot to fill in name and value cache arrays.
1249 0 : PRUint32 nextAttrParamIndex = 0;
1250 :
1251 : // Whether or not we force the wmode below while traversing
1252 : // the name/value pairs.
1253 0 : bool wmodeSet = false;
1254 :
1255 : // Add attribute name/value pairs.
1256 0 : for (PRInt32 index = start; index != end; index += increment) {
1257 0 : const nsAttrName* attrName = mContent->GetAttrNameAt(index);
1258 0 : nsIAtom* atom = attrName->LocalName();
1259 0 : nsAutoString value;
1260 0 : mContent->GetAttr(attrName->NamespaceID(), atom, value);
1261 0 : nsAutoString name;
1262 0 : atom->ToString(name);
1263 :
1264 0 : FixUpURLS(name, value);
1265 :
1266 0 : mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
1267 0 : if (!wmodeType.IsEmpty() &&
1268 0 : 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) {
1269 0 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
1270 :
1271 0 : if (!wmodeSet) {
1272 : // We allocated space to add a wmode attr, but we don't need it now.
1273 0 : mNumCachedAttrs--;
1274 0 : wmodeSet = true;
1275 : }
1276 : } else {
1277 0 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
1278 : }
1279 0 : nextAttrParamIndex++;
1280 : }
1281 :
1282 : // Potentially add WMODE attribute.
1283 0 : if (!wmodeType.IsEmpty() && !wmodeSet) {
1284 0 : mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
1285 0 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
1286 0 : nextAttrParamIndex++;
1287 : }
1288 :
1289 : // Potentially add SRC attribute.
1290 0 : if (!data.IsEmpty()) {
1291 0 : mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
1292 0 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data);
1293 0 : nextAttrParamIndex++;
1294 : }
1295 :
1296 : // Add PARAM and null separator.
1297 0 : mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
1298 : #ifdef MOZ_WIDGET_ANDROID
1299 : // Flash expects an empty string on android
1300 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING(""));
1301 : #else
1302 0 : mCachedAttrParamValues[nextAttrParamIndex] = nsnull;
1303 : #endif
1304 0 : nextAttrParamIndex++;
1305 :
1306 : // Add PARAM name/value pairs.
1307 0 : for (PRUint16 i = 0; i < mNumCachedParams; i++) {
1308 0 : nsIDOMElement* param = ourParams.ObjectAt(i);
1309 0 : if (!param) {
1310 0 : continue;
1311 : }
1312 :
1313 0 : nsAutoString name;
1314 0 : nsAutoString value;
1315 0 : param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
1316 0 : param->GetAttribute(NS_LITERAL_STRING("value"), value);
1317 :
1318 0 : FixUpURLS(name, value);
1319 :
1320 : /*
1321 : * According to the HTML 4.01 spec, at
1322 : * http://www.w3.org/TR/html4/types.html#type-cdata
1323 : * ''User agents may ignore leading and trailing
1324 : * white space in CDATA attribute values (e.g., "
1325 : * myval " may be interpreted as "myval"). Authors
1326 : * should not declare attribute values with
1327 : * leading or trailing white space.''
1328 : * However, do not trim consecutive spaces as in bug 122119
1329 : */
1330 0 : name.Trim(" \n\r\t\b", true, true, false);
1331 0 : value.Trim(" \n\r\t\b", true, true, false);
1332 0 : mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
1333 0 : mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
1334 0 : nextAttrParamIndex++;
1335 : }
1336 :
1337 0 : return NS_OK;
1338 : }
1339 :
1340 : #ifdef XP_MACOSX
1341 :
1342 : #ifndef NP_NO_CARBON
1343 : static void InitializeEventRecord(EventRecord* event, ::Point* aMousePosition)
1344 : {
1345 : memset(event, 0, sizeof(EventRecord));
1346 : if (aMousePosition) {
1347 : event->where = *aMousePosition;
1348 : } else {
1349 : ::GetGlobalMouse(&event->where);
1350 : }
1351 : event->when = ::TickCount();
1352 : event->modifiers = ::GetCurrentKeyModifiers();
1353 : }
1354 : #endif
1355 :
1356 : static void InitializeNPCocoaEvent(NPCocoaEvent* event)
1357 : {
1358 : memset(event, 0, sizeof(NPCocoaEvent));
1359 : }
1360 :
1361 : NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
1362 : {
1363 : #ifndef NP_NO_QUICKDRAW
1364 : NPDrawingModel drawingModel = NPDrawingModelQuickDraw;
1365 : #else
1366 : NPDrawingModel drawingModel = NPDrawingModelCoreGraphics;
1367 : #endif
1368 :
1369 : if (!mInstance)
1370 : return drawingModel;
1371 :
1372 : mInstance->GetDrawingModel((PRInt32*)&drawingModel);
1373 : return drawingModel;
1374 : }
1375 :
1376 : bool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation()
1377 : {
1378 : if (!mInstance)
1379 : return false;
1380 :
1381 : bool coreAnimation;
1382 : if (!NS_SUCCEEDED(mInstance->IsRemoteDrawingCoreAnimation(&coreAnimation)))
1383 : return false;
1384 :
1385 : return coreAnimation;
1386 : }
1387 :
1388 : NPEventModel nsPluginInstanceOwner::GetEventModel()
1389 : {
1390 : return mEventModel;
1391 : }
1392 :
1393 : #define DEFAULT_REFRESH_RATE 20 // 50 FPS
1394 :
1395 : nsCOMPtr<nsITimer> *nsPluginInstanceOwner::sCATimer = NULL;
1396 : nsTArray<nsPluginInstanceOwner*> *nsPluginInstanceOwner::sCARefreshListeners = NULL;
1397 :
1398 : void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) {
1399 : if (!sCARefreshListeners) {
1400 : return;
1401 : }
1402 : for (size_t i = 0; i < sCARefreshListeners->Length(); i++) {
1403 : nsPluginInstanceOwner* instanceOwner = (*sCARefreshListeners)[i];
1404 : NPWindow *window;
1405 : instanceOwner->GetWindow(window);
1406 : if (!window) {
1407 : continue;
1408 : }
1409 : NPRect r;
1410 : r.left = 0;
1411 : r.top = 0;
1412 : r.right = window->width;
1413 : r.bottom = window->height;
1414 : instanceOwner->InvalidateRect(&r);
1415 : }
1416 : }
1417 :
1418 : void nsPluginInstanceOwner::AddToCARefreshTimer() {
1419 : if (!mInstance) {
1420 : return;
1421 : }
1422 :
1423 : // Flash invokes InvalidateRect for us.
1424 : const char* mime = nsnull;
1425 : if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) {
1426 : if (strcmp(mime, "application/x-shockwave-flash") == 0) {
1427 : return;
1428 : }
1429 : }
1430 :
1431 : if (!sCARefreshListeners) {
1432 : sCARefreshListeners = new nsTArray<nsPluginInstanceOwner*>();
1433 : if (!sCARefreshListeners) {
1434 : return;
1435 : }
1436 : }
1437 :
1438 : if (sCARefreshListeners->Contains(this)) {
1439 : return;
1440 : }
1441 :
1442 : sCARefreshListeners->AppendElement(this);
1443 :
1444 : if (!sCATimer) {
1445 : sCATimer = new nsCOMPtr<nsITimer>();
1446 : if (!sCATimer) {
1447 : return;
1448 : }
1449 : }
1450 :
1451 : if (sCARefreshListeners->Length() == 1) {
1452 : *sCATimer = do_CreateInstance("@mozilla.org/timer;1");
1453 : (*sCATimer)->InitWithFuncCallback(CARefresh, NULL,
1454 : DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK);
1455 : }
1456 : }
1457 :
1458 : void nsPluginInstanceOwner::RemoveFromCARefreshTimer() {
1459 : if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) {
1460 : return;
1461 : }
1462 :
1463 : sCARefreshListeners->RemoveElement(this);
1464 :
1465 : if (sCARefreshListeners->Length() == 0) {
1466 : if (sCATimer) {
1467 : (*sCATimer)->Cancel();
1468 : delete sCATimer;
1469 : sCATimer = NULL;
1470 : }
1471 : delete sCARefreshListeners;
1472 : sCARefreshListeners = NULL;
1473 : }
1474 : }
1475 :
1476 : void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
1477 : int aWidth, int aHeight)
1478 : {
1479 : if (aWidth == 0 || aHeight == 0)
1480 : return;
1481 :
1482 : if (!mIOSurface ||
1483 : (mIOSurface->GetWidth() != (size_t)aWidth ||
1484 : mIOSurface->GetHeight() != (size_t)aHeight)) {
1485 : mIOSurface = nsnull;
1486 :
1487 : // If the renderer is backed by an IOSurface, resize it as required.
1488 : mIOSurface = nsIOSurface::CreateIOSurface(aWidth, aHeight);
1489 : if (mIOSurface) {
1490 : nsRefPtr<nsIOSurface> attachSurface = nsIOSurface::LookupSurface(
1491 : mIOSurface->GetIOSurfaceID());
1492 : if (attachSurface) {
1493 : mCARenderer.AttachIOSurface(attachSurface);
1494 : } else {
1495 : NS_ERROR("IOSurface attachment failed");
1496 : mIOSurface = nsnull;
1497 : }
1498 : }
1499 : }
1500 :
1501 : if (!mColorProfile) {
1502 : mColorProfile = CreateSystemColorSpace();
1503 : }
1504 :
1505 : if (mCARenderer.isInit() == false) {
1506 : void *caLayer = NULL;
1507 : nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer);
1508 : if (NS_FAILED(rv) || !caLayer) {
1509 : return;
1510 : }
1511 :
1512 : // We don't run Flash in-process so we can unconditionally disallow
1513 : // the offliner renderer.
1514 : mCARenderer.SetupRenderer(caLayer, aWidth, aHeight, DISALLOW_OFFLINE_RENDERER);
1515 :
1516 : // Setting up the CALayer requires resetting the painting otherwise we
1517 : // get garbage for the first few frames.
1518 : FixUpPluginWindow(ePluginPaintDisable);
1519 : FixUpPluginWindow(ePluginPaintEnable);
1520 : }
1521 :
1522 : CGImageRef caImage = NULL;
1523 : nsresult rt = mCARenderer.Render(aWidth, aHeight, &caImage);
1524 : if (rt == NS_OK && mIOSurface && mColorProfile) {
1525 : nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile,
1526 : 0, 0, aWidth, aHeight);
1527 : } else if (rt == NS_OK && caImage != NULL) {
1528 : // Significant speed up by resetting the scaling
1529 : ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
1530 : ::CGContextTranslateCTM(aCGContext, 0, aHeight);
1531 : ::CGContextScaleCTM(aCGContext, 1.0, -1.0);
1532 :
1533 : ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
1534 : } else {
1535 : NS_NOTREACHED("nsCARenderer::Render failure");
1536 : }
1537 : }
1538 :
1539 : void* nsPluginInstanceOwner::GetPluginPortCopy()
1540 : {
1541 : #ifndef NP_NO_QUICKDRAW
1542 : if (GetDrawingModel() == NPDrawingModelQuickDraw)
1543 : return &mQDPluginPortCopy;
1544 : #endif
1545 : if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
1546 : GetDrawingModel() == NPDrawingModelCoreAnimation ||
1547 : GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
1548 : return &mCGPluginPortCopy;
1549 : return nsnull;
1550 : }
1551 :
1552 : // Currently (on OS X in Cocoa widgets) any changes made as a result of
1553 : // calling GetPluginPortFromWidget() are immediately reflected in the NPWindow
1554 : // structure that has been passed to the plugin via SetWindow(). This is
1555 : // because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG)
1556 : // always return a pointer to the same internal (private) object, but may
1557 : // make changes inside that object. All calls to GetPluginPortFromWidget() made while
1558 : // the plugin is active (i.e. excluding those made at our initialization)
1559 : // need to take this into account. The easiest way to do so is to replace
1560 : // them with calls to SetPluginPortAndDetectChange(). This method keeps track
1561 : // of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make
1562 : // sure SetWindow() gets called the next time through FixUpPluginWindow(), so
1563 : // that the plugin is notified of these changes.
1564 : void* nsPluginInstanceOwner::SetPluginPortAndDetectChange()
1565 : {
1566 : if (!mPluginWindow)
1567 : return nsnull;
1568 : void* pluginPort = GetPluginPortFromWidget();
1569 : if (!pluginPort)
1570 : return nsnull;
1571 : mPluginWindow->window = pluginPort;
1572 :
1573 : #ifndef NP_NO_QUICKDRAW
1574 : NPDrawingModel drawingModel = GetDrawingModel();
1575 : if (drawingModel == NPDrawingModelQuickDraw) {
1576 : NP_Port* windowQDPort = static_cast<NP_Port*>(mPluginWindow->window);
1577 : if (windowQDPort->port != mQDPluginPortCopy.port) {
1578 : mQDPluginPortCopy.port = windowQDPort->port;
1579 : mPluginPortChanged = true;
1580 : }
1581 : } else if (drawingModel == NPDrawingModelCoreGraphics ||
1582 : drawingModel == NPDrawingModelCoreAnimation ||
1583 : drawingModel == NPDrawingModelInvalidatingCoreAnimation)
1584 : #endif
1585 : {
1586 : #ifndef NP_NO_CARBON
1587 : if (GetEventModel() == NPEventModelCarbon) {
1588 : NP_CGContext* windowCGPort = static_cast<NP_CGContext*>(mPluginWindow->window);
1589 : if ((windowCGPort->context != mCGPluginPortCopy.context) ||
1590 : (windowCGPort->window != mCGPluginPortCopy.window)) {
1591 : mCGPluginPortCopy.context = windowCGPort->context;
1592 : mCGPluginPortCopy.window = windowCGPort->window;
1593 : mPluginPortChanged = true;
1594 : }
1595 : }
1596 : #endif
1597 : }
1598 :
1599 : return mPluginWindow->window;
1600 : }
1601 :
1602 : void nsPluginInstanceOwner::BeginCGPaint()
1603 : {
1604 : ++mInCGPaintLevel;
1605 : }
1606 :
1607 : void nsPluginInstanceOwner::EndCGPaint()
1608 : {
1609 : --mInCGPaintLevel;
1610 : NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
1611 : }
1612 :
1613 : #endif
1614 :
1615 : // static
1616 : PRUint32
1617 0 : nsPluginInstanceOwner::GetEventloopNestingLevel()
1618 : {
1619 0 : nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
1620 0 : PRUint32 currentLevel = 0;
1621 0 : if (appShell) {
1622 0 : appShell->GetEventloopNestingLevel(¤tLevel);
1623 : #ifdef XP_MACOSX
1624 : // Cocoa widget code doesn't process UI events through the normal
1625 : // appshell event loop, so it needs an additional count here.
1626 : currentLevel++;
1627 : #endif
1628 : }
1629 :
1630 : // No idea how this happens... but Linux doesn't consistently
1631 : // process UI events through the appshell event loop. If we get a 0
1632 : // here on any platform we increment the level just in case so that
1633 : // we make sure we always tear the plugin down eventually.
1634 0 : if (!currentLevel) {
1635 0 : currentLevel++;
1636 : }
1637 :
1638 0 : return currentLevel;
1639 : }
1640 :
1641 0 : void nsPluginInstanceOwner::ScrollPositionWillChange(nscoord aX, nscoord aY)
1642 : {
1643 : #ifdef MAC_CARBON_PLUGINS
1644 : if (GetEventModel() != NPEventModelCarbon)
1645 : return;
1646 :
1647 : CancelTimer();
1648 :
1649 : if (mInstance) {
1650 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
1651 : if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
1652 : EventRecord scrollEvent;
1653 : InitializeEventRecord(&scrollEvent, nsnull);
1654 : scrollEvent.what = NPEventType_ScrollingBeginsEvent;
1655 :
1656 : void* window = FixUpPluginWindow(ePluginPaintDisable);
1657 : if (window) {
1658 : mInstance->HandleEvent(&scrollEvent, nsnull);
1659 : }
1660 : pluginWidget->EndDrawPlugin();
1661 : }
1662 : }
1663 : #endif
1664 0 : }
1665 :
1666 0 : void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
1667 : {
1668 : #ifdef MAC_CARBON_PLUGINS
1669 : if (GetEventModel() != NPEventModelCarbon)
1670 : return;
1671 :
1672 : if (mInstance) {
1673 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
1674 : if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
1675 : EventRecord scrollEvent;
1676 : InitializeEventRecord(&scrollEvent, nsnull);
1677 : scrollEvent.what = NPEventType_ScrollingEndsEvent;
1678 :
1679 : void* window = FixUpPluginWindow(ePluginPaintEnable);
1680 : if (window) {
1681 : mInstance->HandleEvent(&scrollEvent, nsnull);
1682 : }
1683 : pluginWidget->EndDrawPlugin();
1684 : }
1685 : }
1686 : #endif
1687 0 : }
1688 :
1689 : #ifdef MOZ_WIDGET_ANDROID
1690 :
1691 : void nsPluginInstanceOwner::SendSize(int width, int height)
1692 : {
1693 : if (!mInstance)
1694 : return;
1695 :
1696 : PRInt32 model = mInstance->GetANPDrawingModel();
1697 :
1698 : if (model != kOpenGL_ANPDrawingModel)
1699 : return;
1700 :
1701 : ANPEvent event;
1702 : event.inSize = sizeof(ANPEvent);
1703 : event.eventType = kDraw_ANPEventType;
1704 : event.data.draw.model = kOpenGL_ANPDrawingModel;
1705 : event.data.draw.data.surfaceSize.width = width;
1706 : event.data.draw.data.surfaceSize.height = height;
1707 :
1708 : mInstance->HandleEvent(&event, nsnull);
1709 : }
1710 :
1711 : bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
1712 : {
1713 : void* javaSurface = mInstance->GetJavaSurface();
1714 : if (!javaSurface) {
1715 : mInstance->RequestJavaSurface();
1716 : return false;
1717 : }
1718 :
1719 : JNIEnv* env = GetJNIForThread();
1720 : if (!env)
1721 : return false;
1722 :
1723 : AndroidBridge::AutoLocalJNIFrame frame(env, 1);
1724 :
1725 : jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
1726 :
1727 : #ifdef MOZ_JAVA_COMPOSITOR
1728 : nsAutoString metadata;
1729 : nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
1730 : AndroidBridge::Bridge()->GetDrawMetadataProvider();
1731 : metadataProvider->GetDrawMetadata(metadata);
1732 :
1733 : jstring jMetadata = env->NewString(nsPromiseFlatString(metadata).get(), metadata.Length());
1734 :
1735 : jmethodID method = env->GetStaticMethodID(cls,
1736 : "addPluginView",
1737 : "(Landroid/view/View;IIIILjava/lang/String;)V");
1738 :
1739 : env->CallStaticVoidMethod(cls,
1740 : method,
1741 : javaSurface,
1742 : (int)aRect.x,
1743 : (int)aRect.y,
1744 : (int)aRect.width,
1745 : (int)aRect.height,
1746 : jMetadata);
1747 : #else
1748 : jmethodID method = env->GetStaticMethodID(cls,
1749 : "addPluginView",
1750 : "(Landroid/view/View;DDDD)V");
1751 :
1752 : env->CallStaticVoidMethod(cls,
1753 : method,
1754 : javaSurface,
1755 : aRect.x,
1756 : aRect.y,
1757 : aRect.width,
1758 : aRect.height);
1759 : #endif
1760 :
1761 : return true;
1762 : }
1763 :
1764 : void nsPluginInstanceOwner::RemovePluginView()
1765 : {
1766 : if (!mInstance || !mObjectFrame)
1767 : return;
1768 :
1769 : void* surface = mInstance->GetJavaSurface();
1770 : if (!surface)
1771 : return;
1772 :
1773 : JNIEnv* env = GetJNIForThread();
1774 : if (!env)
1775 : return;
1776 :
1777 : AndroidBridge::AutoLocalJNIFrame frame(env, 1);
1778 :
1779 : jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
1780 : jmethodID method = env->GetStaticMethodID(cls,
1781 : "removePluginView",
1782 : "(Landroid/view/View;)V");
1783 : env->CallStaticVoidMethod(cls, method, surface);
1784 : }
1785 :
1786 : void nsPluginInstanceOwner::Invalidate() {
1787 : NPRect rect;
1788 : rect.left = rect.top = 0;
1789 : rect.right = mPluginWindow->width;
1790 : rect.bottom = mPluginWindow->height;
1791 : InvalidateRect(&rect);
1792 : }
1793 :
1794 : #endif
1795 :
1796 0 : nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
1797 : {
1798 : #ifdef MOZ_WIDGET_ANDROID
1799 : {
1800 : ANPEvent event;
1801 : event.inSize = sizeof(ANPEvent);
1802 : event.eventType = kLifecycle_ANPEventType;
1803 :
1804 : nsAutoString eventType;
1805 : aFocusEvent->GetType(eventType);
1806 : if (eventType.EqualsLiteral("focus")) {
1807 : event.data.lifecycle.action = kGainFocus_ANPLifecycleAction;
1808 : }
1809 : else if (eventType.EqualsLiteral("blur")) {
1810 : event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction;
1811 : }
1812 : else {
1813 : NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType");
1814 : }
1815 : mInstance->HandleEvent(&event, nsnull);
1816 : }
1817 : #endif
1818 :
1819 : #ifndef XP_MACOSX
1820 0 : if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) {
1821 : // continue only for cases without child window
1822 0 : return aFocusEvent->PreventDefault(); // consume event
1823 : }
1824 : #endif
1825 :
1826 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aFocusEvent));
1827 0 : if (privateEvent) {
1828 0 : nsEvent * theEvent = privateEvent->GetInternalNSEvent();
1829 0 : if (theEvent) {
1830 : // we only care about the message in ProcessEvent
1831 : nsGUIEvent focusEvent(NS_IS_TRUSTED_EVENT(theEvent), theEvent->message,
1832 0 : nsnull);
1833 0 : nsEventStatus rv = ProcessEvent(focusEvent);
1834 0 : if (nsEventStatus_eConsumeNoDefault == rv) {
1835 0 : aFocusEvent->PreventDefault();
1836 0 : aFocusEvent->StopPropagation();
1837 : }
1838 : }
1839 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, focusEvent null");
1840 : }
1841 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, privateEvent null");
1842 :
1843 0 : return NS_OK;
1844 : }
1845 :
1846 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
1847 : nsresult nsPluginInstanceOwner::Text(nsIDOMEvent* aTextEvent)
1848 : {
1849 : if (mInstance) {
1850 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aTextEvent));
1851 : if (privateEvent) {
1852 : nsEvent *event = privateEvent->GetInternalNSEvent();
1853 : if (event && event->eventStructType == NS_TEXT_EVENT) {
1854 : nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
1855 : if (nsEventStatus_eConsumeNoDefault == rv) {
1856 : aTextEvent->PreventDefault();
1857 : aTextEvent->StopPropagation();
1858 : }
1859 : }
1860 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchTextToPlugin failed, textEvent null");
1861 : }
1862 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchTextToPlugin failed, privateEvent null");
1863 : }
1864 :
1865 : return NS_OK;
1866 : }
1867 : #endif
1868 :
1869 0 : nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
1870 : {
1871 : #ifdef XP_MACOSX
1872 : #ifndef NP_NO_CARBON
1873 : if (GetEventModel() == NPEventModelCarbon) {
1874 : // KeyPress events are really synthesized keyDown events.
1875 : // Here we check the native message of the event so that
1876 : // we won't send the plugin two keyDown events.
1877 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aKeyEvent));
1878 : if (privateEvent) {
1879 : nsEvent *theEvent = privateEvent->GetInternalNSEvent();
1880 : const EventRecord *ev;
1881 : if (theEvent &&
1882 : theEvent->message == NS_KEY_PRESS &&
1883 : (ev = (EventRecord*)(((nsGUIEvent*)theEvent)->pluginEvent)) &&
1884 : ev->what == keyDown)
1885 : return aKeyEvent->PreventDefault(); // consume event
1886 : }
1887 :
1888 : // Nasty hack to avoid recursive event dispatching with Java. Java can
1889 : // dispatch key events to a TSM handler, which comes back and calls
1890 : // [ChildView insertText:] on the cocoa widget, which sends a key
1891 : // event back down.
1892 : static bool sInKeyDispatch = false;
1893 :
1894 : if (sInKeyDispatch)
1895 : return aKeyEvent->PreventDefault(); // consume event
1896 :
1897 : sInKeyDispatch = true;
1898 : nsresult rv = DispatchKeyToPlugin(aKeyEvent);
1899 : sInKeyDispatch = false;
1900 : return rv;
1901 : }
1902 : #endif
1903 :
1904 : return DispatchKeyToPlugin(aKeyEvent);
1905 : #else
1906 0 : if (SendNativeEvents())
1907 0 : DispatchKeyToPlugin(aKeyEvent);
1908 :
1909 0 : if (mInstance) {
1910 : // If this event is going to the plugin, we want to kill it.
1911 : // Not actually sending keypress to the plugin, since we didn't before.
1912 0 : aKeyEvent->PreventDefault();
1913 0 : aKeyEvent->StopPropagation();
1914 : }
1915 0 : return NS_OK;
1916 : #endif
1917 : }
1918 :
1919 0 : nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
1920 : {
1921 : #if !defined(XP_MACOSX)
1922 0 : if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
1923 0 : return aKeyEvent->PreventDefault(); // consume event
1924 : // continue only for cases without child window
1925 : #endif
1926 :
1927 0 : if (mInstance) {
1928 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aKeyEvent));
1929 0 : if (privateEvent) {
1930 0 : nsEvent *event = privateEvent->GetInternalNSEvent();
1931 0 : if (event && event->eventStructType == NS_KEY_EVENT) {
1932 0 : nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
1933 0 : if (nsEventStatus_eConsumeNoDefault == rv) {
1934 0 : aKeyEvent->PreventDefault();
1935 0 : aKeyEvent->StopPropagation();
1936 0 : }
1937 : }
1938 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, keyEvent null");
1939 : }
1940 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, privateEvent null");
1941 : }
1942 :
1943 0 : return NS_OK;
1944 : }
1945 :
1946 : nsresult
1947 0 : nsPluginInstanceOwner::MouseDown(nsIDOMEvent* aMouseEvent)
1948 : {
1949 : #if !defined(XP_MACOSX)
1950 0 : if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
1951 0 : return aMouseEvent->PreventDefault(); // consume event
1952 : // continue only for cases without child window
1953 : #endif
1954 :
1955 : // if the plugin is windowless, we need to set focus ourselves
1956 : // otherwise, we might not get key events
1957 0 : if (mObjectFrame && mPluginWindow &&
1958 : mPluginWindow->type == NPWindowTypeDrawable) {
1959 :
1960 0 : nsIFocusManager* fm = nsFocusManager::GetFocusManager();
1961 0 : if (fm) {
1962 0 : nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
1963 0 : fm->SetFocus(elem, 0);
1964 : }
1965 : }
1966 :
1967 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aMouseEvent));
1968 0 : if (privateEvent) {
1969 0 : nsEvent* event = privateEvent->GetInternalNSEvent();
1970 0 : if (event && event->eventStructType == NS_MOUSE_EVENT) {
1971 0 : nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
1972 0 : if (nsEventStatus_eConsumeNoDefault == rv) {
1973 0 : return aMouseEvent->PreventDefault(); // consume event
1974 0 : }
1975 : }
1976 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::MouseDown failed, mouseEvent null");
1977 : }
1978 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::MouseDown failed, privateEvent null");
1979 :
1980 0 : return NS_OK;
1981 : }
1982 :
1983 0 : nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
1984 : {
1985 : #if !defined(XP_MACOSX)
1986 0 : if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
1987 0 : return aMouseEvent->PreventDefault(); // consume event
1988 : // continue only for cases without child window
1989 : #endif
1990 : // don't send mouse events if we are hidden
1991 0 : if (!mWidgetVisible)
1992 0 : return NS_OK;
1993 :
1994 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aMouseEvent));
1995 0 : if (privateEvent) {
1996 0 : nsEvent* event = privateEvent->GetInternalNSEvent();
1997 0 : if (event && event->eventStructType == NS_MOUSE_EVENT) {
1998 0 : nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
1999 0 : if (nsEventStatus_eConsumeNoDefault == rv) {
2000 0 : aMouseEvent->PreventDefault();
2001 0 : aMouseEvent->StopPropagation();
2002 0 : }
2003 : }
2004 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, mouseEvent null");
2005 : }
2006 0 : else NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, privateEvent null");
2007 :
2008 0 : return NS_OK;
2009 : }
2010 :
2011 : nsresult
2012 0 : nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
2013 : {
2014 0 : nsAutoString eventType;
2015 0 : aEvent->GetType(eventType);
2016 0 : if (eventType.EqualsLiteral("focus")) {
2017 0 : mContentFocused = true;
2018 0 : return DispatchFocusToPlugin(aEvent);
2019 : }
2020 0 : if (eventType.EqualsLiteral("blur")) {
2021 0 : mContentFocused = false;
2022 0 : return DispatchFocusToPlugin(aEvent);
2023 : }
2024 0 : if (eventType.EqualsLiteral("mousedown")) {
2025 0 : return MouseDown(aEvent);
2026 : }
2027 0 : if (eventType.EqualsLiteral("mouseup")) {
2028 : // Don't send a mouse-up event to the plugin if it isn't focused. This can
2029 : // happen if the previous mouse-down was sent to a DOM element above the
2030 : // plugin, the mouse is still above the plugin, and the mouse-down event
2031 : // caused the element to disappear. See bug 627649.
2032 0 : if (!mContentFocused) {
2033 0 : aEvent->PreventDefault();
2034 0 : return NS_OK;
2035 : }
2036 0 : return DispatchMouseToPlugin(aEvent);
2037 : }
2038 0 : if (eventType.EqualsLiteral("mousemove") ||
2039 0 : eventType.EqualsLiteral("click") ||
2040 0 : eventType.EqualsLiteral("dblclick") ||
2041 0 : eventType.EqualsLiteral("mouseover") ||
2042 0 : eventType.EqualsLiteral("mouseout")) {
2043 0 : return DispatchMouseToPlugin(aEvent);
2044 : }
2045 0 : if (eventType.EqualsLiteral("keydown") ||
2046 0 : eventType.EqualsLiteral("keyup")) {
2047 0 : return DispatchKeyToPlugin(aEvent);
2048 : }
2049 0 : if (eventType.EqualsLiteral("keypress")) {
2050 0 : return KeyPress(aEvent);
2051 : }
2052 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
2053 : if (eventType.EqualsLiteral("text")) {
2054 : return Text(aEvent);
2055 : }
2056 : #endif
2057 :
2058 0 : nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
2059 0 : if (dragEvent && mInstance) {
2060 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
2061 0 : if (privateEvent) {
2062 0 : nsEvent* ievent = privateEvent->GetInternalNSEvent();
2063 0 : if ((ievent && NS_IS_TRUSTED_EVENT(ievent)) &&
2064 : ievent->message != NS_DRAGDROP_ENTER && ievent->message != NS_DRAGDROP_OVER) {
2065 0 : aEvent->PreventDefault();
2066 : }
2067 :
2068 : // Let the plugin handle drag events.
2069 0 : aEvent->StopPropagation();
2070 : }
2071 : }
2072 0 : return NS_OK;
2073 : }
2074 :
2075 : #ifdef MOZ_X11
2076 0 : static unsigned int XInputEventState(const nsInputEvent& anEvent)
2077 : {
2078 0 : unsigned int state = 0;
2079 0 : if (anEvent.isShift) state |= ShiftMask;
2080 0 : if (anEvent.isControl) state |= ControlMask;
2081 0 : if (anEvent.isAlt) state |= Mod1Mask;
2082 0 : if (anEvent.isMeta) state |= Mod4Mask;
2083 0 : return state;
2084 : }
2085 : #endif
2086 :
2087 0 : nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
2088 : {
2089 0 : nsEventStatus rv = nsEventStatus_eIgnore;
2090 :
2091 0 : if (!mInstance || !mObjectFrame) // if mInstance is null, we shouldn't be here
2092 0 : return nsEventStatus_eIgnore;
2093 :
2094 : #ifdef XP_MACOSX
2095 : if (!mWidget)
2096 : return nsEventStatus_eIgnore;
2097 :
2098 : // we never care about synthesized mouse enter
2099 : if (anEvent.message == NS_MOUSE_ENTER_SYNTH)
2100 : return nsEventStatus_eIgnore;
2101 :
2102 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
2103 : if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin()))
2104 : return nsEventStatus_eIgnore;
2105 :
2106 : NPEventModel eventModel = GetEventModel();
2107 :
2108 : // If we have to synthesize an event we'll use one of these.
2109 : #ifndef NP_NO_CARBON
2110 : EventRecord synthCarbonEvent;
2111 : #endif
2112 : NPCocoaEvent synthCocoaEvent;
2113 : void* event = anEvent.pluginEvent;
2114 : nsPoint pt =
2115 : nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
2116 : mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
2117 : nsPresContext* presContext = mObjectFrame->PresContext();
2118 : nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
2119 : presContext->AppUnitsToDevPixels(pt.y));
2120 : #ifndef NP_NO_CARBON
2121 : nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
2122 : ::Point carbonPt = { static_cast<short>(ptPx.y + geckoScreenCoords.y),
2123 : static_cast<short>(ptPx.x + geckoScreenCoords.x) };
2124 : if (eventModel == NPEventModelCarbon) {
2125 : if (event && anEvent.eventStructType == NS_MOUSE_EVENT) {
2126 : static_cast<EventRecord*>(event)->where = carbonPt;
2127 : }
2128 : }
2129 : #endif
2130 : if (!event) {
2131 : #ifndef NP_NO_CARBON
2132 : if (eventModel == NPEventModelCarbon) {
2133 : InitializeEventRecord(&synthCarbonEvent, &carbonPt);
2134 : } else
2135 : #endif
2136 : {
2137 : InitializeNPCocoaEvent(&synthCocoaEvent);
2138 : }
2139 :
2140 : switch (anEvent.message) {
2141 : case NS_FOCUS_CONTENT:
2142 : case NS_BLUR_CONTENT:
2143 : #ifndef NP_NO_CARBON
2144 : if (eventModel == NPEventModelCarbon) {
2145 : synthCarbonEvent.what = (anEvent.message == NS_FOCUS_CONTENT) ?
2146 : NPEventType_GetFocusEvent : NPEventType_LoseFocusEvent;
2147 : event = &synthCarbonEvent;
2148 : }
2149 : #endif
2150 : break;
2151 : case NS_MOUSE_MOVE:
2152 : {
2153 : // Ignore mouse-moved events that happen as part of a dragging
2154 : // operation that started over another frame. See bug 525078.
2155 : nsRefPtr<nsFrameSelection> frameselection = mObjectFrame->GetFrameSelection();
2156 : if (!frameselection->GetMouseDownState() ||
2157 : (nsIPresShell::GetCapturingContent() == mObjectFrame->GetContent())) {
2158 : #ifndef NP_NO_CARBON
2159 : if (eventModel == NPEventModelCarbon) {
2160 : synthCarbonEvent.what = osEvt;
2161 : event = &synthCarbonEvent;
2162 : } else
2163 : #endif
2164 : {
2165 : synthCocoaEvent.type = NPCocoaEventMouseMoved;
2166 : synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
2167 : synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
2168 : event = &synthCocoaEvent;
2169 : }
2170 : }
2171 : }
2172 : break;
2173 : case NS_MOUSE_BUTTON_DOWN:
2174 : #ifndef NP_NO_CARBON
2175 : if (eventModel == NPEventModelCarbon) {
2176 : synthCarbonEvent.what = mouseDown;
2177 : event = &synthCarbonEvent;
2178 : } else
2179 : #endif
2180 : {
2181 : synthCocoaEvent.type = NPCocoaEventMouseDown;
2182 : synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
2183 : synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
2184 : event = &synthCocoaEvent;
2185 : }
2186 : break;
2187 : case NS_MOUSE_BUTTON_UP:
2188 : // If we're in a dragging operation that started over another frame,
2189 : // either ignore the mouse-up event (in the Carbon Event Model) or
2190 : // convert it into a mouse-entered event (in the Cocoa Event Model).
2191 : // See bug 525078.
2192 : if ((static_cast<const nsMouseEvent&>(anEvent).button == nsMouseEvent::eLeftButton) &&
2193 : (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) {
2194 : if (eventModel == NPEventModelCocoa) {
2195 : synthCocoaEvent.type = NPCocoaEventMouseEntered;
2196 : synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
2197 : synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
2198 : event = &synthCocoaEvent;
2199 : }
2200 : } else {
2201 : #ifndef NP_NO_CARBON
2202 : if (eventModel == NPEventModelCarbon) {
2203 : synthCarbonEvent.what = mouseUp;
2204 : event = &synthCarbonEvent;
2205 : } else
2206 : #endif
2207 : {
2208 : synthCocoaEvent.type = NPCocoaEventMouseUp;
2209 : synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
2210 : synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
2211 : event = &synthCocoaEvent;
2212 : }
2213 : }
2214 : break;
2215 : default:
2216 : break;
2217 : }
2218 :
2219 : // If we still don't have an event, bail.
2220 : if (!event) {
2221 : pluginWidget->EndDrawPlugin();
2222 : return nsEventStatus_eIgnore;
2223 : }
2224 : }
2225 :
2226 : #ifndef NP_NO_CARBON
2227 : // Work around an issue in the Flash plugin, which can cache a pointer
2228 : // to a doomed TSM document (one that belongs to a NSTSMInputContext)
2229 : // and try to activate it after it has been deleted. See bug 183313.
2230 : if (eventModel == NPEventModelCarbon && anEvent.message == NS_FOCUS_CONTENT)
2231 : ::DeactivateTSMDocument(::TSMGetActiveDocument());
2232 : #endif
2233 :
2234 : PRInt16 response = kNPEventNotHandled;
2235 : void* window = FixUpPluginWindow(ePluginPaintEnable);
2236 : if (window || (eventModel == NPEventModelCocoa)) {
2237 : mInstance->HandleEvent(event, &response);
2238 : }
2239 :
2240 : if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
2241 : pluginWidget->StartComplexTextInputForCurrentEvent();
2242 : }
2243 :
2244 : if ((response == kNPEventHandled || response == kNPEventStartIME) &&
2245 : !(anEvent.eventStructType == NS_MOUSE_EVENT &&
2246 : anEvent.message == NS_MOUSE_BUTTON_DOWN &&
2247 : static_cast<const nsMouseEvent&>(anEvent).button == nsMouseEvent::eLeftButton &&
2248 : !mContentFocused))
2249 : rv = nsEventStatus_eConsumeNoDefault;
2250 :
2251 : pluginWidget->EndDrawPlugin();
2252 : #endif
2253 :
2254 : #ifdef XP_WIN
2255 : // this code supports windowless plugins
2256 : NPEvent *pPluginEvent = (NPEvent*)anEvent.pluginEvent;
2257 : // we can get synthetic events from the nsEventStateManager... these
2258 : // have no pluginEvent
2259 : NPEvent pluginEvent;
2260 : if (anEvent.eventStructType == NS_MOUSE_EVENT) {
2261 : if (!pPluginEvent) {
2262 : // XXX Should extend this list to synthesize events for more event
2263 : // types
2264 : pluginEvent.event = 0;
2265 : const nsMouseEvent* mouseEvent = static_cast<const nsMouseEvent*>(&anEvent);
2266 : switch (anEvent.message) {
2267 : case NS_MOUSE_MOVE:
2268 : pluginEvent.event = WM_MOUSEMOVE;
2269 : break;
2270 : case NS_MOUSE_BUTTON_DOWN: {
2271 : static const int downMsgs[] =
2272 : { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
2273 : static const int dblClickMsgs[] =
2274 : { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK };
2275 : if (mouseEvent->clickCount == 2) {
2276 : pluginEvent.event = dblClickMsgs[mouseEvent->button];
2277 : } else {
2278 : pluginEvent.event = downMsgs[mouseEvent->button];
2279 : }
2280 : break;
2281 : }
2282 : case NS_MOUSE_BUTTON_UP: {
2283 : static const int upMsgs[] =
2284 : { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
2285 : pluginEvent.event = upMsgs[mouseEvent->button];
2286 : break;
2287 : }
2288 : // don't synthesize anything for NS_MOUSE_DOUBLECLICK, since that
2289 : // is a synthetic event generated on mouse-up, and Windows WM_*DBLCLK
2290 : // messages are sent on mouse-down
2291 : default:
2292 : break;
2293 : }
2294 : if (pluginEvent.event) {
2295 : pPluginEvent = &pluginEvent;
2296 : pluginEvent.wParam =
2297 : (::GetKeyState(VK_CONTROL) ? MK_CONTROL : 0) |
2298 : (::GetKeyState(VK_SHIFT) ? MK_SHIFT : 0) |
2299 : (::GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0) |
2300 : (::GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0) |
2301 : (::GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0) |
2302 : (::GetKeyState(VK_XBUTTON1) ? MK_XBUTTON1 : 0) |
2303 : (::GetKeyState(VK_XBUTTON2) ? MK_XBUTTON2 : 0);
2304 : }
2305 : }
2306 : if (pPluginEvent) {
2307 : // Make event coordinates relative to our enclosing widget,
2308 : // not the widget they were received on.
2309 : // See use of NPEvent in widget/windows/nsWindow.cpp
2310 : // for why this assert should be safe
2311 : NS_ASSERTION(anEvent.message == NS_MOUSE_BUTTON_DOWN ||
2312 : anEvent.message == NS_MOUSE_BUTTON_UP ||
2313 : anEvent.message == NS_MOUSE_DOUBLECLICK ||
2314 : anEvent.message == NS_MOUSE_ENTER_SYNTH ||
2315 : anEvent.message == NS_MOUSE_EXIT_SYNTH ||
2316 : anEvent.message == NS_MOUSE_MOVE,
2317 : "Incorrect event type for coordinate translation");
2318 : nsPoint pt =
2319 : nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
2320 : mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
2321 : nsPresContext* presContext = mObjectFrame->PresContext();
2322 : nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
2323 : presContext->AppUnitsToDevPixels(pt.y));
2324 : nsIntPoint widgetPtPx = ptPx + mObjectFrame->GetWindowOriginInPixels(true);
2325 : pPluginEvent->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y);
2326 : }
2327 : }
2328 : else if (!pPluginEvent) {
2329 : switch (anEvent.message) {
2330 : case NS_FOCUS_CONTENT:
2331 : pluginEvent.event = WM_SETFOCUS;
2332 : pluginEvent.wParam = 0;
2333 : pluginEvent.lParam = 0;
2334 : pPluginEvent = &pluginEvent;
2335 : break;
2336 : case NS_BLUR_CONTENT:
2337 : pluginEvent.event = WM_KILLFOCUS;
2338 : pluginEvent.wParam = 0;
2339 : pluginEvent.lParam = 0;
2340 : pPluginEvent = &pluginEvent;
2341 : break;
2342 : }
2343 : }
2344 :
2345 : if (pPluginEvent && !pPluginEvent->event) {
2346 : // Don't send null events to plugins.
2347 : NS_WARNING("nsObjectFrame ProcessEvent: trying to send null event to plugin.");
2348 : return rv;
2349 : }
2350 :
2351 : if (pPluginEvent) {
2352 : PRInt16 response = kNPEventNotHandled;
2353 : mInstance->HandleEvent(pPluginEvent, &response);
2354 : if (response == kNPEventHandled)
2355 : rv = nsEventStatus_eConsumeNoDefault;
2356 : }
2357 : #endif
2358 :
2359 : #ifdef MOZ_X11
2360 : // this code supports windowless plugins
2361 0 : nsIWidget* widget = anEvent.widget;
2362 0 : XEvent pluginEvent = XEvent();
2363 0 : pluginEvent.type = 0;
2364 :
2365 0 : switch(anEvent.eventStructType)
2366 : {
2367 : case NS_MOUSE_EVENT:
2368 : {
2369 0 : switch (anEvent.message)
2370 : {
2371 : case NS_MOUSE_CLICK:
2372 : case NS_MOUSE_DOUBLECLICK:
2373 : // Button up/down events sent instead.
2374 0 : return rv;
2375 : }
2376 :
2377 : // Get reference point relative to plugin origin.
2378 0 : const nsPresContext* presContext = mObjectFrame->PresContext();
2379 : nsPoint appPoint =
2380 : nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
2381 0 : mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
2382 : nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
2383 0 : presContext->AppUnitsToDevPixels(appPoint.y));
2384 : const nsMouseEvent& mouseEvent =
2385 0 : static_cast<const nsMouseEvent&>(anEvent);
2386 : // Get reference point relative to screen:
2387 0 : nsIntPoint rootPoint(-1,-1);
2388 0 : if (widget)
2389 0 : rootPoint = anEvent.refPoint + widget->WidgetToScreenOffset();
2390 : #ifdef MOZ_WIDGET_GTK2
2391 0 : Window root = GDK_ROOT_WINDOW();
2392 : #elif defined(MOZ_WIDGET_QT)
2393 : Window root = QX11Info::appRootWindow();
2394 : #else
2395 : Window root = None; // Could XQueryTree, but this is not important.
2396 : #endif
2397 :
2398 0 : switch (anEvent.message)
2399 : {
2400 : case NS_MOUSE_ENTER_SYNTH:
2401 : case NS_MOUSE_EXIT_SYNTH:
2402 : {
2403 0 : XCrossingEvent& event = pluginEvent.xcrossing;
2404 : event.type = anEvent.message == NS_MOUSE_ENTER_SYNTH ?
2405 0 : EnterNotify : LeaveNotify;
2406 0 : event.root = root;
2407 0 : event.time = anEvent.time;
2408 0 : event.x = pluginPoint.x;
2409 0 : event.y = pluginPoint.y;
2410 0 : event.x_root = rootPoint.x;
2411 0 : event.y_root = rootPoint.y;
2412 0 : event.state = XInputEventState(mouseEvent);
2413 : // information lost
2414 0 : event.subwindow = None;
2415 0 : event.mode = -1;
2416 0 : event.detail = NotifyDetailNone;
2417 0 : event.same_screen = True;
2418 0 : event.focus = mContentFocused;
2419 : }
2420 0 : break;
2421 : case NS_MOUSE_MOVE:
2422 : {
2423 0 : XMotionEvent& event = pluginEvent.xmotion;
2424 0 : event.type = MotionNotify;
2425 0 : event.root = root;
2426 0 : event.time = anEvent.time;
2427 0 : event.x = pluginPoint.x;
2428 0 : event.y = pluginPoint.y;
2429 0 : event.x_root = rootPoint.x;
2430 0 : event.y_root = rootPoint.y;
2431 0 : event.state = XInputEventState(mouseEvent);
2432 : // information lost
2433 0 : event.subwindow = None;
2434 0 : event.is_hint = NotifyNormal;
2435 0 : event.same_screen = True;
2436 : }
2437 0 : break;
2438 : case NS_MOUSE_BUTTON_DOWN:
2439 : case NS_MOUSE_BUTTON_UP:
2440 : {
2441 0 : XButtonEvent& event = pluginEvent.xbutton;
2442 : event.type = anEvent.message == NS_MOUSE_BUTTON_DOWN ?
2443 0 : ButtonPress : ButtonRelease;
2444 0 : event.root = root;
2445 0 : event.time = anEvent.time;
2446 0 : event.x = pluginPoint.x;
2447 0 : event.y = pluginPoint.y;
2448 0 : event.x_root = rootPoint.x;
2449 0 : event.y_root = rootPoint.y;
2450 0 : event.state = XInputEventState(mouseEvent);
2451 0 : switch (mouseEvent.button)
2452 : {
2453 : case nsMouseEvent::eMiddleButton:
2454 0 : event.button = 2;
2455 0 : break;
2456 : case nsMouseEvent::eRightButton:
2457 0 : event.button = 3;
2458 0 : break;
2459 : default: // nsMouseEvent::eLeftButton;
2460 0 : event.button = 1;
2461 0 : break;
2462 : }
2463 : // information lost:
2464 0 : event.subwindow = None;
2465 0 : event.same_screen = True;
2466 : }
2467 0 : break;
2468 : }
2469 : }
2470 0 : break;
2471 :
2472 : //XXX case NS_MOUSE_SCROLL_EVENT: not received.
2473 :
2474 : case NS_KEY_EVENT:
2475 0 : if (anEvent.pluginEvent)
2476 : {
2477 0 : XKeyEvent &event = pluginEvent.xkey;
2478 : #ifdef MOZ_WIDGET_GTK2
2479 0 : event.root = GDK_ROOT_WINDOW();
2480 0 : event.time = anEvent.time;
2481 : const GdkEventKey* gdkEvent =
2482 0 : static_cast<const GdkEventKey*>(anEvent.pluginEvent);
2483 0 : event.keycode = gdkEvent->hardware_keycode;
2484 0 : event.state = gdkEvent->state;
2485 0 : switch (anEvent.message)
2486 : {
2487 : case NS_KEY_DOWN:
2488 : // Handle NS_KEY_DOWN for modifier key presses
2489 : // For non-modifiers we get NS_KEY_PRESS
2490 0 : if (gdkEvent->is_modifier)
2491 0 : event.type = XKeyPress;
2492 0 : break;
2493 : case NS_KEY_PRESS:
2494 0 : event.type = XKeyPress;
2495 0 : break;
2496 : case NS_KEY_UP:
2497 0 : event.type = KeyRelease;
2498 0 : break;
2499 : }
2500 : #endif
2501 :
2502 : #ifdef MOZ_WIDGET_QT
2503 : const nsKeyEvent& keyEvent = static_cast<const nsKeyEvent&>(anEvent);
2504 :
2505 : memset( &event, 0, sizeof(event) );
2506 : event.time = anEvent.time;
2507 :
2508 : QWidget* qWidget = static_cast<QWidget*>(widget->GetNativeData(NS_NATIVE_WINDOW));
2509 : if (qWidget)
2510 : event.root = qWidget->x11Info().appRootWindow();
2511 :
2512 : // deduce keycode from the information in the attached QKeyEvent
2513 : const QKeyEvent* qtEvent = static_cast<const QKeyEvent*>(anEvent.pluginEvent);
2514 : if (qtEvent) {
2515 :
2516 : if (qtEvent->nativeModifiers())
2517 : event.state = qtEvent->nativeModifiers();
2518 : else // fallback
2519 : event.state = XInputEventState(keyEvent);
2520 :
2521 : if (qtEvent->nativeScanCode())
2522 : event.keycode = qtEvent->nativeScanCode();
2523 : else // fallback
2524 : event.keycode = XKeysymToKeycode( (widget ? static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nsnull), qtEvent->key());
2525 : }
2526 :
2527 : switch (anEvent.message)
2528 : {
2529 : case NS_KEY_DOWN:
2530 : event.type = XKeyPress;
2531 : break;
2532 : case NS_KEY_UP:
2533 : event.type = KeyRelease;
2534 : break;
2535 : }
2536 : #endif
2537 : // Information that could be obtained from pluginEvent but we may not
2538 : // want to promise to provide:
2539 0 : event.subwindow = None;
2540 0 : event.x = 0;
2541 0 : event.y = 0;
2542 0 : event.x_root = -1;
2543 0 : event.y_root = -1;
2544 0 : event.same_screen = False;
2545 : }
2546 : else
2547 : {
2548 : // If we need to send synthesized key events, then
2549 : // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
2550 : // gdk_keymap_get_entries_for_keyval will be useful, but the
2551 : // mappings will not be unique.
2552 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
2553 : bool handled;
2554 : if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
2555 : handled) {
2556 : rv = nsEventStatus_eConsumeNoDefault;
2557 : }
2558 : #else
2559 0 : NS_WARNING("Synthesized key event not sent to plugin");
2560 : #endif
2561 : }
2562 0 : break;
2563 :
2564 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
2565 : case NS_TEXT_EVENT:
2566 : {
2567 : bool handled;
2568 : if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
2569 : handled) {
2570 : rv = nsEventStatus_eConsumeNoDefault;
2571 : }
2572 : }
2573 : break;
2574 : #endif
2575 : default:
2576 0 : switch (anEvent.message)
2577 : {
2578 : case NS_FOCUS_CONTENT:
2579 : case NS_BLUR_CONTENT:
2580 : {
2581 0 : XFocusChangeEvent &event = pluginEvent.xfocus;
2582 : event.type =
2583 0 : anEvent.message == NS_FOCUS_CONTENT ? FocusIn : FocusOut;
2584 : // information lost:
2585 0 : event.mode = -1;
2586 0 : event.detail = NotifyDetailNone;
2587 : }
2588 0 : break;
2589 : }
2590 : }
2591 :
2592 0 : if (!pluginEvent.type) {
2593 0 : return rv;
2594 : }
2595 :
2596 : // Fill in (useless) generic event information.
2597 0 : XAnyEvent& event = pluginEvent.xany;
2598 : event.display = widget ?
2599 0 : static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nsnull;
2600 0 : event.window = None; // not a real window
2601 : // information lost:
2602 0 : event.serial = 0;
2603 0 : event.send_event = False;
2604 :
2605 0 : PRInt16 response = kNPEventNotHandled;
2606 0 : mInstance->HandleEvent(&pluginEvent, &response);
2607 0 : if (response == kNPEventHandled)
2608 0 : rv = nsEventStatus_eConsumeNoDefault;
2609 : #endif
2610 :
2611 : #ifdef MOZ_WIDGET_ANDROID
2612 : // this code supports windowless plugins
2613 : {
2614 : // The plugin needs focus to receive keyboard and touch events
2615 : nsIFocusManager* fm = nsFocusManager::GetFocusManager();
2616 : if (fm) {
2617 : nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
2618 : fm->SetFocus(elem, 0);
2619 : }
2620 : }
2621 : switch(anEvent.eventStructType)
2622 : {
2623 : case NS_MOUSE_EVENT:
2624 : {
2625 : switch (anEvent.message)
2626 : {
2627 : case NS_MOUSE_CLICK:
2628 : case NS_MOUSE_DOUBLECLICK:
2629 : // Button up/down events sent instead.
2630 : return rv;
2631 : }
2632 :
2633 : // Get reference point relative to plugin origin.
2634 : const nsPresContext* presContext = mObjectFrame->PresContext();
2635 : nsPoint appPoint =
2636 : nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
2637 : mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
2638 : nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
2639 : presContext->AppUnitsToDevPixels(appPoint.y));
2640 :
2641 : switch (anEvent.message)
2642 : {
2643 : case NS_MOUSE_MOVE:
2644 : {
2645 : // are these going to be touch events?
2646 : // pluginPoint.x;
2647 : // pluginPoint.y;
2648 : }
2649 : break;
2650 : case NS_MOUSE_BUTTON_DOWN:
2651 : {
2652 : ANPEvent event;
2653 : event.inSize = sizeof(ANPEvent);
2654 : event.eventType = kMouse_ANPEventType;
2655 : event.data.mouse.action = kDown_ANPMouseAction;
2656 : event.data.mouse.x = pluginPoint.x;
2657 : event.data.mouse.y = pluginPoint.y;
2658 : mInstance->HandleEvent(&event, nsnull);
2659 : }
2660 : break;
2661 : case NS_MOUSE_BUTTON_UP:
2662 : {
2663 : ANPEvent event;
2664 : event.inSize = sizeof(ANPEvent);
2665 : event.eventType = kMouse_ANPEventType;
2666 : event.data.mouse.action = kUp_ANPMouseAction;
2667 : event.data.mouse.x = pluginPoint.x;
2668 : event.data.mouse.y = pluginPoint.y;
2669 : mInstance->HandleEvent(&event, nsnull);
2670 : }
2671 : break;
2672 : }
2673 : }
2674 : break;
2675 :
2676 : case NS_KEY_EVENT:
2677 : {
2678 : const nsKeyEvent& keyEvent = static_cast<const nsKeyEvent&>(anEvent);
2679 : LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
2680 :
2681 : int modifiers = 0;
2682 : if (keyEvent.isShift)
2683 : modifiers |= kShift_ANPKeyModifier;
2684 : if (keyEvent.isAlt)
2685 : modifiers |= kAlt_ANPKeyModifier;
2686 :
2687 : ANPEvent event;
2688 : event.inSize = sizeof(ANPEvent);
2689 : event.eventType = kKey_ANPEventType;
2690 : event.data.key.nativeCode = keyEvent.keyCode;
2691 : event.data.key.virtualCode = keyEvent.charCode;
2692 : event.data.key.modifiers = modifiers;
2693 : event.data.key.repeatCount = 0;
2694 : event.data.key.unichar = 0;
2695 : switch (anEvent.message)
2696 : {
2697 : case NS_KEY_DOWN:
2698 : event.data.key.action = kDown_ANPKeyAction;
2699 : mInstance->HandleEvent(&event, nsnull);
2700 : break;
2701 :
2702 : case NS_KEY_UP:
2703 : event.data.key.action = kUp_ANPKeyAction;
2704 : mInstance->HandleEvent(&event, nsnull);
2705 : break;
2706 : }
2707 : }
2708 : }
2709 : rv = nsEventStatus_eConsumeNoDefault;
2710 : #endif
2711 :
2712 0 : return rv;
2713 : }
2714 :
2715 : nsresult
2716 0 : nsPluginInstanceOwner::Destroy()
2717 : {
2718 0 : if (mObjectFrame)
2719 0 : mObjectFrame->SetInstanceOwner(nsnull);
2720 :
2721 : #ifdef MAC_CARBON_PLUGINS
2722 : // stop the timer explicitly to reduce reference count.
2723 : CancelTimer();
2724 : #endif
2725 : #ifdef XP_MACOSX
2726 : RemoveFromCARefreshTimer();
2727 : if (mColorProfile)
2728 : ::CGColorSpaceRelease(mColorProfile);
2729 : #endif
2730 :
2731 : // unregister context menu listener
2732 0 : if (mCXMenuListener) {
2733 0 : mCXMenuListener->Destroy(mContent);
2734 0 : mCXMenuListener = nsnull;
2735 : }
2736 :
2737 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("focus"), this, false);
2738 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("blur"), this, false);
2739 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, false);
2740 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, false);
2741 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false);
2742 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
2743 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dblclick"), this, false);
2744 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false);
2745 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
2746 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
2747 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
2748 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
2749 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true);
2750 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), this, true);
2751 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("drag"), this, true);
2752 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragenter"), this, true);
2753 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragover"), this, true);
2754 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragleave"), this, true);
2755 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragexit"), this, true);
2756 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
2757 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, true);
2758 0 : mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, true);
2759 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
2760 : mContent->RemoveEventListener(NS_LITERAL_STRING("text"), this, true);
2761 : #endif
2762 :
2763 : #if MOZ_WIDGET_ANDROID
2764 : RemovePluginView();
2765 :
2766 : if (mLayer)
2767 : mLayer->SetVisible(false);
2768 :
2769 : #endif
2770 :
2771 0 : if (mWidget) {
2772 0 : if (mPluginWindow) {
2773 0 : mPluginWindow->SetPluginWidget(nsnull);
2774 : }
2775 :
2776 0 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
2777 0 : if (pluginWidget) {
2778 0 : pluginWidget->SetPluginInstanceOwner(nsnull);
2779 : }
2780 0 : mWidget->Destroy();
2781 : }
2782 :
2783 0 : return NS_OK;
2784 : }
2785 :
2786 : // Paints are handled differently, so we just simulate an update event.
2787 :
2788 : #ifdef XP_MACOSX
2789 : void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgContext)
2790 : {
2791 : if (!mInstance || !mObjectFrame)
2792 : return;
2793 :
2794 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
2795 : if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
2796 : #ifndef NP_NO_CARBON
2797 : void* window = FixUpPluginWindow(ePluginPaintEnable);
2798 : if (GetEventModel() == NPEventModelCarbon && window) {
2799 : EventRecord updateEvent;
2800 : InitializeEventRecord(&updateEvent, nsnull);
2801 : updateEvent.what = updateEvt;
2802 : updateEvent.message = UInt32(window);
2803 :
2804 : mInstance->HandleEvent(&updateEvent, nsnull);
2805 : } else if (GetEventModel() == NPEventModelCocoa)
2806 : #endif
2807 : {
2808 : DoCocoaEventDrawRect(aDirtyRect, cgContext);
2809 : }
2810 : pluginWidget->EndDrawPlugin();
2811 : }
2812 : }
2813 :
2814 : void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
2815 : {
2816 : if (!mInstance || !mObjectFrame)
2817 : return;
2818 :
2819 : // The context given here is only valid during the HandleEvent call.
2820 : NPCocoaEvent updateEvent;
2821 : InitializeNPCocoaEvent(&updateEvent);
2822 : updateEvent.type = NPCocoaEventDrawRect;
2823 : updateEvent.data.draw.context = cgContext;
2824 : updateEvent.data.draw.x = aDrawRect.X();
2825 : updateEvent.data.draw.y = aDrawRect.Y();
2826 : updateEvent.data.draw.width = aDrawRect.Width();
2827 : updateEvent.data.draw.height = aDrawRect.Height();
2828 :
2829 : mInstance->HandleEvent(&updateEvent, nsnull);
2830 : }
2831 : #endif
2832 :
2833 : #ifdef XP_WIN
2834 : void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC)
2835 : {
2836 : if (!mInstance || !mObjectFrame)
2837 : return;
2838 :
2839 : NPEvent pluginEvent;
2840 : pluginEvent.event = WM_PAINT;
2841 : pluginEvent.wParam = WPARAM(aDC);
2842 : pluginEvent.lParam = LPARAM(&aDirty);
2843 : mInstance->HandleEvent(&pluginEvent, nsnull);
2844 : }
2845 : #endif
2846 :
2847 : #ifdef XP_OS2
2848 : void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
2849 : {
2850 : if (!mInstance || !mObjectFrame)
2851 : return;
2852 :
2853 : NPWindow *window;
2854 : GetWindow(window);
2855 : nsIntRect relDirtyRect = aDirtyRect.ToOutsidePixels(mObjectFrame->PresContext()->AppUnitsPerDevPixel());
2856 :
2857 : // we got dirty rectangle in relative window coordinates, but we
2858 : // need it in absolute units and in the (left, top, right, bottom) form
2859 : RECTL rectl;
2860 : rectl.xLeft = relDirtyRect.x + window->x;
2861 : rectl.yBottom = relDirtyRect.y + window->y;
2862 : rectl.xRight = rectl.xLeft + relDirtyRect.width;
2863 : rectl.yTop = rectl.yBottom + relDirtyRect.height;
2864 :
2865 : NPEvent pluginEvent;
2866 : pluginEvent.event = WM_PAINT;
2867 : pluginEvent.wParam = (uint32)aHPS;
2868 : pluginEvent.lParam = (uint32)&rectl;
2869 : mInstance->HandleEvent(&pluginEvent, nsnull);
2870 : }
2871 : #endif
2872 :
2873 : #ifdef MOZ_WIDGET_ANDROID
2874 :
2875 : void nsPluginInstanceOwner::Paint(gfxContext* aContext,
2876 : const gfxRect& aFrameRect,
2877 : const gfxRect& aDirtyRect)
2878 : {
2879 : if (!mInstance || !mObjectFrame || !mPluginDocumentActiveState)
2880 : return;
2881 :
2882 : PRInt32 model = mInstance->GetANPDrawingModel();
2883 :
2884 : if (model == kSurface_ANPDrawingModel) {
2885 : if (!AddPluginView(aFrameRect)) {
2886 : Invalidate();
2887 : }
2888 : return;
2889 : }
2890 :
2891 : if (model == kOpenGL_ANPDrawingModel) {
2892 : if (!mLayer)
2893 : mLayer = new AndroidMediaLayer();
2894 :
2895 : // FIXME: this is gross
2896 : float zoomLevel = aFrameRect.width / (float)mPluginWindow->width;
2897 : mLayer->UpdatePosition(aFrameRect, zoomLevel);
2898 :
2899 : SendSize((int)aFrameRect.width, (int)aFrameRect.height);
2900 : return;
2901 : }
2902 :
2903 : if (model != kBitmap_ANPDrawingModel)
2904 : return;
2905 :
2906 : #ifdef ANP_BITMAP_DRAWING_MODEL
2907 : static nsRefPtr<gfxImageSurface> pluginSurface;
2908 :
2909 : if (pluginSurface == nsnull ||
2910 : aFrameRect.width != pluginSurface->Width() ||
2911 : aFrameRect.height != pluginSurface->Height()) {
2912 :
2913 : pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height),
2914 : gfxImageSurface::ImageFormatARGB32);
2915 : if (!pluginSurface)
2916 : return;
2917 : }
2918 :
2919 : // Clears buffer. I think this is needed.
2920 : nsRefPtr<gfxContext> ctx = new gfxContext(pluginSurface);
2921 : ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
2922 : ctx->Paint();
2923 :
2924 : ANPEvent event;
2925 : event.inSize = sizeof(ANPEvent);
2926 : event.eventType = 4;
2927 : event.data.draw.model = 1;
2928 :
2929 : event.data.draw.clip.top = 0;
2930 : event.data.draw.clip.left = 0;
2931 : event.data.draw.clip.bottom = aFrameRect.width;
2932 : event.data.draw.clip.right = aFrameRect.height;
2933 :
2934 : event.data.draw.data.bitmap.format = kRGBA_8888_ANPBitmapFormat;
2935 : event.data.draw.data.bitmap.width = aFrameRect.width;
2936 : event.data.draw.data.bitmap.height = aFrameRect.height;
2937 : event.data.draw.data.bitmap.baseAddr = pluginSurface->Data();
2938 : event.data.draw.data.bitmap.rowBytes = aFrameRect.width * 4;
2939 :
2940 : if (!mInstance)
2941 : return;
2942 :
2943 : mInstance->HandleEvent(&event, nsnull);
2944 :
2945 : aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
2946 : aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y));
2947 : aContext->Clip(aFrameRect);
2948 : aContext->Paint();
2949 : #endif
2950 : }
2951 : #endif
2952 :
2953 : #if defined(MOZ_X11)
2954 0 : void nsPluginInstanceOwner::Paint(gfxContext* aContext,
2955 : const gfxRect& aFrameRect,
2956 : const gfxRect& aDirtyRect)
2957 : {
2958 0 : if (!mInstance || !mObjectFrame)
2959 0 : return;
2960 :
2961 : // to provide crisper and faster drawing.
2962 0 : gfxRect pluginRect = aFrameRect;
2963 0 : if (aContext->UserToDevicePixelSnapped(pluginRect)) {
2964 0 : pluginRect = aContext->DeviceToUser(pluginRect);
2965 : }
2966 :
2967 : // Round out the dirty rect to plugin pixels to ensure the plugin draws
2968 : // enough pixels for interpolation to device pixels.
2969 0 : gfxRect dirtyRect = aDirtyRect - pluginRect.TopLeft();
2970 0 : dirtyRect.RoundOut();
2971 :
2972 : // Plugins can only draw an integer number of pixels.
2973 : //
2974 : // With translation-only transformation matrices, pluginRect is already
2975 : // pixel-aligned.
2976 : //
2977 : // With more complex transformations, modifying the scales in the
2978 : // transformation matrix could retain subpixel accuracy and let the plugin
2979 : // draw a suitable number of pixels for interpolation to device pixels in
2980 : // Renderer::Draw, but such cases are not common enough to warrant the
2981 : // effort now.
2982 : nsIntSize pluginSize(NS_lround(pluginRect.width),
2983 0 : NS_lround(pluginRect.height));
2984 :
2985 : // Determine what the plugin needs to draw.
2986 : nsIntRect pluginDirtyRect(PRInt32(dirtyRect.x),
2987 : PRInt32(dirtyRect.y),
2988 : PRInt32(dirtyRect.width),
2989 0 : PRInt32(dirtyRect.height));
2990 0 : if (!pluginDirtyRect.
2991 : IntersectRect(nsIntRect(0, 0, pluginSize.width, pluginSize.height),
2992 0 : pluginDirtyRect))
2993 0 : return;
2994 :
2995 : NPWindow* window;
2996 0 : GetWindow(window);
2997 :
2998 0 : PRUint32 rendererFlags = 0;
2999 0 : if (!mFlash10Quirks) {
3000 : rendererFlags |=
3001 : Renderer::DRAW_SUPPORTS_CLIP_RECT |
3002 0 : Renderer::DRAW_SUPPORTS_ALTERNATE_VISUAL;
3003 : }
3004 :
3005 : bool transparent;
3006 0 : mInstance->IsTransparent(&transparent);
3007 0 : if (!transparent)
3008 0 : rendererFlags |= Renderer::DRAW_IS_OPAQUE;
3009 :
3010 : // Renderer::Draw() draws a rectangle with top-left at the aContext origin.
3011 0 : gfxContextAutoSaveRestore autoSR(aContext);
3012 0 : aContext->Translate(pluginRect.TopLeft());
3013 :
3014 0 : Renderer renderer(window, this, pluginSize, pluginDirtyRect);
3015 : #ifdef MOZ_WIDGET_GTK2
3016 : // This is the visual used by the widgets, 24-bit if available.
3017 0 : GdkVisual* gdkVisual = gdk_rgb_get_visual();
3018 0 : Visual* visual = gdk_x11_visual_get_xvisual(gdkVisual);
3019 : Screen* screen =
3020 0 : gdk_x11_screen_get_xscreen(gdk_visual_get_screen(gdkVisual));
3021 : #endif
3022 : #ifdef MOZ_WIDGET_QT
3023 : Display* dpy = QX11Info().display();
3024 : Screen* screen = ScreenOfDisplay(dpy, QX11Info().screen());
3025 : Visual* visual = static_cast<Visual*>(QX11Info().visual());
3026 : #endif
3027 : renderer.Draw(aContext, nsIntSize(window->width, window->height),
3028 0 : rendererFlags, screen, visual, nsnull);
3029 : }
3030 : nsresult
3031 0 : nsPluginInstanceOwner::Renderer::DrawWithXlib(gfxXlibSurface* xsurface,
3032 : nsIntPoint offset,
3033 : nsIntRect *clipRects,
3034 : PRUint32 numClipRects)
3035 : {
3036 0 : Screen *screen = cairo_xlib_surface_get_screen(xsurface->CairoSurface());
3037 : Colormap colormap;
3038 : Visual* visual;
3039 0 : if (!xsurface->GetColormapAndVisual(&colormap, &visual)) {
3040 0 : NS_ERROR("Failed to get visual and colormap");
3041 0 : return NS_ERROR_UNEXPECTED;
3042 : }
3043 :
3044 0 : nsNPAPIPluginInstance *instance = mInstanceOwner->mInstance;
3045 0 : if (!instance)
3046 0 : return NS_ERROR_FAILURE;
3047 :
3048 : // See if the plugin must be notified of new window parameters.
3049 0 : bool doupdatewindow = false;
3050 :
3051 0 : if (mWindow->x != offset.x || mWindow->y != offset.y) {
3052 0 : mWindow->x = offset.x;
3053 0 : mWindow->y = offset.y;
3054 0 : doupdatewindow = true;
3055 : }
3056 :
3057 0 : if (nsIntSize(mWindow->width, mWindow->height) != mPluginSize) {
3058 0 : mWindow->width = mPluginSize.width;
3059 0 : mWindow->height = mPluginSize.height;
3060 0 : doupdatewindow = true;
3061 : }
3062 :
3063 : // The clip rect is relative to drawable top-left.
3064 0 : NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!");
3065 0 : nsIntRect clipRect;
3066 0 : if (numClipRects) {
3067 0 : clipRect.x = clipRects[0].x;
3068 0 : clipRect.y = clipRects[0].y;
3069 0 : clipRect.width = clipRects[0].width;
3070 0 : clipRect.height = clipRects[0].height;
3071 : // NPRect members are unsigned, but clip rectangles should be contained by
3072 : // the surface.
3073 0 : NS_ASSERTION(clipRect.x >= 0 && clipRect.y >= 0,
3074 : "Clip rectangle offsets are negative!");
3075 : }
3076 : else {
3077 0 : clipRect.x = offset.x;
3078 0 : clipRect.y = offset.y;
3079 0 : clipRect.width = mWindow->width;
3080 0 : clipRect.height = mWindow->height;
3081 : // Don't ask the plugin to draw outside the drawable.
3082 : // This also ensures that the unsigned clip rectangle offsets won't be -ve.
3083 0 : gfxIntSize surfaceSize = xsurface->GetSize();
3084 : clipRect.IntersectRect(clipRect,
3085 : nsIntRect(0, 0,
3086 0 : surfaceSize.width, surfaceSize.height));
3087 : }
3088 :
3089 : NPRect newClipRect;
3090 0 : newClipRect.left = clipRect.x;
3091 0 : newClipRect.top = clipRect.y;
3092 0 : newClipRect.right = clipRect.XMost();
3093 0 : newClipRect.bottom = clipRect.YMost();
3094 0 : if (mWindow->clipRect.left != newClipRect.left ||
3095 : mWindow->clipRect.top != newClipRect.top ||
3096 : mWindow->clipRect.right != newClipRect.right ||
3097 : mWindow->clipRect.bottom != newClipRect.bottom) {
3098 0 : mWindow->clipRect = newClipRect;
3099 0 : doupdatewindow = true;
3100 : }
3101 :
3102 : NPSetWindowCallbackStruct* ws_info =
3103 0 : static_cast<NPSetWindowCallbackStruct*>(mWindow->ws_info);
3104 : #ifdef MOZ_X11
3105 0 : if (ws_info->visual != visual || ws_info->colormap != colormap) {
3106 0 : ws_info->visual = visual;
3107 0 : ws_info->colormap = colormap;
3108 0 : ws_info->depth = gfxXlibSurface::DepthOfVisual(screen, visual);
3109 0 : doupdatewindow = true;
3110 : }
3111 : #endif
3112 :
3113 : {
3114 0 : if (doupdatewindow)
3115 0 : instance->SetWindow(mWindow);
3116 : }
3117 :
3118 : // Translate the dirty rect to drawable coordinates.
3119 0 : nsIntRect dirtyRect = mDirtyRect + offset;
3120 0 : if (mInstanceOwner->mFlash10Quirks) {
3121 : // Work around a bug in Flash up to 10.1 d51 at least, where expose event
3122 : // top left coordinates within the plugin-rect and not at the drawable
3123 : // origin are misinterpreted. (We can move the top left coordinate
3124 : // provided it is within the clipRect.)
3125 : dirtyRect.SetRect(offset.x, offset.y,
3126 0 : mDirtyRect.XMost(), mDirtyRect.YMost());
3127 : }
3128 : // Intersect the dirty rect with the clip rect to ensure that it lies within
3129 : // the drawable.
3130 0 : if (!dirtyRect.IntersectRect(dirtyRect, clipRect))
3131 0 : return NS_OK;
3132 :
3133 : {
3134 0 : XEvent pluginEvent = XEvent();
3135 0 : XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
3136 : // set the drawing info
3137 0 : exposeEvent.type = GraphicsExpose;
3138 0 : exposeEvent.display = DisplayOfScreen(screen);
3139 0 : exposeEvent.drawable = xsurface->XDrawable();
3140 0 : exposeEvent.x = dirtyRect.x;
3141 0 : exposeEvent.y = dirtyRect.y;
3142 0 : exposeEvent.width = dirtyRect.width;
3143 0 : exposeEvent.height = dirtyRect.height;
3144 0 : exposeEvent.count = 0;
3145 : // information not set:
3146 0 : exposeEvent.serial = 0;
3147 0 : exposeEvent.send_event = False;
3148 0 : exposeEvent.major_code = 0;
3149 0 : exposeEvent.minor_code = 0;
3150 :
3151 0 : instance->HandleEvent(&pluginEvent, nsnull);
3152 : }
3153 0 : return NS_OK;
3154 : }
3155 : #endif
3156 :
3157 0 : void nsPluginInstanceOwner::SendIdleEvent()
3158 : {
3159 : #ifdef MAC_CARBON_PLUGINS
3160 : // validate the plugin clipping information by syncing the plugin window info to
3161 : // reflect the current widget location. This makes sure that everything is updated
3162 : // correctly in the event of scrolling in the window.
3163 : if (mInstance) {
3164 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
3165 : if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
3166 : void* window = FixUpPluginWindow(ePluginPaintEnable);
3167 : if (window) {
3168 : EventRecord idleEvent;
3169 : InitializeEventRecord(&idleEvent, nsnull);
3170 : idleEvent.what = nullEvent;
3171 :
3172 : // give a bogus 'where' field of our null event when hidden, so Flash
3173 : // won't respond to mouse moves in other tabs, see bug 120875
3174 : if (!mWidgetVisible)
3175 : idleEvent.where.h = idleEvent.where.v = 20000;
3176 :
3177 : mInstance->HandleEvent(&idleEvent, nsnull);
3178 : }
3179 :
3180 : pluginWidget->EndDrawPlugin();
3181 : }
3182 : }
3183 : #endif
3184 0 : }
3185 :
3186 : #ifdef MAC_CARBON_PLUGINS
3187 : void nsPluginInstanceOwner::StartTimer(bool isVisible)
3188 : {
3189 : if (GetEventModel() != NPEventModelCarbon)
3190 : return;
3191 :
3192 : mPluginHost->AddIdleTimeTarget(this, isVisible);
3193 : }
3194 :
3195 : void nsPluginInstanceOwner::CancelTimer()
3196 : {
3197 : mPluginHost->RemoveIdleTimeTarget(this);
3198 : }
3199 : #endif
3200 :
3201 0 : nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
3202 : {
3203 0 : mLastEventloopNestingLevel = GetEventloopNestingLevel();
3204 :
3205 0 : mContent = aContent;
3206 :
3207 : // Get a frame, don't reflow. If a reflow was necessary it should have been
3208 : // done at a higher level than this (content).
3209 0 : nsIFrame* frame = aContent->GetPrimaryFrame();
3210 0 : nsIObjectFrame* iObjFrame = do_QueryFrame(frame);
3211 0 : nsObjectFrame* objFrame = static_cast<nsObjectFrame*>(iObjFrame);
3212 0 : if (objFrame) {
3213 0 : SetFrame(objFrame);
3214 : // Some plugins require a specific sequence of shutdown and startup when
3215 : // a page is reloaded. Shutdown happens usually when the last instance
3216 : // is destroyed. Here we make sure the plugin instance in the old
3217 : // document is destroyed before we try to create the new one.
3218 0 : objFrame->PresContext()->EnsureVisible();
3219 : } else {
3220 0 : return NS_ERROR_FAILURE;
3221 : }
3222 :
3223 : // register context menu listener
3224 0 : mCXMenuListener = new nsPluginDOMContextMenuListener();
3225 0 : if (mCXMenuListener) {
3226 0 : mCXMenuListener->Init(aContent);
3227 : }
3228 :
3229 0 : mContent->AddEventListener(NS_LITERAL_STRING("focus"), this, false,
3230 0 : false);
3231 0 : mContent->AddEventListener(NS_LITERAL_STRING("blur"), this, false,
3232 0 : false);
3233 0 : mContent->AddEventListener(NS_LITERAL_STRING("mouseup"), this, false,
3234 0 : false);
3235 0 : mContent->AddEventListener(NS_LITERAL_STRING("mousedown"), this, false,
3236 0 : false);
3237 0 : mContent->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false,
3238 0 : false);
3239 0 : mContent->AddEventListener(NS_LITERAL_STRING("click"), this, false,
3240 0 : false);
3241 0 : mContent->AddEventListener(NS_LITERAL_STRING("dblclick"), this, false,
3242 0 : false);
3243 0 : mContent->AddEventListener(NS_LITERAL_STRING("mouseover"), this, false,
3244 0 : false);
3245 0 : mContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false,
3246 0 : false);
3247 0 : mContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
3248 0 : mContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
3249 0 : mContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
3250 0 : mContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true);
3251 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragdrop"), this, true);
3252 0 : mContent->AddEventListener(NS_LITERAL_STRING("drag"), this, true);
3253 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragenter"), this, true);
3254 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragover"), this, true);
3255 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragleave"), this, true);
3256 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, true);
3257 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
3258 0 : mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
3259 0 : mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
3260 : #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
3261 : mContent->AddEventListener(NS_LITERAL_STRING("text"), this, true);
3262 : #endif
3263 :
3264 0 : return NS_OK;
3265 : }
3266 :
3267 0 : void* nsPluginInstanceOwner::GetPluginPortFromWidget()
3268 : {
3269 : //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
3270 :
3271 0 : void* result = NULL;
3272 0 : if (mWidget) {
3273 : #ifdef XP_WIN
3274 : if (mPluginWindow && (mPluginWindow->type == NPWindowTypeDrawable))
3275 : result = mWidget->GetNativeData(NS_NATIVE_GRAPHIC);
3276 : else
3277 : #endif
3278 : #ifdef XP_MACOSX
3279 : if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
3280 : GetDrawingModel() == NPDrawingModelCoreAnimation ||
3281 : GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
3282 : result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG);
3283 : else
3284 : #endif
3285 0 : result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
3286 : }
3287 0 : return result;
3288 : }
3289 :
3290 0 : void nsPluginInstanceOwner::ReleasePluginPort(void * pluginPort)
3291 : {
3292 : #ifdef XP_WIN
3293 : if (mWidget && mPluginWindow &&
3294 : mPluginWindow->type == NPWindowTypeDrawable) {
3295 : mWidget->FreeNativeData((HDC)pluginPort, NS_NATIVE_GRAPHIC);
3296 : }
3297 : #endif
3298 0 : }
3299 :
3300 0 : NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
3301 : {
3302 0 : NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
3303 :
3304 0 : nsresult rv = NS_ERROR_FAILURE;
3305 :
3306 : // Can't call this twice!
3307 0 : if (mWidget) {
3308 0 : NS_WARNING("Trying to create a plugin widget twice!");
3309 0 : return NS_ERROR_FAILURE;
3310 : }
3311 :
3312 0 : bool windowless = false;
3313 0 : mInstance->IsWindowless(&windowless);
3314 0 : if (!windowless && !nsIWidget::UsePuppetWidgets()) {
3315 : // Try to get a parent widget, on some platforms widget creation will fail without
3316 : // a parent.
3317 0 : nsCOMPtr<nsIWidget> parentWidget;
3318 0 : nsIDocument *doc = nsnull;
3319 0 : if (mContent) {
3320 0 : doc = mContent->OwnerDoc();
3321 0 : parentWidget = nsContentUtils::WidgetForDocument(doc);
3322 : }
3323 :
3324 0 : mWidget = do_CreateInstance(kWidgetCID, &rv);
3325 0 : if (NS_FAILED(rv)) {
3326 0 : return rv;
3327 : }
3328 :
3329 0 : nsWidgetInitData initData;
3330 0 : initData.mWindowType = eWindowType_plugin;
3331 0 : initData.mUnicode = false;
3332 0 : initData.clipChildren = true;
3333 0 : initData.clipSiblings = true;
3334 0 : rv = mWidget->Create(parentWidget.get(), nsnull, nsIntRect(0,0,0,0),
3335 0 : nsnull, nsnull, &initData);
3336 0 : if (NS_FAILED(rv)) {
3337 0 : mWidget->Destroy();
3338 0 : mWidget = nsnull;
3339 0 : return rv;
3340 : }
3341 :
3342 0 : mWidget->EnableDragDrop(true);
3343 0 : mWidget->Show(false);
3344 0 : mWidget->Enable(false);
3345 :
3346 : #ifdef XP_MACOSX
3347 : // Now that we have a widget we want to set the event model before
3348 : // any events are processed.
3349 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
3350 : if (!pluginWidget) {
3351 : return NS_ERROR_FAILURE;
3352 : }
3353 : pluginWidget->SetPluginEventModel(GetEventModel());
3354 : pluginWidget->SetPluginDrawingModel(GetDrawingModel());
3355 :
3356 : if (GetDrawingModel() == NPDrawingModelCoreAnimation) {
3357 : AddToCARefreshTimer();
3358 : }
3359 : #endif
3360 : }
3361 :
3362 0 : if (mObjectFrame) {
3363 : // NULL widget is fine, will result in windowless setup.
3364 0 : mObjectFrame->PrepForDrawing(mWidget);
3365 : }
3366 :
3367 0 : if (windowless) {
3368 0 : mPluginWindow->type = NPWindowTypeDrawable;
3369 :
3370 : // this needs to be a HDC according to the spec, but I do
3371 : // not see the right way to release it so let's postpone
3372 : // passing HDC till paint event when it is really
3373 : // needed. Change spec?
3374 0 : mPluginWindow->window = nsnull;
3375 : #ifdef MOZ_X11
3376 : // Fill in the display field.
3377 : NPSetWindowCallbackStruct* ws_info =
3378 0 : static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
3379 0 : ws_info->display = DefaultXDisplay();
3380 :
3381 0 : nsCAutoString description;
3382 0 : GetPluginDescription(description);
3383 0 : NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
3384 0 : mFlash10Quirks = StringBeginsWith(description, flash10Head);
3385 : #endif
3386 0 : } else if (mWidget) {
3387 : // mPluginWindow->type is used in |GetPluginPort| so it must
3388 : // be initialized first
3389 0 : mPluginWindow->type = NPWindowTypeWindow;
3390 0 : mPluginWindow->window = GetPluginPortFromWidget();
3391 : #ifdef MAC_CARBON_PLUGINS
3392 : // start the idle timer.
3393 : StartTimer(true);
3394 : #endif
3395 : // tell the plugin window about the widget
3396 0 : mPluginWindow->SetPluginWidget(mWidget);
3397 :
3398 : // tell the widget about the current plugin instance owner.
3399 0 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
3400 0 : if (pluginWidget) {
3401 0 : pluginWidget->SetPluginInstanceOwner(this);
3402 : }
3403 : }
3404 :
3405 0 : mWidgetCreationComplete = true;
3406 :
3407 0 : return NS_OK;
3408 : }
3409 :
3410 : // Mac specific code to fix up the port location and clipping region
3411 : #ifdef XP_MACOSX
3412 :
3413 : void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
3414 : {
3415 : if (!mWidget || !mPluginWindow || !mInstance || !mObjectFrame)
3416 : return nsnull;
3417 :
3418 : NPDrawingModel drawingModel = GetDrawingModel();
3419 : NPEventModel eventModel = GetEventModel();
3420 :
3421 : nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
3422 : if (!pluginWidget)
3423 : return nsnull;
3424 :
3425 : // If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
3426 : // don't want calls to SetPluginPortAndDetectChange() to step on our work.
3427 : void* pluginPort = nsnull;
3428 : if (mInCGPaintLevel > 0) {
3429 : pluginPort = mPluginWindow->window;
3430 : } else {
3431 : pluginPort = SetPluginPortAndDetectChange();
3432 : }
3433 :
3434 : #ifdef MAC_CARBON_PLUGINS
3435 : if (eventModel == NPEventModelCarbon && !pluginPort)
3436 : return nsnull;
3437 : #endif
3438 :
3439 : // We'll need the top-level Cocoa window for the Cocoa event model.
3440 : void* cocoaTopLevelWindow = nsnull;
3441 : if (eventModel == NPEventModelCocoa) {
3442 : nsIWidget* widget = mObjectFrame->GetNearestWidget();
3443 : if (!widget)
3444 : return nsnull;
3445 : cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW);
3446 : if (!cocoaTopLevelWindow)
3447 : return nsnull;
3448 : }
3449 :
3450 : nsIntPoint pluginOrigin;
3451 : nsIntRect widgetClip;
3452 : bool widgetVisible;
3453 : pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible);
3454 : mWidgetVisible = widgetVisible;
3455 :
3456 : // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
3457 :
3458 : #ifndef NP_NO_QUICKDRAW
3459 : // set the port coordinates
3460 : if (drawingModel == NPDrawingModelQuickDraw) {
3461 : mPluginWindow->x = -static_cast<NP_Port*>(pluginPort)->portx;
3462 : mPluginWindow->y = -static_cast<NP_Port*>(pluginPort)->porty;
3463 : }
3464 : else if (drawingModel == NPDrawingModelCoreGraphics ||
3465 : drawingModel == NPDrawingModelCoreAnimation ||
3466 : drawingModel == NPDrawingModelInvalidatingCoreAnimation)
3467 : #endif
3468 : {
3469 : // This would be a lot easier if we could use obj-c here,
3470 : // but we can't. Since we have only nsIWidget and we can't
3471 : // use its native widget (an obj-c object) we have to go
3472 : // from the widget's screen coordinates to its window coords
3473 : // instead of straight to window coords.
3474 : nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
3475 :
3476 : nsRect windowRect;
3477 : #ifndef NP_NO_CARBON
3478 : if (eventModel == NPEventModelCarbon)
3479 : NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef>(static_cast<NP_CGContext*>(pluginPort)->window), windowRect);
3480 : else
3481 : #endif
3482 : {
3483 : NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
3484 : }
3485 :
3486 : mPluginWindow->x = geckoScreenCoords.x - windowRect.x;
3487 : mPluginWindow->y = geckoScreenCoords.y - windowRect.y;
3488 : }
3489 :
3490 : NPRect oldClipRect = mPluginWindow->clipRect;
3491 :
3492 : // fix up the clipping region
3493 : mPluginWindow->clipRect.top = widgetClip.y;
3494 : mPluginWindow->clipRect.left = widgetClip.x;
3495 :
3496 : if (!mWidgetVisible || inPaintState == ePluginPaintDisable) {
3497 : mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
3498 : mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
3499 : }
3500 : else if (inPaintState == ePluginPaintEnable)
3501 : {
3502 : mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top + widgetClip.height;
3503 : mPluginWindow->clipRect.right = mPluginWindow->clipRect.left + widgetClip.width;
3504 : }
3505 :
3506 : // if the clip rect changed, call SetWindow()
3507 : // (RealPlayer needs this to draw correctly)
3508 : if (mPluginWindow->clipRect.left != oldClipRect.left ||
3509 : mPluginWindow->clipRect.top != oldClipRect.top ||
3510 : mPluginWindow->clipRect.right != oldClipRect.right ||
3511 : mPluginWindow->clipRect.bottom != oldClipRect.bottom)
3512 : {
3513 : if (UseAsyncRendering()) {
3514 : mInstance->AsyncSetWindow(mPluginWindow);
3515 : }
3516 : else {
3517 : mPluginWindow->CallSetWindow(mInstance);
3518 : }
3519 : mPluginPortChanged = false;
3520 : #ifdef MAC_CARBON_PLUGINS
3521 : // if the clipRect is of size 0, make the null timer fire less often
3522 : CancelTimer();
3523 : if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
3524 : mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
3525 : StartTimer(false);
3526 : }
3527 : else {
3528 : StartTimer(true);
3529 : }
3530 : #endif
3531 : } else if (mPluginPortChanged) {
3532 : if (UseAsyncRendering()) {
3533 : mInstance->AsyncSetWindow(mPluginWindow);
3534 : }
3535 : else {
3536 : mPluginWindow->CallSetWindow(mInstance);
3537 : }
3538 : mPluginPortChanged = false;
3539 : }
3540 :
3541 : // After the first NPP_SetWindow call we need to send an initial
3542 : // top-level window focus event.
3543 : if (eventModel == NPEventModelCocoa && !mSentInitialTopLevelWindowEvent) {
3544 : // Set this before calling ProcessEvent to avoid endless recursion.
3545 : mSentInitialTopLevelWindowEvent = true;
3546 :
3547 : nsPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nsnull);
3548 : NPCocoaEvent cocoaEvent;
3549 : InitializeNPCocoaEvent(&cocoaEvent);
3550 : cocoaEvent.type = NPCocoaEventWindowFocusChanged;
3551 : cocoaEvent.data.focus.hasFocus = NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow);
3552 : pluginEvent.pluginEvent = &cocoaEvent;
3553 : ProcessEvent(pluginEvent);
3554 : }
3555 :
3556 : #ifndef NP_NO_QUICKDRAW
3557 : if (drawingModel == NPDrawingModelQuickDraw)
3558 : return ::GetWindowFromPort(static_cast<NP_Port*>(pluginPort)->port);
3559 : #endif
3560 :
3561 : #ifdef MAC_CARBON_PLUGINS
3562 : if (drawingModel == NPDrawingModelCoreGraphics && eventModel == NPEventModelCarbon)
3563 : return static_cast<NP_CGContext*>(pluginPort)->window;
3564 : #endif
3565 :
3566 : return nsnull;
3567 : }
3568 :
3569 : void
3570 : nsPluginInstanceOwner::HidePluginWindow()
3571 : {
3572 : if (!mPluginWindow || !mInstance) {
3573 : return;
3574 : }
3575 :
3576 : mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
3577 : mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
3578 : mWidgetVisible = false;
3579 : if (UseAsyncRendering()) {
3580 : mInstance->AsyncSetWindow(mPluginWindow);
3581 : } else {
3582 : mInstance->SetWindow(mPluginWindow);
3583 : }
3584 : }
3585 :
3586 : #else // XP_MACOSX
3587 :
3588 0 : void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow)
3589 : {
3590 0 : if (!mPluginWindow)
3591 0 : return;
3592 :
3593 : // For windowless plugins a non-empty clip rectangle will be
3594 : // passed to the plugin during paint, an additional update
3595 : // of the the clip rectangle here is not required
3596 0 : if (aSetWindow && !mWidget && mPluginWindowVisible && !UseAsyncRendering())
3597 0 : return;
3598 :
3599 0 : const NPWindow oldWindow = *mPluginWindow;
3600 :
3601 0 : bool windowless = (mPluginWindow->type == NPWindowTypeDrawable);
3602 0 : nsIntPoint origin = mObjectFrame->GetWindowOriginInPixels(windowless);
3603 :
3604 0 : mPluginWindow->x = origin.x;
3605 0 : mPluginWindow->y = origin.y;
3606 :
3607 0 : mPluginWindow->clipRect.left = 0;
3608 0 : mPluginWindow->clipRect.top = 0;
3609 :
3610 0 : if (mPluginWindowVisible && mPluginDocumentActiveState) {
3611 0 : mPluginWindow->clipRect.right = mPluginWindow->width;
3612 0 : mPluginWindow->clipRect.bottom = mPluginWindow->height;
3613 : } else {
3614 0 : mPluginWindow->clipRect.right = 0;
3615 0 : mPluginWindow->clipRect.bottom = 0;
3616 : }
3617 :
3618 0 : if (!aSetWindow)
3619 0 : return;
3620 :
3621 0 : if (mPluginWindow->x != oldWindow.x ||
3622 : mPluginWindow->y != oldWindow.y ||
3623 : mPluginWindow->clipRect.left != oldWindow.clipRect.left ||
3624 : mPluginWindow->clipRect.top != oldWindow.clipRect.top ||
3625 : mPluginWindow->clipRect.right != oldWindow.clipRect.right ||
3626 : mPluginWindow->clipRect.bottom != oldWindow.clipRect.bottom) {
3627 0 : CallSetWindow();
3628 : }
3629 : }
3630 :
3631 : void
3632 0 : nsPluginInstanceOwner::UpdateWindowVisibility(bool aVisible)
3633 : {
3634 0 : mPluginWindowVisible = aVisible;
3635 0 : UpdateWindowPositionAndClipRect(true);
3636 0 : }
3637 :
3638 : void
3639 0 : nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
3640 : {
3641 0 : mPluginDocumentActiveState = aIsActive;
3642 0 : UpdateWindowPositionAndClipRect(true);
3643 :
3644 : #ifdef MOZ_WIDGET_ANDROID
3645 : if (mInstance) {
3646 : if (mLayer)
3647 : mLayer->SetVisible(mPluginDocumentActiveState);
3648 :
3649 : if (!mPluginDocumentActiveState)
3650 : RemovePluginView();
3651 :
3652 : mInstance->NotifyOnScreen(mPluginDocumentActiveState);
3653 :
3654 : // This is, perhaps, incorrect. It is supposed to be sent
3655 : // when "the webview has paused or resumed". The side effect
3656 : // is that Flash video players pause or resume (if they were
3657 : // playing before) based on the value here. I personally think
3658 : // we want that on Android when switching to another tab, so
3659 : // that's why we call it here.
3660 : mInstance->NotifyForeground(mPluginDocumentActiveState);
3661 : }
3662 : #endif
3663 0 : }
3664 : #endif // XP_MACOSX
3665 :
3666 : NS_IMETHODIMP
3667 0 : nsPluginInstanceOwner::CallSetWindow()
3668 : {
3669 0 : if (mObjectFrame) {
3670 0 : mObjectFrame->CallSetWindow(false);
3671 0 : } else if (mInstance) {
3672 0 : if (UseAsyncRendering()) {
3673 0 : mInstance->AsyncSetWindow(mPluginWindow);
3674 : } else {
3675 0 : mInstance->SetWindow(mPluginWindow);
3676 : }
3677 : }
3678 :
3679 0 : return NS_OK;
3680 : }
3681 :
3682 0 : void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
3683 : {
3684 : // Don't do anything if the frame situation hasn't changed.
3685 0 : if (mObjectFrame == aFrame) {
3686 0 : return;
3687 : }
3688 :
3689 : // If we already have a frame that is changing or going away...
3690 0 : if (mObjectFrame) {
3691 : // We have an old frame.
3692 : // Drop image reference because the child may destroy the surface after we return.
3693 0 : nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
3694 0 : if (container) {
3695 : #ifdef XP_MACOSX
3696 : AutoLockImage autoLock(container);
3697 : Image *image = autoLock.GetImage();
3698 : if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
3699 : // Undo what we did to the current image in SetCurrentImage().
3700 : MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
3701 : oglImage->SetUpdateCallback(nsnull, nsnull);
3702 : oglImage->SetDestroyCallback(nsnull);
3703 : // If we have a current image here, its destructor hasn't yet been
3704 : // called, so OnDestroyImage() can't yet have been called. So we need
3705 : // to do ourselves what OnDestroyImage() would have done.
3706 : NS_RELEASE_THIS();
3707 : }
3708 : // Important! Unlock here otherwise SetCurrentImage will deadlock with
3709 : // our lock if we have a RemoteImage.
3710 : autoLock.Unlock();
3711 : #endif
3712 0 : container->SetCurrentImage(nsnull);
3713 : }
3714 :
3715 : // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
3716 : #if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
3717 : // Our frame is changing or going away, unregister for a scroll position listening.
3718 : // It's OK to unregister when we didn't register, so don't be strict about unregistering.
3719 : // Better to unregister when we didn't have to than to not unregister when we should.
3720 : for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
3721 : nsIScrollableFrame* sf = do_QueryFrame(f);
3722 : if (sf) {
3723 : sf->RemoveScrollPositionListener(this);
3724 : }
3725 : }
3726 : #endif
3727 :
3728 : // Make sure the old frame isn't holding a reference to us.
3729 0 : mObjectFrame->SetInstanceOwner(nsnull);
3730 : }
3731 :
3732 : // Swap in the new frame (or no frame)
3733 0 : mObjectFrame = aFrame;
3734 :
3735 : // Set up a new frame
3736 0 : if (mObjectFrame) {
3737 0 : mObjectFrame->SetInstanceOwner(this);
3738 : // Can only call PrepForDrawing on an object frame once. Don't do it here unless
3739 : // widget creation is complete. Doesn't matter if we actually have a widget.
3740 0 : if (mWidgetCreationComplete) {
3741 0 : mObjectFrame->PrepForDrawing(mWidget);
3742 : }
3743 0 : mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
3744 0 : mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
3745 :
3746 : // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
3747 : #if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
3748 : // We need to register as a scroll position listener on every scrollable frame up to the top.
3749 : if (GetEventModel() == NPEventModelCarbon) {
3750 : for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
3751 : nsIScrollableFrame* sf = do_QueryFrame(f);
3752 : if (sf) {
3753 : sf->AddScrollPositionListener(this);
3754 : }
3755 : }
3756 : }
3757 : #endif
3758 : }
3759 : }
3760 :
3761 0 : nsObjectFrame* nsPluginInstanceOwner::GetFrame()
3762 : {
3763 0 : return mObjectFrame;
3764 : }
3765 :
3766 : // Little helper function to resolve relative URL in
3767 : // |value| for certain inputs of |name|
3768 0 : void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
3769 : {
3770 0 : if (name.LowerCaseEqualsLiteral("pluginurl") ||
3771 0 : name.LowerCaseEqualsLiteral("pluginspage")) {
3772 0 : nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
3773 0 : nsAutoString newURL;
3774 0 : NS_MakeAbsoluteURI(newURL, value, baseURI);
3775 0 : if (!newURL.IsEmpty())
3776 0 : value = newURL;
3777 : }
3778 0 : }
3779 :
3780 : // nsPluginDOMContextMenuListener class implementation
3781 :
3782 0 : nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener()
3783 : {
3784 0 : }
3785 :
3786 0 : nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener()
3787 : {
3788 0 : }
3789 :
3790 0 : NS_IMPL_ISUPPORTS1(nsPluginDOMContextMenuListener,
3791 : nsIDOMEventListener)
3792 :
3793 : NS_IMETHODIMP
3794 0 : nsPluginDOMContextMenuListener::HandleEvent(nsIDOMEvent* aEvent)
3795 : {
3796 0 : aEvent->PreventDefault(); // consume event
3797 :
3798 0 : return NS_OK;
3799 : }
3800 :
3801 0 : nsresult nsPluginDOMContextMenuListener::Init(nsIContent* aContent)
3802 : {
3803 0 : nsCOMPtr<nsIDOMEventTarget> receiver(do_QueryInterface(aContent));
3804 0 : if (receiver) {
3805 0 : receiver->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
3806 0 : return NS_OK;
3807 : }
3808 :
3809 0 : return NS_ERROR_NO_INTERFACE;
3810 : }
3811 :
3812 0 : nsresult nsPluginDOMContextMenuListener::Destroy(nsIContent* aContent)
3813 : {
3814 : // Unregister context menu listener
3815 0 : nsCOMPtr<nsIDOMEventTarget> receiver(do_QueryInterface(aContent));
3816 0 : if (receiver) {
3817 0 : receiver->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
3818 : }
3819 :
3820 0 : return NS_OK;
3821 : }
|