dom/plugins/base/nsPluginInstanceOwner.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifdef MOZ_X11
     8 #include <cairo-xlib.h>
     9 #include "gfxXlibSurface.h"
    10 /* X headers suck */
    11 enum { XKeyPress = KeyPress };
    12 #include "mozilla/X11Util.h"
    13 using mozilla::DefaultXDisplay;
    14 #endif
    16 #include "nsPluginInstanceOwner.h"
    17 #include "nsIRunnable.h"
    18 #include "nsContentUtils.h"
    19 #include "nsRect.h"
    20 #include "nsSize.h"
    21 #include "nsDisplayList.h"
    22 #include "ImageLayers.h"
    23 #include "SharedTextureImage.h"
    24 #include "nsObjectFrame.h"
    25 #include "nsIPluginDocument.h"
    26 #include "nsIStringStream.h"
    27 #include "nsNetUtil.h"
    28 #include "mozilla/Preferences.h"
    29 #include "nsILinkHandler.h"
    30 #include "nsIDocShellTreeItem.h"
    31 #include "nsIWebBrowserChrome.h"
    32 #include "nsLayoutUtils.h"
    33 #include "nsIPluginWidget.h"
    34 #include "nsViewManager.h"
    35 #include "nsIDocShellTreeOwner.h"
    36 #include "nsIDOMHTMLObjectElement.h"
    37 #include "nsIAppShell.h"
    38 #include "nsIDOMHTMLAppletElement.h"
    39 #include "nsIObjectLoadingContent.h"
    40 #include "nsAttrName.h"
    41 #include "nsIFocusManager.h"
    42 #include "nsFocusManager.h"
    43 #include "nsIDOMDragEvent.h"
    44 #include "nsIScrollableFrame.h"
    45 #include "nsIDocShell.h"
    46 #include "ImageContainer.h"
    47 #include "nsIDOMHTMLCollection.h"
    48 #include "GLContext.h"
    49 #include "GLSharedHandleHelpers.h"
    50 #include "nsIContentInlines.h"
    51 #include "mozilla/MiscEvents.h"
    52 #include "mozilla/MouseEvents.h"
    53 #include "mozilla/TextEvents.h"
    55 #include "nsContentCID.h"
    56 #include "nsWidgetsCID.h"
    57 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
    58 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
    60 #ifdef XP_WIN
    61 #include <wtypes.h>
    62 #include <winuser.h>
    63 #endif
    65 #ifdef XP_MACOSX
    66 #include <Carbon/Carbon.h>
    67 #include "nsPluginUtilsOSX.h"
    68 #endif
    70 #if (MOZ_WIDGET_GTK == 2)
    71 #include <gdk/gdk.h>
    72 #include <gdk/gdkx.h>
    73 #include <gtk/gtk.h>
    74 #endif
    76 #ifdef MOZ_WIDGET_ANDROID
    77 #include "ANPBase.h"
    78 #include "AndroidBridge.h"
    79 #include "nsWindow.h"
    81 static nsPluginInstanceOwner* sFullScreenInstance = nullptr;
    83 using namespace mozilla::dom;
    85 #include <android/log.h>
    86 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
    87 #endif
    89 using namespace mozilla;
    90 using namespace mozilla::layers;
    92 // special class for handeling DOM context menu events because for
    93 // some reason it starves other mouse events if implemented on the
    94 // same class
    95 class nsPluginDOMContextMenuListener : public nsIDOMEventListener
    96 {
    97 public:
    98   nsPluginDOMContextMenuListener(nsIContent* aContent);
    99   virtual ~nsPluginDOMContextMenuListener();
   101   NS_DECL_ISUPPORTS
   102   NS_DECL_NSIDOMEVENTLISTENER
   104   void Destroy(nsIContent* aContent);
   106   nsEventStatus ProcessEvent(const WidgetGUIEvent& anEvent)
   107   {
   108     return nsEventStatus_eConsumeNoDefault;
   109   }
   110 };
   112 class AsyncPaintWaitEvent : public nsRunnable
   113 {
   114 public:
   115   AsyncPaintWaitEvent(nsIContent* aContent, bool aFinished) :
   116     mContent(aContent), mFinished(aFinished)
   117   {
   118   }
   120   NS_IMETHOD Run()
   121   {
   122     nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent,
   123         mFinished ? NS_LITERAL_STRING("MozPaintWaitFinished") : NS_LITERAL_STRING("MozPaintWait"),
   124         true, true);
   125     return NS_OK;
   126   }
   128 private:
   129   nsCOMPtr<nsIContent> mContent;
   130   bool                 mFinished;
   131 };
   133 void
   134 nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
   135 {
   136   // This is notification for reftests about async plugin paint start
   137   if (!mWaitingForPaint && !IsUpToDate() && aBuilder->ShouldSyncDecodeImages()) {
   138     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, false);
   139     // Run this event as soon as it's safe to do so, since listeners need to
   140     // receive it immediately
   141     mWaitingForPaint = nsContentUtils::AddScriptRunner(event);
   142   }
   143 }
   145 already_AddRefed<ImageContainer>
   146 nsPluginInstanceOwner::GetImageContainer()
   147 {
   148   if (!mInstance)
   149     return nullptr;
   151   nsRefPtr<ImageContainer> container;
   153 #if MOZ_WIDGET_ANDROID
   154   // Right now we only draw with Gecko layers on Honeycomb and higher. See Paint()
   155   // for what we do on other versions.
   156   if (AndroidBridge::Bridge()->GetAPIVersion() < 11)
   157     return nullptr;
   159   LayoutDeviceRect r = GetPluginRect();
   161   // NotifySize() causes Flash to do a bunch of stuff like ask for surfaces to render
   162   // into, set y-flip flags, etc, so we do this at the beginning.
   163   gfxSize resolution = mObjectFrame->PresContext()->PresShell()->GetCumulativeResolution();
   164   ScreenSize screenSize = (r * LayoutDeviceToScreenScale(resolution.width, resolution.height)).Size();
   165   mInstance->NotifySize(nsIntSize(screenSize.width, screenSize.height));
   167   container = LayerManager::CreateImageContainer();
   169   nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE);
   171   SharedTextureImage::Data data;
   172   data.mSize = gfx::IntSize(r.width, r.height);
   173   data.mHandle = mInstance->CreateSharedHandle();
   174   data.mShareType = mozilla::gl::SharedTextureShareType::SameProcess;
   175   data.mInverted = mInstance->Inverted();
   177   SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
   178   pluginImage->SetData(data);
   180   container->SetCurrentImageInTransaction(img);
   182   return container.forget();
   183 #endif
   185   mInstance->GetImageContainer(getter_AddRefs(container));
   186   return container.forget();
   187 }
   189 void
   190 nsPluginInstanceOwner::SetBackgroundUnknown()
   191 {
   192   if (mInstance) {
   193     mInstance->SetBackgroundUnknown();
   194   }
   195 }
   197 already_AddRefed<gfxContext>
   198 nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
   199 {
   200   nsIntRect rect = aRect;
   201   nsRefPtr<gfxContext> ctx;
   202   if (mInstance &&
   203       NS_SUCCEEDED(mInstance->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) {
   204     return ctx.forget();
   205   }
   206   return nullptr;
   207 }
   209 void
   210 nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext,
   211                                            const nsIntRect& aRect)
   212 {
   213   nsIntRect rect = aRect;
   214   if (mInstance) {
   215     mInstance->EndUpdateBackground(aContext, &rect);
   216   }
   217 }
   219 bool
   220 nsPluginInstanceOwner::UseAsyncRendering()
   221 {
   222 #ifdef XP_MACOSX
   223   if (mUseAsyncRendering) {
   224     return true;
   225   }
   226 #endif
   228   bool isOOP;
   229   bool result = (mInstance &&
   230           NS_SUCCEEDED(mInstance->GetIsOOP(&isOOP)) && isOOP
   231 #ifndef XP_MACOSX
   232           && (!mPluginWindow ||
   233            mPluginWindow->type == NPWindowTypeDrawable)
   234 #endif
   235           );
   237 #ifdef XP_MACOSX
   238   if (result) {
   239     mUseAsyncRendering = true;
   240   }
   241 #endif
   243   return result;
   244 }
   246 nsIntSize
   247 nsPluginInstanceOwner::GetCurrentImageSize()
   248 {
   249   nsIntSize size(0,0);
   250   if (mInstance) {
   251     mInstance->GetImageSize(&size);
   252   }
   253   return size;
   254 }
   256 nsPluginInstanceOwner::nsPluginInstanceOwner()
   257 {
   258   // create nsPluginNativeWindow object, it is derived from NPWindow
   259   // struct and allows to manipulate native window procedure
   260   nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
   261   mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());  
   262   if (mPluginHost)
   263     mPluginHost->NewPluginNativeWindow(&mPluginWindow);
   264   else
   265     mPluginWindow = nullptr;
   267   mObjectFrame = nullptr;
   268   mContent = nullptr;
   269   mWidgetCreationComplete = false;
   270 #ifdef XP_MACOSX
   271   memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
   272   mInCGPaintLevel = 0;
   273   mSentInitialTopLevelWindowEvent = false;
   274   mColorProfile = nullptr;
   275   mPluginPortChanged = false;
   276 #endif
   277   mContentFocused = false;
   278   mWidgetVisible = true;
   279   mPluginWindowVisible = false;
   280   mPluginDocumentActiveState = true;
   281   mNumCachedAttrs = 0;
   282   mNumCachedParams = 0;
   283   mCachedAttrParamNames = nullptr;
   284   mCachedAttrParamValues = nullptr;
   285   mLastMouseDownButtonType = -1;
   287 #ifdef XP_MACOSX
   288 #ifndef NP_NO_CARBON
   289   // We don't support Carbon, but it is still the default model for i386 NPAPI.
   290   mEventModel = NPEventModelCarbon;
   291 #else
   292   mEventModel = NPEventModelCocoa;
   293 #endif
   294   mUseAsyncRendering = false;
   295 #endif
   297   mWaitingForPaint = false;
   299 #ifdef MOZ_WIDGET_ANDROID
   300   mFullScreen = false;
   301   mJavaView = nullptr;
   302 #endif
   303 }
   305 nsPluginInstanceOwner::~nsPluginInstanceOwner()
   306 {
   307   int32_t cnt;
   309   if (mWaitingForPaint) {
   310     // We don't care when the event is dispatched as long as it's "soon",
   311     // since whoever needs it will be waiting for it.
   312     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
   313     NS_DispatchToMainThread(event);
   314   }
   316   mObjectFrame = nullptr;
   318   for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
   319     if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) {
   320       NS_Free(mCachedAttrParamNames[cnt]);
   321       mCachedAttrParamNames[cnt] = nullptr;
   322     }
   324     if (mCachedAttrParamValues && mCachedAttrParamValues[cnt]) {
   325       NS_Free(mCachedAttrParamValues[cnt]);
   326       mCachedAttrParamValues[cnt] = nullptr;
   327     }
   328   }
   330   if (mCachedAttrParamNames) {
   331     NS_Free(mCachedAttrParamNames);
   332     mCachedAttrParamNames = nullptr;
   333   }
   335   if (mCachedAttrParamValues) {
   336     NS_Free(mCachedAttrParamValues);
   337     mCachedAttrParamValues = nullptr;
   338   }
   340   PLUG_DeletePluginNativeWindow(mPluginWindow);
   341   mPluginWindow = nullptr;
   343 #ifdef MOZ_WIDGET_ANDROID
   344   RemovePluginView();
   345 #endif
   347   if (mInstance) {
   348     mInstance->SetOwner(nullptr);
   349   }
   350 }
   352 NS_IMPL_ISUPPORTS(nsPluginInstanceOwner,
   353                   nsIPluginInstanceOwner,
   354                   nsIDOMEventListener,
   355                   nsIPrivacyTransitionObserver,
   356                   nsISupportsWeakReference)
   358 nsresult
   359 nsPluginInstanceOwner::SetInstance(nsNPAPIPluginInstance *aInstance)
   360 {
   361   NS_ASSERTION(!mInstance || !aInstance, "mInstance should only be set or unset!");
   363   // If we're going to null out mInstance after use, be sure to call
   364   // mInstance->SetOwner(nullptr) here, since it now won't be called
   365   // from our destructor.  This fixes bug 613376.
   366   if (mInstance && !aInstance) {
   367     mInstance->SetOwner(nullptr);
   369 #ifdef MOZ_WIDGET_ANDROID
   370     RemovePluginView();
   371 #endif
   372   }
   374   mInstance = aInstance;
   376   nsCOMPtr<nsIDocument> doc;
   377   GetDocument(getter_AddRefs(doc));
   378   if (doc) {
   379     nsCOMPtr<nsPIDOMWindow> domWindow = doc->GetWindow();
   380     if (domWindow) {
   381       nsCOMPtr<nsIDocShell> docShell = domWindow->GetDocShell();
   382       if (docShell)
   383         docShell->AddWeakPrivacyTransitionObserver(this);
   384     }
   385   }
   387   return NS_OK;
   388 }
   390 NS_IMETHODIMP nsPluginInstanceOwner::GetWindow(NPWindow *&aWindow)
   391 {
   392   NS_ASSERTION(mPluginWindow, "the plugin window object being returned is null");
   393   aWindow = mPluginWindow;
   394   return NS_OK;
   395 }
   397 NS_IMETHODIMP nsPluginInstanceOwner::GetMode(int32_t *aMode)
   398 {
   399   nsCOMPtr<nsIDocument> doc;
   400   nsresult rv = GetDocument(getter_AddRefs(doc));
   401   nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
   403   if (pDoc) {
   404     *aMode = NP_FULL;
   405   } else {
   406     *aMode = NP_EMBED;
   407   }
   409   return rv;
   410 }
   412 NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(uint16_t& n,
   413                                                    const char*const*& names,
   414                                                    const char*const*& values)
   415 {
   416   nsresult rv = EnsureCachedAttrParamArrays();
   417   NS_ENSURE_SUCCESS(rv, rv);
   419   n = mNumCachedAttrs;
   420   names  = (const char **)mCachedAttrParamNames;
   421   values = (const char **)mCachedAttrParamValues;
   423   return rv;
   424 }
   426 NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char* *result)
   427 {
   428   NS_ENSURE_ARG_POINTER(name);
   429   NS_ENSURE_ARG_POINTER(result);
   431   nsresult rv = EnsureCachedAttrParamArrays();
   432   NS_ENSURE_SUCCESS(rv, rv);
   434   *result = nullptr;
   436   for (int i = 0; i < mNumCachedAttrs; i++) {
   437     if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
   438       *result = mCachedAttrParamValues[i];
   439       return NS_OK;
   440     }
   441   }
   443   return NS_ERROR_FAILURE;
   444 }
   446 NS_IMETHODIMP nsPluginInstanceOwner::GetDOMElement(nsIDOMElement* *result)
   447 {
   448   return CallQueryInterface(mContent, result);
   449 }
   451 nsresult nsPluginInstanceOwner::GetInstance(nsNPAPIPluginInstance **aInstance)
   452 {
   453   NS_ENSURE_ARG_POINTER(aInstance);
   455   *aInstance = mInstance;
   456   NS_IF_ADDREF(*aInstance);
   457   return NS_OK;
   458 }
   460 NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
   461                                             const char *aTarget,
   462                                             nsIInputStream *aPostStream,
   463                                             void *aHeadersData,
   464                                             uint32_t aHeadersDataLen)
   465 {
   466   NS_ENSURE_TRUE(mContent, NS_ERROR_NULL_POINTER);
   468   if (mContent->IsEditable()) {
   469     return NS_OK;
   470   }
   472   nsIDocument *doc = mContent->GetCurrentDoc();
   473   if (!doc) {
   474     return NS_ERROR_FAILURE;
   475   }
   477   nsIPresShell *presShell = doc->GetShell();
   478   if (!presShell) {
   479     return NS_ERROR_FAILURE;
   480   }
   482   nsPresContext *presContext = presShell->GetPresContext();
   483   if (!presContext) {
   484     return NS_ERROR_FAILURE;
   485   }
   487   // the container of the pres context will give us the link handler
   488   nsCOMPtr<nsISupports> container = presContext->GetContainerWeak();
   489   NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);
   490   nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
   491   NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE);
   493   nsAutoString  unitarget;
   494   unitarget.AssignASCII(aTarget); // XXX could this be nonascii?
   496   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
   498   // Create an absolute URL
   499   nsCOMPtr<nsIURI> uri;
   500   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
   502   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   504   nsCOMPtr<nsIInputStream> headersDataStream;
   505   if (aPostStream && aHeadersData) {
   506     if (!aHeadersDataLen)
   507       return NS_ERROR_UNEXPECTED;
   509     nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1");
   510     if (!sis)
   511       return NS_ERROR_OUT_OF_MEMORY;
   513     rv = sis->SetData((char *)aHeadersData, aHeadersDataLen);
   514     NS_ENSURE_SUCCESS(rv, rv);
   515     headersDataStream = do_QueryInterface(sis);
   516   }
   518   int32_t blockPopups =
   519     Preferences::GetInt("privacy.popups.disable_from_plugins");
   520   nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
   522   rv = lh->OnLinkClick(mContent, uri, unitarget.get(), NullString(),
   523                        aPostStream, headersDataStream, true);
   525   return rv;
   526 }
   528 NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg)
   529 {
   530   nsresult  rv = NS_ERROR_FAILURE;
   532   rv = this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg).get());
   534   return rv;
   535 }
   537 NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char16_t *aStatusMsg)
   538 {
   539   nsresult  rv = NS_ERROR_FAILURE;
   541   if (!mObjectFrame) {
   542     return rv;
   543   }
   544   nsCOMPtr<nsIDocShellTreeItem> docShellItem = mObjectFrame->PresContext()->GetDocShell();
   545   if (NS_FAILED(rv) || !docShellItem) {
   546     return rv;
   547   }
   549   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   550   rv = docShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
   551   if (NS_FAILED(rv) || !treeOwner) {
   552     return rv;
   553   }
   555   nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner, &rv));
   556   if (NS_FAILED(rv) || !browserChrome) {
   557     return rv;
   558   }
   559   rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT, 
   560                                 aStatusMsg);
   562   return rv;
   563 }
   565 NS_IMETHODIMP nsPluginInstanceOwner::GetDocument(nsIDocument* *aDocument)
   566 {
   567   if (!aDocument)
   568     return NS_ERROR_NULL_POINTER;
   570   // XXX sXBL/XBL2 issue: current doc or owner doc?
   571   // But keep in mind bug 322414 comment 33
   572   NS_IF_ADDREF(*aDocument = mContent->OwnerDoc());
   573   return NS_OK;
   574 }
   576 NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
   577 {
   578   // If our object frame has gone away, we won't be able to determine
   579   // up-to-date-ness, so just fire off the event.
   580   if (mWaitingForPaint && (!mObjectFrame || IsUpToDate())) {
   581     // We don't care when the event is dispatched as long as it's "soon",
   582     // since whoever needs it will be waiting for it.
   583     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
   584     NS_DispatchToMainThread(event);
   585     mWaitingForPaint = false;
   586   }
   588   if (!mObjectFrame || !invalidRect || !mWidgetVisible)
   589     return NS_ERROR_FAILURE;
   591 #if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
   592   // Each time an asynchronously-drawing plugin sends a new surface to display,
   593   // the image in the ImageContainer is updated and InvalidateRect is called.
   594   // There are different side effects for (sync) Android plugins.
   595   nsRefPtr<ImageContainer> container;
   596   mInstance->GetImageContainer(getter_AddRefs(container));
   597 #endif
   599 #ifndef XP_MACOSX
   600   // Windowed plugins should not be calling NPN_InvalidateRect, but
   601   // Silverlight does and expects it to "work"
   602   if (mWidget) {
   603     mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
   604                                   invalidRect->right - invalidRect->left,
   605                                   invalidRect->bottom - invalidRect->top));
   606     return NS_OK;
   607   }
   608 #endif
   609   nsIntRect rect(invalidRect->left,
   610                  invalidRect->top,
   611                  invalidRect->right - invalidRect->left,
   612                  invalidRect->bottom - invalidRect->top);
   613   // invalidRect is in "display pixels".  In non-HiDPI modes "display pixels"
   614   // are device pixels.  But in HiDPI modes each display pixel corresponds
   615   // to more than one device pixel.
   616   double scaleFactor = 1.0;
   617   GetContentsScaleFactor(&scaleFactor);
   618   rect.ScaleRoundOut(scaleFactor);
   619   mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
   620   return NS_OK;
   621 }
   623 NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
   624 {
   625   return NS_ERROR_NOT_IMPLEMENTED;
   626 }
   628 NS_IMETHODIMP
   629 nsPluginInstanceOwner::RedrawPlugin()
   630 {
   631   if (mObjectFrame) {
   632     mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN);
   633   }
   634   return NS_OK;
   635 }
   637 NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
   638 {
   639   if (!mObjectFrame) {
   640     NS_WARNING("plugin owner has no owner in getting doc's window handle");
   641     return NS_ERROR_FAILURE;
   642   }
   644 #if defined(XP_WIN)
   645   void** pvalue = (void**)value;
   646   nsViewManager* vm = mObjectFrame->PresContext()->GetPresShell()->GetViewManager();
   647   if (!vm)
   648     return NS_ERROR_FAILURE;
   649 #if defined(XP_WIN)
   650   // This property is provided to allow a "windowless" plugin to determine the window it is drawing
   651   // in, so it can translate mouse coordinates it receives directly from the operating system
   652   // to coordinates relative to itself.
   654   // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
   655   // 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
   657   // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
   658   // determines the window handle of the mozilla window containing the "windowless" plugin.
   660   // Given that this HWND may not be that of the document's window, there is a slight risk
   661   // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
   662   // does not suggest this HWND IS that of the document window, rather that of the window
   663   // the plugin is drawn in, this seems like a safe fix.
   665   // we only attempt to get the nearest window if this really is a "windowless" plugin so as not
   666   // to change any behaviour for the much more common windowed plugins,
   667   // though why this method would even be being called for a windowed plugin escapes me.
   668   if (mPluginWindow && mPluginWindow->type == NPWindowTypeDrawable) {
   669     // it turns out that flash also uses this window for determining focus, and is currently
   670     // unable to show a caret correctly if we return the enclosing window. Therefore for
   671     // now we only return the enclosing window when there is an actual offset which
   672     // would otherwise cause coordinates to be offset incorrectly. (i.e.
   673     // if the enclosing window if offset from the document window)
   674     //
   675     // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
   676     // does not seem to be possible without a change to the flash plugin
   678     nsIWidget* win = mObjectFrame->GetNearestWidget();
   679     if (win) {
   680       nsView *view = nsView::GetViewFor(win);
   681       NS_ASSERTION(view, "No view for widget");
   682       nsPoint offset = view->GetOffsetTo(nullptr);
   684       if (offset.x || offset.y) {
   685         // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
   686         // so that mouse co-ordinates are not messed up.
   687         *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW);
   688         if (*pvalue)
   689           return NS_OK;
   690       }
   691     }
   692   }
   693 #endif
   694   // simply return the topmost document window
   695   nsCOMPtr<nsIWidget> widget;
   696   vm->GetRootWidget(getter_AddRefs(widget));
   697   if (widget) {
   698     *pvalue = (void*)widget->GetNativeData(NS_NATIVE_WINDOW);
   699   } else {
   700     NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle");
   701   }
   703   return NS_OK;
   704 #elif (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)) && defined(MOZ_X11)
   705   // X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
   706   nsIWidget* win = mObjectFrame->GetNearestWidget();
   707   if (!win)
   708     return NS_ERROR_FAILURE;
   709   *static_cast<Window*>(value) = (long unsigned int)win->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW);
   710   return NS_OK;
   711 #else
   712   return NS_ERROR_NOT_IMPLEMENTED;
   713 #endif
   714 }
   716 NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel)
   717 {
   718 #ifdef XP_MACOSX
   719   mEventModel = static_cast<NPEventModel>(eventModel);
   720   return NS_OK;
   721 #else
   722   return NS_ERROR_NOT_IMPLEMENTED;
   723 #endif
   724 }
   726 NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
   727 {
   728   if (!menu || !event)
   729     return NPERR_GENERIC_ERROR;
   731 #ifdef XP_MACOSX
   732   if (GetEventModel() != NPEventModelCocoa)
   733     return NPERR_INCOMPATIBLE_VERSION_ERROR;
   735   return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu), mWidget,
   736                                        static_cast<NPCocoaEvent*>(event));
   737 #else
   738   return NPERR_INCOMPATIBLE_VERSION_ERROR;
   739 #endif
   740 }
   742 NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
   743                                            double *destX, double *destY, NPCoordinateSpace destSpace)
   744 {
   745 #ifdef XP_MACOSX
   746   if (!mWidget)
   747     return false;
   749   return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET),
   750                                     sourceX, sourceY, sourceSpace, destX, destY, destSpace);
   751 #else
   752   // we should implement this for all platforms
   753   return false;
   754 #endif
   755 }
   757 NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format,
   758                                                 void *initData, NPAsyncSurface *surface)
   759 {
   760   return NPERR_INCOMPATIBLE_VERSION_ERROR;
   761 }
   763 NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *)
   764 {
   765   return NPERR_INCOMPATIBLE_VERSION_ERROR;
   766 }
   768 void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*)
   769 {
   770 }
   772 NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
   773 {
   774   NS_ENSURE_ARG_POINTER(result);
   776   *result = nsPluginTagType_Unknown;
   778   nsIAtom *atom = mContent->Tag();
   780   if (atom == nsGkAtoms::applet)
   781     *result = nsPluginTagType_Applet;
   782   else if (atom == nsGkAtoms::embed)
   783     *result = nsPluginTagType_Embed;
   784   else if (atom == nsGkAtoms::object)
   785     *result = nsPluginTagType_Object;
   787   return NS_OK;
   788 }
   790 NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(uint16_t& n, const char*const*& names, const char*const*& values)
   791 {
   792   nsresult rv = EnsureCachedAttrParamArrays();
   793   NS_ENSURE_SUCCESS(rv, rv);
   795   n = mNumCachedParams;
   796   if (n) {
   797     names  = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
   798     values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
   799   } else
   800     names = values = nullptr;
   802   return rv;
   803 }
   805 NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char* *result)
   806 {
   807   NS_ENSURE_ARG_POINTER(name);
   808   NS_ENSURE_ARG_POINTER(result);
   810   nsresult rv = EnsureCachedAttrParamArrays();
   811   NS_ENSURE_SUCCESS(rv, rv);
   813   *result = nullptr;
   815   for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
   816     if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
   817       *result = mCachedAttrParamValues[i];
   818       return NS_OK;
   819     }
   820   }
   822   return NS_ERROR_FAILURE;
   823 }
   826 // Cache the attributes and/or parameters of our tag into a single set
   827 // of arrays to be compatible with Netscape 4.x. The attributes go first,
   828 // followed by a PARAM/null and then any PARAM tags. Also, hold the
   829 // cached array around for the duration of the life of the instance
   830 // because Netscape 4.x did. See bug 111008.
   831 nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
   832 {
   833   if (mCachedAttrParamValues)
   834     return NS_OK;
   836   NS_PRECONDITION(((mNumCachedAttrs + mNumCachedParams) == 0) &&
   837                     !mCachedAttrParamNames,
   838                   "re-cache of attrs/params not implemented! use the DOM "
   839                     "node directy instead");
   841   // Convert to a 16-bit count. Subtract 3 in case we add an extra
   842   // "src", "wmode", or "codebase" entry below.
   843   uint32_t cattrs = mContent->GetAttrCount();
   844   if (cattrs < 0x0000FFFC) {
   845     mNumCachedAttrs = static_cast<uint16_t>(cattrs);
   846   } else {
   847     mNumCachedAttrs = 0xFFFC;
   848   }
   850   // Check if we are java for special codebase handling
   851   const char* mime = nullptr;
   852   bool isJava = NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime &&
   853                 nsPluginHost::IsJavaMIMEType(mime);
   855   // now, we need to find all the PARAM tags that are children of us
   856   // however, be careful not to include any PARAMs that don't have us
   857   // as a direct parent. For nested object (or applet) tags, be sure
   858   // to only round up the param tags that coorespond with THIS
   859   // instance. And also, weed out any bogus tags that may get in the
   860   // way, see bug 39609. Then, with any param tag that meet our
   861   // qualification, temporarly cache them in an nsCOMArray until
   862   // we can figure out what size to make our fixed char* array.
   863   nsCOMArray<nsIDOMElement> ourParams;
   865   // Get all dependent PARAM tags, even if they are not direct children.
   866   nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent);
   867   NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
   869   // Making DOM method calls can cause our frame to go away.
   870   nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this);
   872   nsCOMPtr<nsIDOMHTMLCollection> allParams;
   873   NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
   874   mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
   875                                        getter_AddRefs(allParams));
   876   if (allParams) {
   877     uint32_t numAllParams;
   878     allParams->GetLength(&numAllParams);
   879     for (uint32_t i = 0; i < numAllParams; i++) {
   880       nsCOMPtr<nsIDOMNode> pnode;
   881       allParams->Item(i, getter_AddRefs(pnode));
   882       nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
   883       if (domelement) {
   884         // Ignore params without a name attribute.
   885         nsAutoString name;
   886         domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
   887         if (!name.IsEmpty()) {
   888           // Find the first object or applet parent.
   889           nsCOMPtr<nsIDOMNode> parent;
   890           nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
   891           nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
   892           pnode->GetParentNode(getter_AddRefs(parent));
   893           while (!(domobject || domapplet) && parent) {
   894             domobject = do_QueryInterface(parent);
   895             domapplet = do_QueryInterface(parent);
   896             nsCOMPtr<nsIDOMNode> temp;
   897             parent->GetParentNode(getter_AddRefs(temp));
   898             parent = temp;
   899           }
   900           if (domapplet || domobject) {
   901             if (domapplet) {
   902               parent = do_QueryInterface(domapplet);
   903             }
   904             else {
   905               parent = do_QueryInterface(domobject);
   906             }
   907             nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
   908             if (parent == mydomNode) {
   909               ourParams.AppendObject(domelement);
   910             }
   911           }
   912         }
   913       }
   914     }
   915   }
   917   // Convert to a 16-bit count.
   918   uint32_t cparams = ourParams.Count();
   919   if (cparams < 0x0000FFFF) {
   920     mNumCachedParams = static_cast<uint16_t>(cparams);
   921   } else {
   922     mNumCachedParams = 0xFFFF;
   923   }
   925   uint16_t numRealAttrs = mNumCachedAttrs;
   927   // Some plugins were never written to understand the "data" attribute of the OBJECT tag.
   928   // Real and WMP will not play unless they find a "src" attribute, see bug 152334.
   929   // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
   930   // look for "data", lets instead copy the "data" attribute and add another entry
   931   // to the bottom of the array if there isn't already a "src" specified.
   932   nsAutoString data;
   933   if (mContent->Tag() == nsGkAtoms::object &&
   934       !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
   935       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, data) &&
   936       !data.IsEmpty()) {
   937     mNumCachedAttrs++;
   938   }
   940   // "plugins.force.wmode" forces us to send a specific "wmode" parameter,
   941   // used by flash to select a rendering mode. Common values include
   942   // "opaque", "transparent", "windowed", "direct"
   943   nsCString wmodeType;
   944   nsAdoptingCString wmodePref = Preferences::GetCString("plugins.force.wmode");
   945   if (!wmodePref.IsEmpty()) {
   946     mNumCachedAttrs++;
   947     wmodeType = wmodePref;
   948   }
   949 #if defined(XP_WIN) || defined(XP_LINUX)
   950   // Bug 923745 - Until we support windowed mode plugins in content processes,
   951   // force flash to use a windowless rendering mode. This hack should go away
   952   // when bug 923746 lands. (OS X plugins always use some native widgets, so
   953   // unfortunately this does not help there)
   954   else if (XRE_GetProcessType() == GeckoProcessType_Content) {
   955     mNumCachedAttrs++;
   956     wmodeType.AssignLiteral("transparent");
   957   }
   958 #endif
   960   // (Bug 738396) java has quirks in its codebase parsing, pass the
   961   // absolute codebase URI as content sees it.
   962   bool addCodebase = false;
   963   nsAutoCString codebaseStr;
   964   if (isJava) {
   965     nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(mContent);
   966     NS_ENSURE_TRUE(objlc, NS_ERROR_UNEXPECTED);
   967     nsCOMPtr<nsIURI> codebaseURI;
   968     nsresult rv = objlc->GetBaseURI(getter_AddRefs(codebaseURI));
   969     NS_ENSURE_SUCCESS(rv, rv);
   970     codebaseURI->GetSpec(codebaseStr);
   971     if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) {
   972       mNumCachedAttrs++;
   973       addCodebase = true;
   974     }
   975   }
   977   mCachedAttrParamNames  = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
   978   NS_ENSURE_TRUE(mCachedAttrParamNames,  NS_ERROR_OUT_OF_MEMORY);
   979   mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
   980   NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
   982   // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
   983   // attribute order.  So we want to make sure we give the plugin the
   984   // attributes in the order they came in in the source, to be compatible with
   985   // other browsers.  Now in HTML, the storage order is the reverse of the
   986   // source order, while in XML and XHTML it's the same as the source order
   987   // (see the AddAttributes functions in the HTML and XML content sinks).
   988   int32_t start, end, increment;
   989   if (mContent->IsHTML() &&
   990       mContent->IsInHTMLDocument()) {
   991     // HTML.  Walk attributes in reverse order.
   992     start = numRealAttrs - 1;
   993     end = -1;
   994     increment = -1;
   995   } else {
   996     // XHTML or XML.  Walk attributes in forward order.
   997     start = 0;
   998     end = numRealAttrs;
   999     increment = 1;
  1002   // Set to the next slot to fill in name and value cache arrays.
  1003   uint32_t nextAttrParamIndex = 0;
  1005   // Whether or not we force the wmode below while traversing
  1006   // the name/value pairs.
  1007   bool wmodeSet = false;
  1009   // Add attribute name/value pairs.
  1010   for (int32_t index = start; index != end; index += increment) {
  1011     const nsAttrName* attrName = mContent->GetAttrNameAt(index);
  1012     nsIAtom* atom = attrName->LocalName();
  1013     nsAutoString value;
  1014     mContent->GetAttr(attrName->NamespaceID(), atom, value);
  1015     nsAutoString name;
  1016     atom->ToString(name);
  1018     FixUpURLS(name, value);
  1020     mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
  1021     if (!wmodeType.IsEmpty() &&
  1022         0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) {
  1023       mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
  1025       if (!wmodeSet) {
  1026         // We allocated space to add a wmode attr, but we don't need it now.
  1027         mNumCachedAttrs--;
  1028         wmodeSet = true;
  1030     } else if (isJava && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) {
  1031       mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
  1032     } else {
  1033       mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
  1035     nextAttrParamIndex++;
  1038   // Potentially add CODEBASE attribute
  1039   if (addCodebase) {
  1040     mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase"));
  1041     mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
  1042     nextAttrParamIndex++;
  1045   // Potentially add WMODE attribute.
  1046   if (!wmodeType.IsEmpty() && !wmodeSet) {
  1047     mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
  1048     mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
  1049     nextAttrParamIndex++;
  1052   // Potentially add SRC attribute.
  1053   if (!data.IsEmpty()) {
  1054     mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
  1055     mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data);
  1056     nextAttrParamIndex++;
  1059   // Add PARAM and null separator.
  1060   mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
  1061 #ifdef MOZ_WIDGET_ANDROID
  1062   // Flash expects an empty string on android
  1063   mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING(""));
  1064 #else
  1065   mCachedAttrParamValues[nextAttrParamIndex] = nullptr;
  1066 #endif
  1067   nextAttrParamIndex++;
  1069   // Add PARAM name/value pairs.
  1071   // We may decrement mNumCachedParams below
  1072   uint16_t totalParams = mNumCachedParams;
  1073   for (uint16_t i = 0; i < totalParams; i++) {
  1074     nsIDOMElement* param = ourParams.ObjectAt(i);
  1075     if (!param) {
  1076       continue;
  1079     nsAutoString name;
  1080     nsAutoString value;
  1081     param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
  1082     param->GetAttribute(NS_LITERAL_STRING("value"), value);
  1084     FixUpURLS(name, value);
  1086     /*
  1087      * According to the HTML 4.01 spec, at
  1088      * http://www.w3.org/TR/html4/types.html#type-cdata
  1089      * ''User agents may ignore leading and trailing
  1090      * white space in CDATA attribute values (e.g., "
  1091      * myval " may be interpreted as "myval"). Authors
  1092      * should not declare attribute values with
  1093      * leading or trailing white space.''
  1094      * However, do not trim consecutive spaces as in bug 122119
  1095      */
  1096     name.Trim(" \n\r\t\b", true, true, false);
  1097     value.Trim(" \n\r\t\b", true, true, false);
  1098     if (isJava && name.EqualsIgnoreCase("codebase")) {
  1099       // We inserted normalized codebase above, don't include other versions in
  1100       // params
  1101       mNumCachedParams--;
  1102       continue;
  1104     mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
  1105     mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
  1106     nextAttrParamIndex++;
  1109   return NS_OK;
  1112 #ifdef XP_MACOSX
  1114 static void InitializeNPCocoaEvent(NPCocoaEvent* event)
  1116   memset(event, 0, sizeof(NPCocoaEvent));
  1119 NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
  1121 #ifndef NP_NO_QUICKDRAW
  1122   // We don't support the Quickdraw drawing model any more but it's still
  1123   // the default model for i386 per NPAPI.
  1124   NPDrawingModel drawingModel = NPDrawingModelQuickDraw;
  1125 #else
  1126   NPDrawingModel drawingModel = NPDrawingModelCoreGraphics;
  1127 #endif
  1129   if (!mInstance)
  1130     return drawingModel;
  1132   mInstance->GetDrawingModel((int32_t*)&drawingModel);
  1133   return drawingModel;
  1136 bool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation()
  1138   if (!mInstance)
  1139     return false;
  1141   bool coreAnimation;
  1142   if (!NS_SUCCEEDED(mInstance->IsRemoteDrawingCoreAnimation(&coreAnimation)))
  1143     return false;
  1145   return coreAnimation;
  1148 nsresult nsPluginInstanceOwner::ContentsScaleFactorChanged(double aContentsScaleFactor)
  1150   if (!mInstance) {
  1151     return NS_ERROR_NULL_POINTER;
  1153   return mInstance->ContentsScaleFactorChanged(aContentsScaleFactor);
  1156 NPEventModel nsPluginInstanceOwner::GetEventModel()
  1158   return mEventModel;
  1161 #define DEFAULT_REFRESH_RATE 20 // 50 FPS
  1163 nsCOMPtr<nsITimer>               *nsPluginInstanceOwner::sCATimer = nullptr;
  1164 nsTArray<nsPluginInstanceOwner*> *nsPluginInstanceOwner::sCARefreshListeners = nullptr;
  1166 void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) {
  1167   if (!sCARefreshListeners) {
  1168     return;
  1170   for (size_t i = 0; i < sCARefreshListeners->Length(); i++) {
  1171     nsPluginInstanceOwner* instanceOwner = (*sCARefreshListeners)[i];
  1172     NPWindow *window;
  1173     instanceOwner->GetWindow(window);
  1174     if (!window) {
  1175       continue;
  1177     NPRect r;
  1178     r.left = 0;
  1179     r.top = 0;
  1180     r.right = window->width;
  1181     r.bottom = window->height; 
  1182     instanceOwner->InvalidateRect(&r);
  1186 void nsPluginInstanceOwner::AddToCARefreshTimer() {
  1187   if (!mInstance) {
  1188     return;
  1191   // Flash invokes InvalidateRect for us.
  1192   const char* mime = nullptr;
  1193   if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) {
  1194     if (strcmp(mime, "application/x-shockwave-flash") == 0) {
  1195       return;
  1199   if (!sCARefreshListeners) {
  1200     sCARefreshListeners = new nsTArray<nsPluginInstanceOwner*>();
  1201     if (!sCARefreshListeners) {
  1202       return;
  1206   if (sCARefreshListeners->Contains(this)) {
  1207     return;
  1210   sCARefreshListeners->AppendElement(this);
  1212   if (!sCATimer) {
  1213     sCATimer = new nsCOMPtr<nsITimer>();
  1214     if (!sCATimer) {
  1215       return;
  1219   if (sCARefreshListeners->Length() == 1) {
  1220     *sCATimer = do_CreateInstance("@mozilla.org/timer;1");
  1221     (*sCATimer)->InitWithFuncCallback(CARefresh, nullptr, 
  1222                    DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK);
  1226 void nsPluginInstanceOwner::RemoveFromCARefreshTimer() {
  1227   if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) {
  1228     return;
  1231   sCARefreshListeners->RemoveElement(this);
  1233   if (sCARefreshListeners->Length() == 0) {
  1234     if (sCATimer) {
  1235       (*sCATimer)->Cancel();
  1236       delete sCATimer;
  1237       sCATimer = nullptr;
  1239     delete sCARefreshListeners;
  1240     sCARefreshListeners = nullptr;
  1244 void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
  1245                                                 int aWidth, int aHeight)
  1247   if (aWidth == 0 || aHeight == 0)
  1248     return;
  1250   if (!mCARenderer) {
  1251     mCARenderer = new nsCARenderer();
  1254   // aWidth and aHeight are in "display pixels".  In non-HiDPI modes
  1255   // "display pixels" are device pixels.  But in HiDPI modes each
  1256   // display pixel corresponds to more than one device pixel.
  1257   double scaleFactor = 1.0;
  1258   GetContentsScaleFactor(&scaleFactor);
  1260   if (!mIOSurface ||
  1261       (mIOSurface->GetWidth() != (size_t)aWidth ||
  1262        mIOSurface->GetHeight() != (size_t)aHeight ||
  1263        mIOSurface->GetContentsScaleFactor() != scaleFactor)) {
  1264     mIOSurface = nullptr;
  1266     // If the renderer is backed by an IOSurface, resize it as required.
  1267     mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, scaleFactor);
  1268     if (mIOSurface) {
  1269       RefPtr<MacIOSurface> attachSurface = MacIOSurface::LookupSurface(
  1270                                               mIOSurface->GetIOSurfaceID(),
  1271                                               scaleFactor);
  1272       if (attachSurface) {
  1273         mCARenderer->AttachIOSurface(attachSurface);
  1274       } else {
  1275         NS_ERROR("IOSurface attachment failed");
  1276         mIOSurface = nullptr;
  1281   if (!mColorProfile) {
  1282     mColorProfile = CreateSystemColorSpace();
  1285   if (mCARenderer->isInit() == false) {
  1286     void *caLayer = nullptr;
  1287     nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer);
  1288     if (NS_FAILED(rv) || !caLayer) {
  1289       return;
  1292     // We don't run Flash in-process so we can unconditionally disallow
  1293     // the offliner renderer.
  1294     mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, scaleFactor,
  1295                                DISALLOW_OFFLINE_RENDERER);
  1297     // Setting up the CALayer requires resetting the painting otherwise we
  1298     // get garbage for the first few frames.
  1299     FixUpPluginWindow(ePluginPaintDisable);
  1300     FixUpPluginWindow(ePluginPaintEnable);
  1303   CGImageRef caImage = nullptr;
  1304   nsresult rt = mCARenderer->Render(aWidth, aHeight, scaleFactor, &caImage);
  1305   if (rt == NS_OK && mIOSurface && mColorProfile) {
  1306     nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile,
  1307                                          0, 0, aWidth, aHeight);
  1308   } else if (rt == NS_OK && caImage != nullptr) {
  1309     // Significant speed up by resetting the scaling
  1310     ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
  1311     ::CGContextTranslateCTM(aCGContext, 0, (double) aHeight * scaleFactor);
  1312     ::CGContextScaleCTM(aCGContext, scaleFactor, -scaleFactor);
  1314     ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
  1315   } else {
  1316     NS_NOTREACHED("nsCARenderer::Render failure");
  1320 void* nsPluginInstanceOwner::GetPluginPortCopy()
  1322   if (GetDrawingModel() == NPDrawingModelCoreGraphics || 
  1323       GetDrawingModel() == NPDrawingModelCoreAnimation ||
  1324       GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
  1325     return &mCGPluginPortCopy;
  1326   return nullptr;
  1329 // Currently (on OS X in Cocoa widgets) any changes made as a result of
  1330 // calling GetPluginPortFromWidget() are immediately reflected in the NPWindow
  1331 // structure that has been passed to the plugin via SetWindow().  This is
  1332 // because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG)
  1333 // always return a pointer to the same internal (private) object, but may
  1334 // make changes inside that object.  All calls to GetPluginPortFromWidget() made while
  1335 // the plugin is active (i.e. excluding those made at our initialization)
  1336 // need to take this into account.  The easiest way to do so is to replace
  1337 // them with calls to SetPluginPortAndDetectChange().  This method keeps track
  1338 // of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make
  1339 // sure SetWindow() gets called the next time through FixUpPluginWindow(), so
  1340 // that the plugin is notified of these changes.
  1341 void* nsPluginInstanceOwner::SetPluginPortAndDetectChange()
  1343   if (!mPluginWindow)
  1344     return nullptr;
  1345   void* pluginPort = GetPluginPortFromWidget();
  1346   if (!pluginPort)
  1347     return nullptr;
  1348   mPluginWindow->window = pluginPort;
  1350   return mPluginWindow->window;
  1353 void nsPluginInstanceOwner::BeginCGPaint()
  1355   ++mInCGPaintLevel;
  1358 void nsPluginInstanceOwner::EndCGPaint()
  1360   --mInCGPaintLevel;
  1361   NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
  1364 #endif
  1366 // static
  1367 uint32_t
  1368 nsPluginInstanceOwner::GetEventloopNestingLevel()
  1370   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
  1371   uint32_t currentLevel = 0;
  1372   if (appShell) {
  1373     appShell->GetEventloopNestingLevel(&currentLevel);
  1374 #ifdef XP_MACOSX
  1375     // Cocoa widget code doesn't process UI events through the normal
  1376     // appshell event loop, so it needs an additional count here.
  1377     currentLevel++;
  1378 #endif
  1381   // No idea how this happens... but Linux doesn't consistently
  1382   // process UI events through the appshell event loop. If we get a 0
  1383   // here on any platform we increment the level just in case so that
  1384   // we make sure we always tear the plugin down eventually.
  1385   if (!currentLevel) {
  1386     currentLevel++;
  1389   return currentLevel;
  1392 #ifdef MOZ_WIDGET_ANDROID
  1394 // Modified version of nsFrame::GetOffsetToCrossDoc that stops when it
  1395 // hits an element with a displayport (or runs out of frames). This is
  1396 // not really the right thing to do, but it's better than what was here before.
  1397 static nsPoint
  1398 GetOffsetRootContent(nsIFrame* aFrame)
  1400   // offset will hold the final offset
  1401   // docOffset holds the currently accumulated offset at the current APD, it
  1402   // will be converted and added to offset when the current APD changes.
  1403   nsPoint offset(0, 0), docOffset(0, 0);
  1404   const nsIFrame* f = aFrame;
  1405   int32_t currAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
  1406   int32_t apd = currAPD;
  1407   nsRect displayPort;
  1408   while (f) {
  1409     if (f->GetContent() && nsLayoutUtils::GetDisplayPort(f->GetContent(), &displayPort))
  1410       break;
  1412     docOffset += f->GetPosition();
  1413     nsIFrame* parent = f->GetParent();
  1414     if (parent) {
  1415       f = parent;
  1416     } else {
  1417       nsPoint newOffset(0, 0);
  1418       f = nsLayoutUtils::GetCrossDocParentFrame(f, &newOffset);
  1419       int32_t newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0;
  1420       if (!f || newAPD != currAPD) {
  1421         // Convert docOffset to the right APD and add it to offset.
  1422         offset += docOffset.ConvertAppUnits(currAPD, apd);
  1423         docOffset.x = docOffset.y = 0;
  1425       currAPD = newAPD;
  1426       docOffset += newOffset;
  1430   offset += docOffset.ConvertAppUnits(currAPD, apd);
  1432   return offset;
  1435 LayoutDeviceRect nsPluginInstanceOwner::GetPluginRect()
  1437   // Get the offset of the content relative to the page
  1438   nsRect bounds = mObjectFrame->GetContentRectRelativeToSelf() + GetOffsetRootContent(mObjectFrame);
  1439   LayoutDeviceIntRect rect = LayoutDeviceIntRect::FromAppUnitsToNearest(bounds, mObjectFrame->PresContext()->AppUnitsPerDevPixel());
  1440   return LayoutDeviceRect(rect);
  1443 bool nsPluginInstanceOwner::AddPluginView(const LayoutDeviceRect& aRect /* = LayoutDeviceRect(0, 0, 0, 0) */)
  1445   if (!mJavaView) {
  1446     mJavaView = mInstance->GetJavaSurface();
  1448     if (!mJavaView)
  1449       return false;
  1451     mJavaView = (void*)AndroidBridge::GetJNIEnv()->NewGlobalRef((jobject)mJavaView);
  1454   if (AndroidBridge::Bridge())
  1455     AndroidBridge::Bridge()->AddPluginView((jobject)mJavaView, aRect, mFullScreen);
  1457   if (mFullScreen)
  1458     sFullScreenInstance = this;
  1460   return true;
  1463 void nsPluginInstanceOwner::RemovePluginView()
  1465   if (!mInstance || !mJavaView)
  1466     return;
  1468   mozilla::widget::android::GeckoAppShell::RemovePluginView((jobject)mJavaView, mFullScreen);
  1469   AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView);
  1470   mJavaView = nullptr;
  1472   if (mFullScreen)
  1473     sFullScreenInstance = nullptr;
  1476 void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
  1478   if (!mInstance)
  1479     return;
  1481   mInstance->GetVideos(aVideos);
  1484 already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
  1486   nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
  1488   nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE);
  1490   SharedTextureImage::Data data;
  1492   data.mShareType = gl::SharedTextureShareType::SameProcess;
  1493   data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(),
  1494                                         data.mShareType,
  1495                                         aVideoInfo->mSurfaceTexture,
  1496                                         gl::SharedTextureBufferType::SurfaceTexture);
  1498   // The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
  1499   // inverted flag for video.
  1500   data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted();
  1501   data.mSize = gfx::IntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
  1503   SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
  1504   pluginImage->SetData(data);
  1505   container->SetCurrentImageInTransaction(img);
  1507   return container.forget();
  1510 void nsPluginInstanceOwner::Invalidate() {
  1511   NPRect rect;
  1512   rect.left = rect.top = 0;
  1513   rect.right = mPluginWindow->width;
  1514   rect.bottom = mPluginWindow->height;
  1515   InvalidateRect(&rect);
  1518 void nsPluginInstanceOwner::RequestFullScreen() {
  1519   if (mFullScreen)
  1520     return;
  1522   // Remove whatever view we currently have (if any, fullscreen or otherwise)
  1523   RemovePluginView();
  1525   mFullScreen = true;
  1526   AddPluginView();
  1528   mInstance->NotifyFullScreen(mFullScreen);
  1531 void nsPluginInstanceOwner::ExitFullScreen() {
  1532   if (!mFullScreen)
  1533     return;
  1535   RemovePluginView();
  1537   mFullScreen = false;
  1539   int32_t model = mInstance->GetANPDrawingModel();
  1541   if (model == kSurface_ANPDrawingModel) {
  1542     // We need to do this immediately, otherwise Flash
  1543     // sometimes causes a deadlock (bug 762407)
  1544     AddPluginView(GetPluginRect());
  1547   mInstance->NotifyFullScreen(mFullScreen);
  1549   // This will cause Paint() to be called, which is where
  1550   // we normally add/update views and layers
  1551   Invalidate();
  1554 void nsPluginInstanceOwner::ExitFullScreen(jobject view) {
  1555   JNIEnv* env = AndroidBridge::GetJNIEnv();
  1557   if (sFullScreenInstance && sFullScreenInstance->mInstance &&
  1558       env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) {
  1559     sFullScreenInstance->ExitFullScreen();
  1563 #endif
  1565 nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
  1567 #ifdef MOZ_WIDGET_ANDROID
  1568   if (mInstance) {
  1569     ANPEvent event;
  1570     event.inSize = sizeof(ANPEvent);
  1571     event.eventType = kLifecycle_ANPEventType;
  1573     nsAutoString eventType;
  1574     aFocusEvent->GetType(eventType);
  1575     if (eventType.EqualsLiteral("focus")) {
  1576       event.data.lifecycle.action = kGainFocus_ANPLifecycleAction;
  1578     else if (eventType.EqualsLiteral("blur")) {
  1579       event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction;
  1581     else {
  1582       NS_ASSERTION(false, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType");   
  1584     mInstance->HandleEvent(&event, nullptr);
  1586 #endif
  1588 #ifndef XP_MACOSX
  1589   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) {
  1590     // continue only for cases without child window
  1591     return aFocusEvent->PreventDefault(); // consume event
  1593 #endif
  1595   WidgetEvent* theEvent = aFocusEvent->GetInternalNSEvent();
  1596   if (theEvent) {
  1597     // we only care about the message in ProcessEvent
  1598     WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->message,
  1599                               nullptr);
  1600     nsEventStatus rv = ProcessEvent(focusEvent);
  1601     if (nsEventStatus_eConsumeNoDefault == rv) {
  1602       aFocusEvent->PreventDefault();
  1603       aFocusEvent->StopPropagation();
  1607   return NS_OK;
  1610 nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent)
  1612 #ifdef XP_MACOSX
  1613   return DispatchKeyToPlugin(aKeyEvent);
  1614 #else
  1615   if (SendNativeEvents())
  1616     DispatchKeyToPlugin(aKeyEvent);
  1618   if (mInstance) {
  1619     // If this event is going to the plugin, we want to kill it.
  1620     // Not actually sending keypress to the plugin, since we didn't before.
  1621     aKeyEvent->PreventDefault();
  1622     aKeyEvent->StopPropagation();
  1624   return NS_OK;
  1625 #endif
  1628 nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
  1630 #if !defined(XP_MACOSX)
  1631   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
  1632     return aKeyEvent->PreventDefault(); // consume event
  1633   // continue only for cases without child window
  1634 #endif
  1636   if (mInstance) {
  1637     WidgetKeyboardEvent* keyEvent =
  1638       aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
  1639     if (keyEvent && keyEvent->eventStructType == NS_KEY_EVENT) {
  1640       nsEventStatus rv = ProcessEvent(*keyEvent);
  1641       if (nsEventStatus_eConsumeNoDefault == rv) {
  1642         aKeyEvent->PreventDefault();
  1643         aKeyEvent->StopPropagation();
  1648   return NS_OK;
  1651 nsresult
  1652 nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
  1654 #if !defined(XP_MACOSX)
  1655   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
  1656     return aMouseEvent->PreventDefault(); // consume event
  1657   // continue only for cases without child window
  1658 #endif
  1660   // if the plugin is windowless, we need to set focus ourselves
  1661   // otherwise, we might not get key events
  1662   if (mObjectFrame && mPluginWindow &&
  1663       mPluginWindow->type == NPWindowTypeDrawable) {
  1665     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  1666     if (fm) {
  1667       nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
  1668       fm->SetFocus(elem, 0);
  1672   WidgetMouseEvent* mouseEvent =
  1673     aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
  1674   if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT) {
  1675     mLastMouseDownButtonType = mouseEvent->button;
  1676     nsEventStatus rv = ProcessEvent(*mouseEvent);
  1677     if (nsEventStatus_eConsumeNoDefault == rv) {
  1678       return aMouseEvent->PreventDefault(); // consume event
  1682   return NS_OK;
  1685 nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
  1686                                                       bool aAllowPropagate)
  1688 #if !defined(XP_MACOSX)
  1689   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
  1690     return aMouseEvent->PreventDefault(); // consume event
  1691   // continue only for cases without child window
  1692 #endif
  1693   // don't send mouse events if we are hidden
  1694   if (!mWidgetVisible)
  1695     return NS_OK;
  1697   WidgetMouseEvent* mouseEvent =
  1698     aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
  1699   if (mouseEvent && mouseEvent->eventStructType == NS_MOUSE_EVENT) {
  1700     nsEventStatus rv = ProcessEvent(*mouseEvent);
  1701     if (nsEventStatus_eConsumeNoDefault == rv) {
  1702       aMouseEvent->PreventDefault();
  1703       if (!aAllowPropagate) {
  1704         aMouseEvent->StopPropagation();
  1707     if (mouseEvent->message == NS_MOUSE_BUTTON_UP) {
  1708       mLastMouseDownButtonType = -1;
  1711   return NS_OK;
  1714 nsresult
  1715 nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
  1717   NS_ASSERTION(mInstance, "Should have a valid plugin instance or not receive events.");
  1719   nsAutoString eventType;
  1720   aEvent->GetType(eventType);
  1721   if (eventType.EqualsLiteral("focus")) {
  1722     mContentFocused = true;
  1723     return DispatchFocusToPlugin(aEvent);
  1725   if (eventType.EqualsLiteral("blur")) {
  1726     mContentFocused = false;
  1727     return DispatchFocusToPlugin(aEvent);
  1729   if (eventType.EqualsLiteral("mousedown")) {
  1730     return ProcessMouseDown(aEvent);
  1732   if (eventType.EqualsLiteral("mouseup")) {
  1733     // Don't send a mouse-up event to the plugin if its button type doesn't
  1734     // match that of the preceding mouse-down event (if any).  This kind of
  1735     // mismatch can happen if the previous mouse-down event was sent to a DOM
  1736     // element above the plugin, the mouse is still above the plugin, and the
  1737     // mouse-down event caused the element to disappear.  See bug 627649 and
  1738     // bug 909678.
  1739     WidgetMouseEvent* mouseEvent = aEvent->GetInternalNSEvent()->AsMouseEvent();
  1740     if (mouseEvent &&
  1741         static_cast<int>(mouseEvent->button) != mLastMouseDownButtonType) {
  1742       aEvent->PreventDefault();
  1743       return NS_OK;
  1745     return DispatchMouseToPlugin(aEvent);
  1747   if (eventType.EqualsLiteral("mousemove")) {
  1748     return DispatchMouseToPlugin(aEvent, true);
  1750   if (eventType.EqualsLiteral("click") ||
  1751       eventType.EqualsLiteral("dblclick") ||
  1752       eventType.EqualsLiteral("mouseover") ||
  1753       eventType.EqualsLiteral("mouseout")) {
  1754     return DispatchMouseToPlugin(aEvent);
  1756   if (eventType.EqualsLiteral("keydown") ||
  1757       eventType.EqualsLiteral("keyup")) {
  1758     return DispatchKeyToPlugin(aEvent);
  1760   if (eventType.EqualsLiteral("keypress")) {
  1761     return ProcessKeyPress(aEvent);
  1764   nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
  1765   if (dragEvent && mInstance) {
  1766     WidgetEvent* ievent = aEvent->GetInternalNSEvent();
  1767     if ((ievent && ievent->mFlags.mIsTrusted) &&
  1768          ievent->message != NS_DRAGDROP_ENTER && ievent->message != NS_DRAGDROP_OVER) {
  1769       aEvent->PreventDefault();
  1772     // Let the plugin handle drag events.
  1773     aEvent->StopPropagation();
  1775   return NS_OK;
  1778 #ifdef MOZ_X11
  1779 static unsigned int XInputEventState(const WidgetInputEvent& anEvent)
  1781   unsigned int state = 0;
  1782   if (anEvent.IsShift()) state |= ShiftMask;
  1783   if (anEvent.IsControl()) state |= ControlMask;
  1784   if (anEvent.IsAlt()) state |= Mod1Mask;
  1785   if (anEvent.IsMeta()) state |= Mod4Mask;
  1786   return state;
  1788 #endif
  1790 nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
  1792   nsEventStatus rv = nsEventStatus_eIgnore;
  1794   if (!mInstance || !mObjectFrame)   // if mInstance is null, we shouldn't be here
  1795     return nsEventStatus_eIgnore;
  1797 #ifdef XP_MACOSX
  1798   if (!mWidget)
  1799     return nsEventStatus_eIgnore;
  1801   // we never care about synthesized mouse enter
  1802   if (anEvent.message == NS_MOUSE_ENTER_SYNTH)
  1803     return nsEventStatus_eIgnore;
  1805   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  1806   if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin()))
  1807     return nsEventStatus_eIgnore;
  1809   NPEventModel eventModel = GetEventModel();
  1811   // If we have to synthesize an event we'll use one of these.
  1812   NPCocoaEvent synthCocoaEvent;
  1813   void* event = anEvent.pluginEvent;
  1814   nsPoint pt =
  1815   nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
  1816   mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
  1817   nsPresContext* presContext = mObjectFrame->PresContext();
  1818   // Plugin event coordinates need to be translated from device pixels
  1819   // into "display pixels" in HiDPI modes.
  1820   double scaleFactor = 1.0;
  1821   GetContentsScaleFactor(&scaleFactor);
  1822   size_t intScaleFactor = ceil(scaleFactor);
  1823   nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor,
  1824                   presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor);
  1826   if (!event) {
  1827     InitializeNPCocoaEvent(&synthCocoaEvent);
  1828     switch (anEvent.message) {
  1829       case NS_MOUSE_MOVE:
  1831         // Ignore mouse-moved events that happen as part of a dragging
  1832         // operation that started over another frame.  See bug 525078.
  1833         nsRefPtr<nsFrameSelection> frameselection = mObjectFrame->GetFrameSelection();
  1834         if (!frameselection->GetMouseDownState() ||
  1835           (nsIPresShell::GetCapturingContent() == mObjectFrame->GetContent())) {
  1836           synthCocoaEvent.type = NPCocoaEventMouseMoved;
  1837           synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
  1838           synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
  1839           event = &synthCocoaEvent;
  1842         break;
  1843       case NS_MOUSE_BUTTON_DOWN:
  1844         synthCocoaEvent.type = NPCocoaEventMouseDown;
  1845         synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
  1846         synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
  1847         event = &synthCocoaEvent;
  1848         break;
  1849       case NS_MOUSE_BUTTON_UP:
  1850         // If we're in a dragging operation that started over another frame,
  1851         // convert it into a mouse-entered event (in the Cocoa Event Model).
  1852         // See bug 525078.
  1853         if (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
  1854             (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) {
  1855           synthCocoaEvent.type = NPCocoaEventMouseEntered;
  1856           synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
  1857           synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
  1858           event = &synthCocoaEvent;
  1859         } else {
  1860           synthCocoaEvent.type = NPCocoaEventMouseUp;
  1861           synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
  1862           synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
  1863           event = &synthCocoaEvent;
  1865         break;
  1866       default:
  1867         break;
  1870     // If we still don't have an event, bail.
  1871     if (!event) {
  1872       pluginWidget->EndDrawPlugin();
  1873       return nsEventStatus_eIgnore;
  1877   int16_t response = kNPEventNotHandled;
  1878   void* window = FixUpPluginWindow(ePluginPaintEnable);
  1879   if (window || (eventModel == NPEventModelCocoa)) {
  1880     mInstance->HandleEvent(event, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  1883   if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
  1884     pluginWidget->StartComplexTextInputForCurrentEvent();
  1887   if ((response == kNPEventHandled || response == kNPEventStartIME) &&
  1888       !(anEvent.message == NS_MOUSE_BUTTON_DOWN &&
  1889         anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
  1890         !mContentFocused)) {
  1891     rv = nsEventStatus_eConsumeNoDefault;
  1894   pluginWidget->EndDrawPlugin();
  1895 #endif
  1897 #ifdef XP_WIN
  1898   // this code supports windowless plugins
  1899   NPEvent *pPluginEvent = (NPEvent*)anEvent.pluginEvent;
  1900   // we can get synthetic events from the EventStateManager... these
  1901   // have no pluginEvent
  1902   NPEvent pluginEvent;
  1903   if (anEvent.eventStructType == NS_MOUSE_EVENT) {
  1904     if (!pPluginEvent) {
  1905       // XXX Should extend this list to synthesize events for more event
  1906       // types
  1907       pluginEvent.event = 0;
  1908       const WidgetMouseEvent* mouseEvent = anEvent.AsMouseEvent();
  1909       switch (anEvent.message) {
  1910       case NS_MOUSE_MOVE:
  1911         pluginEvent.event = WM_MOUSEMOVE;
  1912         break;
  1913       case NS_MOUSE_BUTTON_DOWN: {
  1914         static const int downMsgs[] =
  1915           { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
  1916         static const int dblClickMsgs[] =
  1917           { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK };
  1918         if (mouseEvent->clickCount == 2) {
  1919           pluginEvent.event = dblClickMsgs[mouseEvent->button];
  1920         } else {
  1921           pluginEvent.event = downMsgs[mouseEvent->button];
  1923         break;
  1925       case NS_MOUSE_BUTTON_UP: {
  1926         static const int upMsgs[] =
  1927           { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
  1928         pluginEvent.event = upMsgs[mouseEvent->button];
  1929         break;
  1931       // don't synthesize anything for NS_MOUSE_DOUBLECLICK, since that
  1932       // is a synthetic event generated on mouse-up, and Windows WM_*DBLCLK
  1933       // messages are sent on mouse-down
  1934       default:
  1935         break;
  1937       if (pluginEvent.event) {
  1938         pPluginEvent = &pluginEvent;
  1939         pluginEvent.wParam =
  1940           (::GetKeyState(VK_CONTROL) ? MK_CONTROL : 0) |
  1941           (::GetKeyState(VK_SHIFT) ? MK_SHIFT : 0) |
  1942           (::GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0) |
  1943           (::GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0) |
  1944           (::GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0) |
  1945           (::GetKeyState(VK_XBUTTON1) ? MK_XBUTTON1 : 0) |
  1946           (::GetKeyState(VK_XBUTTON2) ? MK_XBUTTON2 : 0);
  1949     if (pPluginEvent) {
  1950       // Make event coordinates relative to our enclosing widget,
  1951       // not the widget they were received on.
  1952       // See use of NPEvent in widget/windows/nsWindow.cpp
  1953       // for why this assert should be safe
  1954       NS_ASSERTION(anEvent.message == NS_MOUSE_BUTTON_DOWN ||
  1955                    anEvent.message == NS_MOUSE_BUTTON_UP ||
  1956                    anEvent.message == NS_MOUSE_DOUBLECLICK ||
  1957                    anEvent.message == NS_MOUSE_ENTER_SYNTH ||
  1958                    anEvent.message == NS_MOUSE_EXIT_SYNTH ||
  1959                    anEvent.message == NS_MOUSE_MOVE,
  1960                    "Incorrect event type for coordinate translation");
  1961       nsPoint pt =
  1962         nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
  1963         mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
  1964       nsPresContext* presContext = mObjectFrame->PresContext();
  1965       nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
  1966                       presContext->AppUnitsToDevPixels(pt.y));
  1967       nsIntPoint widgetPtPx = ptPx + mObjectFrame->GetWindowOriginInPixels(true);
  1968       pPluginEvent->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y);
  1971   else if (!pPluginEvent) {
  1972     switch (anEvent.message) {
  1973       case NS_FOCUS_CONTENT:
  1974         pluginEvent.event = WM_SETFOCUS;
  1975         pluginEvent.wParam = 0;
  1976         pluginEvent.lParam = 0;
  1977         pPluginEvent = &pluginEvent;
  1978         break;
  1979       case NS_BLUR_CONTENT:
  1980         pluginEvent.event = WM_KILLFOCUS;
  1981         pluginEvent.wParam = 0;
  1982         pluginEvent.lParam = 0;
  1983         pPluginEvent = &pluginEvent;
  1984         break;
  1988   if (pPluginEvent && !pPluginEvent->event) {
  1989     // Don't send null events to plugins.
  1990     NS_WARNING("nsObjectFrame ProcessEvent: trying to send null event to plugin.");
  1991     return rv;
  1994   if (pPluginEvent) {
  1995     int16_t response = kNPEventNotHandled;
  1996     mInstance->HandleEvent(pPluginEvent, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  1997     if (response == kNPEventHandled)
  1998       rv = nsEventStatus_eConsumeNoDefault;
  2000 #endif
  2002 #ifdef MOZ_X11
  2003   // this code supports windowless plugins
  2004   nsIWidget* widget = anEvent.widget;
  2005   XEvent pluginEvent = XEvent();
  2006   pluginEvent.type = 0;
  2008   switch(anEvent.eventStructType)
  2010     case NS_MOUSE_EVENT:
  2012         switch (anEvent.message)
  2014           case NS_MOUSE_CLICK:
  2015           case NS_MOUSE_DOUBLECLICK:
  2016             // Button up/down events sent instead.
  2017             return rv;
  2020         // Get reference point relative to plugin origin.
  2021         const nsPresContext* presContext = mObjectFrame->PresContext();
  2022         nsPoint appPoint =
  2023           nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
  2024           mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
  2025         nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
  2026                                presContext->AppUnitsToDevPixels(appPoint.y));
  2027         const WidgetMouseEvent& mouseEvent = *anEvent.AsMouseEvent();
  2028         // Get reference point relative to screen:
  2029         LayoutDeviceIntPoint rootPoint(-1, -1);
  2030         if (widget)
  2031           rootPoint = anEvent.refPoint +
  2032             LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset());
  2033 #ifdef MOZ_WIDGET_GTK
  2034         Window root = GDK_ROOT_WINDOW();
  2035 #elif defined(MOZ_WIDGET_QT)
  2036         Window root = RootWindowOfScreen(DefaultScreenOfDisplay(mozilla::DefaultXDisplay()));
  2037 #else
  2038         Window root = None; // Could XQueryTree, but this is not important.
  2039 #endif
  2041         switch (anEvent.message)
  2043           case NS_MOUSE_ENTER_SYNTH:
  2044           case NS_MOUSE_EXIT_SYNTH:
  2046               XCrossingEvent& event = pluginEvent.xcrossing;
  2047               event.type = anEvent.message == NS_MOUSE_ENTER_SYNTH ?
  2048                 EnterNotify : LeaveNotify;
  2049               event.root = root;
  2050               event.time = anEvent.time;
  2051               event.x = pluginPoint.x;
  2052               event.y = pluginPoint.y;
  2053               event.x_root = rootPoint.x;
  2054               event.y_root = rootPoint.y;
  2055               event.state = XInputEventState(mouseEvent);
  2056               // information lost
  2057               event.subwindow = None;
  2058               event.mode = -1;
  2059               event.detail = NotifyDetailNone;
  2060               event.same_screen = True;
  2061               event.focus = mContentFocused;
  2063             break;
  2064           case NS_MOUSE_MOVE:
  2066               XMotionEvent& event = pluginEvent.xmotion;
  2067               event.type = MotionNotify;
  2068               event.root = root;
  2069               event.time = anEvent.time;
  2070               event.x = pluginPoint.x;
  2071               event.y = pluginPoint.y;
  2072               event.x_root = rootPoint.x;
  2073               event.y_root = rootPoint.y;
  2074               event.state = XInputEventState(mouseEvent);
  2075               // information lost
  2076               event.subwindow = None;
  2077               event.is_hint = NotifyNormal;
  2078               event.same_screen = True;
  2080             break;
  2081           case NS_MOUSE_BUTTON_DOWN:
  2082           case NS_MOUSE_BUTTON_UP:
  2084               XButtonEvent& event = pluginEvent.xbutton;
  2085               event.type = anEvent.message == NS_MOUSE_BUTTON_DOWN ?
  2086                 ButtonPress : ButtonRelease;
  2087               event.root = root;
  2088               event.time = anEvent.time;
  2089               event.x = pluginPoint.x;
  2090               event.y = pluginPoint.y;
  2091               event.x_root = rootPoint.x;
  2092               event.y_root = rootPoint.y;
  2093               event.state = XInputEventState(mouseEvent);
  2094               switch (mouseEvent.button)
  2096                 case WidgetMouseEvent::eMiddleButton:
  2097                   event.button = 2;
  2098                   break;
  2099                 case WidgetMouseEvent::eRightButton:
  2100                   event.button = 3;
  2101                   break;
  2102                 default: // WidgetMouseEvent::eLeftButton;
  2103                   event.button = 1;
  2104                   break;
  2106               // information lost:
  2107               event.subwindow = None;
  2108               event.same_screen = True;
  2110             break;
  2113       break;
  2115    //XXX case NS_MOUSE_SCROLL_EVENT: not received.
  2117    case NS_KEY_EVENT:
  2118       if (anEvent.pluginEvent)
  2120           XKeyEvent &event = pluginEvent.xkey;
  2121 #ifdef MOZ_WIDGET_GTK
  2122           event.root = GDK_ROOT_WINDOW();
  2123           event.time = anEvent.time;
  2124           const GdkEventKey* gdkEvent =
  2125             static_cast<const GdkEventKey*>(anEvent.pluginEvent);
  2126           event.keycode = gdkEvent->hardware_keycode;
  2127           event.state = gdkEvent->state;
  2128           switch (anEvent.message)
  2130             case NS_KEY_DOWN:
  2131               // Handle NS_KEY_DOWN for modifier key presses
  2132               // For non-modifiers we get NS_KEY_PRESS
  2133               if (gdkEvent->is_modifier)
  2134                 event.type = XKeyPress;
  2135               break;
  2136             case NS_KEY_PRESS:
  2137               event.type = XKeyPress;
  2138               break;
  2139             case NS_KEY_UP:
  2140               event.type = KeyRelease;
  2141               break;
  2143 #endif
  2145           // Information that could be obtained from pluginEvent but we may not
  2146           // want to promise to provide:
  2147           event.subwindow = None;
  2148           event.x = 0;
  2149           event.y = 0;
  2150           event.x_root = -1;
  2151           event.y_root = -1;
  2152           event.same_screen = False;
  2154       else
  2156           // If we need to send synthesized key events, then
  2157           // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
  2158           // gdk_keymap_get_entries_for_keyval will be useful, but the
  2159           // mappings will not be unique.
  2160           NS_WARNING("Synthesized key event not sent to plugin");
  2162       break;
  2164     default: 
  2165       switch (anEvent.message)
  2167         case NS_FOCUS_CONTENT:
  2168         case NS_BLUR_CONTENT:
  2170             XFocusChangeEvent &event = pluginEvent.xfocus;
  2171             event.type =
  2172               anEvent.message == NS_FOCUS_CONTENT ? FocusIn : FocusOut;
  2173             // information lost:
  2174             event.mode = -1;
  2175             event.detail = NotifyDetailNone;
  2177           break;
  2181   if (!pluginEvent.type) {
  2182     return rv;
  2185   // Fill in (useless) generic event information.
  2186   XAnyEvent& event = pluginEvent.xany;
  2187   event.display = widget ?
  2188     static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nullptr;
  2189   event.window = None; // not a real window
  2190   // information lost:
  2191   event.serial = 0;
  2192   event.send_event = False;
  2194   int16_t response = kNPEventNotHandled;
  2195   mInstance->HandleEvent(&pluginEvent, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  2196   if (response == kNPEventHandled)
  2197     rv = nsEventStatus_eConsumeNoDefault;
  2198 #endif
  2200 #ifdef MOZ_WIDGET_ANDROID
  2201   // this code supports windowless plugins
  2203     // The plugin needs focus to receive keyboard and touch events
  2204     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  2205     if (fm) {
  2206       nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
  2207       fm->SetFocus(elem, 0);
  2210   switch(anEvent.eventStructType)
  2212     case NS_MOUSE_EVENT:
  2214         switch (anEvent.message)
  2216           case NS_MOUSE_CLICK:
  2217           case NS_MOUSE_DOUBLECLICK:
  2218             // Button up/down events sent instead.
  2219             return rv;
  2222         // Get reference point relative to plugin origin.
  2223         const nsPresContext* presContext = mObjectFrame->PresContext();
  2224         nsPoint appPoint =
  2225           nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
  2226           mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
  2227         nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
  2228                                presContext->AppUnitsToDevPixels(appPoint.y));
  2230         switch (anEvent.message)
  2232           case NS_MOUSE_MOVE:
  2234               // are these going to be touch events?
  2235               // pluginPoint.x;
  2236               // pluginPoint.y;
  2238             break;
  2239           case NS_MOUSE_BUTTON_DOWN:
  2241               ANPEvent event;
  2242               event.inSize = sizeof(ANPEvent);
  2243               event.eventType = kMouse_ANPEventType;
  2244               event.data.mouse.action = kDown_ANPMouseAction;
  2245               event.data.mouse.x = pluginPoint.x;
  2246               event.data.mouse.y = pluginPoint.y;
  2247               mInstance->HandleEvent(&event, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  2249             break;
  2250           case NS_MOUSE_BUTTON_UP:
  2252               ANPEvent event;
  2253               event.inSize = sizeof(ANPEvent);
  2254               event.eventType = kMouse_ANPEventType;
  2255               event.data.mouse.action = kUp_ANPMouseAction;
  2256               event.data.mouse.x = pluginPoint.x;
  2257               event.data.mouse.y = pluginPoint.y;
  2258               mInstance->HandleEvent(&event, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  2260             break;
  2263       break;
  2265     case NS_KEY_EVENT:
  2267        const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
  2268        LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
  2269        // pluginEvent is initialized by nsWindow::InitKeyEvent().
  2270        ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent);
  2271        if (pluginEvent) {
  2272          MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent));
  2273          MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType);
  2274          mInstance->HandleEvent(pluginEvent, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
  2277      break;
  2279     default:
  2280       break;
  2282     rv = nsEventStatus_eConsumeNoDefault;
  2283 #endif
  2285   return rv;
  2288 nsresult
  2289 nsPluginInstanceOwner::Destroy()
  2291   SetFrame(nullptr);
  2293 #ifdef XP_MACOSX
  2294   RemoveFromCARefreshTimer();
  2295   if (mColorProfile)
  2296     ::CGColorSpaceRelease(mColorProfile);
  2297 #endif
  2299   // unregister context menu listener
  2300   if (mCXMenuListener) {
  2301     mCXMenuListener->Destroy(mContent);
  2302     mCXMenuListener = nullptr;
  2305   mContent->RemoveEventListener(NS_LITERAL_STRING("focus"), this, false);
  2306   mContent->RemoveEventListener(NS_LITERAL_STRING("blur"), this, false);
  2307   mContent->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, false);
  2308   mContent->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, false);
  2309   mContent->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false);
  2310   mContent->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
  2311   mContent->RemoveEventListener(NS_LITERAL_STRING("dblclick"), this, false);
  2312   mContent->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false);
  2313   mContent->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
  2314   mContent->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
  2315   mContent->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
  2316   mContent->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
  2317   mContent->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true);
  2318   mContent->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), this, true);
  2319   mContent->RemoveEventListener(NS_LITERAL_STRING("drag"), this, true);
  2320   mContent->RemoveEventListener(NS_LITERAL_STRING("dragenter"), this, true);
  2321   mContent->RemoveEventListener(NS_LITERAL_STRING("dragover"), this, true);
  2322   mContent->RemoveEventListener(NS_LITERAL_STRING("dragleave"), this, true);
  2323   mContent->RemoveEventListener(NS_LITERAL_STRING("dragexit"), this, true);
  2324   mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
  2325   mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, true);
  2326   mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, true);
  2328 #if MOZ_WIDGET_ANDROID
  2329   RemovePluginView();
  2330 #endif
  2332   if (mWidget) {
  2333     if (mPluginWindow) {
  2334       mPluginWindow->SetPluginWidget(nullptr);
  2337     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  2338     if (pluginWidget) {
  2339       pluginWidget->SetPluginInstanceOwner(nullptr);
  2341     mWidget->Destroy();
  2344   return NS_OK;
  2347 // Paints are handled differently, so we just simulate an update event.
  2349 #ifdef XP_MACOSX
  2350 void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgContext)
  2352   if (!mInstance || !mObjectFrame)
  2353     return;
  2355   gfxRect dirtyRectCopy = aDirtyRect; 
  2356   double scaleFactor = 1.0;
  2357   GetContentsScaleFactor(&scaleFactor);
  2358   if (scaleFactor != 1.0) {
  2359     ::CGContextScaleCTM(cgContext, scaleFactor, scaleFactor);
  2360     // Convert aDirtyRect from device pixels to "display pixels"
  2361     // for HiDPI modes
  2362     dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor);
  2365   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  2366   if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
  2367     DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
  2368     pluginWidget->EndDrawPlugin();
  2372 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
  2374   if (!mInstance || !mObjectFrame)
  2375     return;
  2377   // The context given here is only valid during the HandleEvent call.
  2378   NPCocoaEvent updateEvent;
  2379   InitializeNPCocoaEvent(&updateEvent);
  2380   updateEvent.type = NPCocoaEventDrawRect;
  2381   updateEvent.data.draw.context = cgContext;
  2382   updateEvent.data.draw.x = aDrawRect.X();
  2383   updateEvent.data.draw.y = aDrawRect.Y();
  2384   updateEvent.data.draw.width = aDrawRect.Width();
  2385   updateEvent.data.draw.height = aDrawRect.Height();
  2387   mInstance->HandleEvent(&updateEvent, nullptr);
  2389 #endif
  2391 #ifdef XP_WIN
  2392 void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC)
  2394   if (!mInstance || !mObjectFrame)
  2395     return;
  2397   NPEvent pluginEvent;
  2398   pluginEvent.event = WM_PAINT;
  2399   pluginEvent.wParam = WPARAM(aDC);
  2400   pluginEvent.lParam = LPARAM(&aDirty);
  2401   mInstance->HandleEvent(&pluginEvent, nullptr);
  2403 #endif
  2405 #ifdef MOZ_WIDGET_ANDROID
  2407 void nsPluginInstanceOwner::Paint(gfxContext* aContext,
  2408                                   const gfxRect& aFrameRect,
  2409                                   const gfxRect& aDirtyRect)
  2411   if (!mInstance || !mObjectFrame || !mPluginDocumentActiveState || mFullScreen)
  2412     return;
  2414   int32_t model = mInstance->GetANPDrawingModel();
  2416   if (model == kSurface_ANPDrawingModel) {
  2417     if (!AddPluginView(GetPluginRect())) {
  2418       Invalidate();
  2420     return;
  2423   if (model != kBitmap_ANPDrawingModel)
  2424     return;
  2426 #ifdef ANP_BITMAP_DRAWING_MODEL
  2427   static nsRefPtr<gfxImageSurface> pluginSurface;
  2429   if (pluginSurface == nullptr ||
  2430       aFrameRect.width  != pluginSurface->Width() ||
  2431       aFrameRect.height != pluginSurface->Height()) {
  2433     pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height), 
  2434                                         gfxImageFormat::ARGB32);
  2435     if (!pluginSurface)
  2436       return;
  2439   // Clears buffer.  I think this is needed.
  2440   nsRefPtr<gfxContext> ctx = new gfxContext(pluginSurface);
  2441   ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
  2442   ctx->Paint();
  2444   ANPEvent event;
  2445   event.inSize = sizeof(ANPEvent);
  2446   event.eventType = 4;
  2447   event.data.draw.model = 1;
  2449   event.data.draw.clip.top     = 0;
  2450   event.data.draw.clip.left    = 0;
  2451   event.data.draw.clip.bottom  = aFrameRect.width;
  2452   event.data.draw.clip.right   = aFrameRect.height;
  2454   event.data.draw.data.bitmap.format   = kRGBA_8888_ANPBitmapFormat;
  2455   event.data.draw.data.bitmap.width    = aFrameRect.width;
  2456   event.data.draw.data.bitmap.height   = aFrameRect.height;
  2457   event.data.draw.data.bitmap.baseAddr = pluginSurface->Data();
  2458   event.data.draw.data.bitmap.rowBytes = aFrameRect.width * 4;
  2460   if (!mInstance)
  2461     return;
  2463   mInstance->HandleEvent(&event, nullptr);
  2465   aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
  2466   aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y));
  2467   aContext->Clip(aFrameRect);
  2468   aContext->Paint();
  2469 #endif
  2471 #endif
  2473 #if defined(MOZ_X11)
  2474 void nsPluginInstanceOwner::Paint(gfxContext* aContext,
  2475                                   const gfxRect& aFrameRect,
  2476                                   const gfxRect& aDirtyRect)
  2478   if (!mInstance || !mObjectFrame)
  2479     return;
  2481   // to provide crisper and faster drawing.
  2482   gfxRect pluginRect = aFrameRect;
  2483   if (aContext->UserToDevicePixelSnapped(pluginRect)) {
  2484     pluginRect = aContext->DeviceToUser(pluginRect);
  2487   // Round out the dirty rect to plugin pixels to ensure the plugin draws
  2488   // enough pixels for interpolation to device pixels.
  2489   gfxRect dirtyRect = aDirtyRect - pluginRect.TopLeft();
  2490   dirtyRect.RoundOut();
  2492   // Plugins can only draw an integer number of pixels.
  2493   //
  2494   // With translation-only transformation matrices, pluginRect is already
  2495   // pixel-aligned.
  2496   //
  2497   // With more complex transformations, modifying the scales in the
  2498   // transformation matrix could retain subpixel accuracy and let the plugin
  2499   // draw a suitable number of pixels for interpolation to device pixels in
  2500   // Renderer::Draw, but such cases are not common enough to warrant the
  2501   // effort now.
  2502   nsIntSize pluginSize(NS_lround(pluginRect.width),
  2503                        NS_lround(pluginRect.height));
  2505   // Determine what the plugin needs to draw.
  2506   nsIntRect pluginDirtyRect(int32_t(dirtyRect.x),
  2507                             int32_t(dirtyRect.y),
  2508                             int32_t(dirtyRect.width),
  2509                             int32_t(dirtyRect.height));
  2510   if (!pluginDirtyRect.
  2511       IntersectRect(nsIntRect(0, 0, pluginSize.width, pluginSize.height),
  2512                     pluginDirtyRect))
  2513     return;
  2515   NPWindow* window;
  2516   GetWindow(window);
  2518   uint32_t rendererFlags = 0;
  2519   if (!mFlash10Quirks) {
  2520     rendererFlags |=
  2521       Renderer::DRAW_SUPPORTS_CLIP_RECT |
  2522       Renderer::DRAW_SUPPORTS_ALTERNATE_VISUAL;
  2525   bool transparent;
  2526   mInstance->IsTransparent(&transparent);
  2527   if (!transparent)
  2528     rendererFlags |= Renderer::DRAW_IS_OPAQUE;
  2530   // Renderer::Draw() draws a rectangle with top-left at the aContext origin.
  2531   gfxContextAutoSaveRestore autoSR(aContext);
  2532   aContext->Translate(pluginRect.TopLeft());
  2534   Renderer renderer(window, this, pluginSize, pluginDirtyRect);
  2536   Display* dpy = mozilla::DefaultXDisplay();
  2537   Screen* screen = DefaultScreenOfDisplay(dpy);
  2538   Visual* visual = DefaultVisualOfScreen(screen);
  2540   renderer.Draw(aContext, nsIntSize(window->width, window->height),
  2541                 rendererFlags, screen, visual);
  2543 nsresult
  2544 nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface,
  2545                                               nsIntPoint offset,
  2546                                               nsIntRect *clipRects, 
  2547                                               uint32_t numClipRects)
  2549   Screen *screen = cairo_xlib_surface_get_screen(xsurface);
  2550   Colormap colormap;
  2551   Visual* visual;
  2552   if (!gfxXlibSurface::GetColormapAndVisual(xsurface, &colormap, &visual)) {
  2553     NS_ERROR("Failed to get visual and colormap");
  2554     return NS_ERROR_UNEXPECTED;
  2557   nsNPAPIPluginInstance *instance = mInstanceOwner->mInstance;
  2558   if (!instance)
  2559     return NS_ERROR_FAILURE;
  2561   // See if the plugin must be notified of new window parameters.
  2562   bool doupdatewindow = false;
  2564   if (mWindow->x != offset.x || mWindow->y != offset.y) {
  2565     mWindow->x = offset.x;
  2566     mWindow->y = offset.y;
  2567     doupdatewindow = true;
  2570   if (nsIntSize(mWindow->width, mWindow->height) != mPluginSize) {
  2571     mWindow->width = mPluginSize.width;
  2572     mWindow->height = mPluginSize.height;
  2573     doupdatewindow = true;
  2576   // The clip rect is relative to drawable top-left.
  2577   NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!");
  2578   nsIntRect clipRect;
  2579   if (numClipRects) {
  2580     clipRect.x = clipRects[0].x;
  2581     clipRect.y = clipRects[0].y;
  2582     clipRect.width  = clipRects[0].width;
  2583     clipRect.height = clipRects[0].height;
  2584     // NPRect members are unsigned, but clip rectangles should be contained by
  2585     // the surface.
  2586     NS_ASSERTION(clipRect.x >= 0 && clipRect.y >= 0,
  2587                  "Clip rectangle offsets are negative!");
  2589   else {
  2590     clipRect.x = offset.x;
  2591     clipRect.y = offset.y;
  2592     clipRect.width  = mWindow->width;
  2593     clipRect.height = mWindow->height;
  2594     // Don't ask the plugin to draw outside the drawable.
  2595     // This also ensures that the unsigned clip rectangle offsets won't be -ve.
  2596     clipRect.IntersectRect(clipRect,
  2597                            nsIntRect(0, 0,
  2598                                      cairo_xlib_surface_get_width(xsurface),
  2599                                      cairo_xlib_surface_get_height(xsurface)));
  2602   NPRect newClipRect;
  2603   newClipRect.left = clipRect.x;
  2604   newClipRect.top = clipRect.y;
  2605   newClipRect.right = clipRect.XMost();
  2606   newClipRect.bottom = clipRect.YMost();
  2607   if (mWindow->clipRect.left    != newClipRect.left   ||
  2608       mWindow->clipRect.top     != newClipRect.top    ||
  2609       mWindow->clipRect.right   != newClipRect.right  ||
  2610       mWindow->clipRect.bottom  != newClipRect.bottom) {
  2611     mWindow->clipRect = newClipRect;
  2612     doupdatewindow = true;
  2615   NPSetWindowCallbackStruct* ws_info = 
  2616     static_cast<NPSetWindowCallbackStruct*>(mWindow->ws_info);
  2617 #ifdef MOZ_X11
  2618   if (ws_info->visual != visual || ws_info->colormap != colormap) {
  2619     ws_info->visual = visual;
  2620     ws_info->colormap = colormap;
  2621     ws_info->depth = gfxXlibSurface::DepthOfVisual(screen, visual);
  2622     doupdatewindow = true;
  2624 #endif
  2627     if (doupdatewindow)
  2628       instance->SetWindow(mWindow);
  2631   // Translate the dirty rect to drawable coordinates.
  2632   nsIntRect dirtyRect = mDirtyRect + offset;
  2633   if (mInstanceOwner->mFlash10Quirks) {
  2634     // Work around a bug in Flash up to 10.1 d51 at least, where expose event
  2635     // top left coordinates within the plugin-rect and not at the drawable
  2636     // origin are misinterpreted.  (We can move the top left coordinate
  2637     // provided it is within the clipRect.)
  2638     dirtyRect.SetRect(offset.x, offset.y,
  2639                       mDirtyRect.XMost(), mDirtyRect.YMost());
  2641   // Intersect the dirty rect with the clip rect to ensure that it lies within
  2642   // the drawable.
  2643   if (!dirtyRect.IntersectRect(dirtyRect, clipRect))
  2644     return NS_OK;
  2647     XEvent pluginEvent = XEvent();
  2648     XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
  2649     // set the drawing info
  2650     exposeEvent.type = GraphicsExpose;
  2651     exposeEvent.display = DisplayOfScreen(screen);
  2652     exposeEvent.drawable = cairo_xlib_surface_get_drawable(xsurface);
  2653     exposeEvent.x = dirtyRect.x;
  2654     exposeEvent.y = dirtyRect.y;
  2655     exposeEvent.width  = dirtyRect.width;
  2656     exposeEvent.height = dirtyRect.height;
  2657     exposeEvent.count = 0;
  2658     // information not set:
  2659     exposeEvent.serial = 0;
  2660     exposeEvent.send_event = False;
  2661     exposeEvent.major_code = 0;
  2662     exposeEvent.minor_code = 0;
  2664     instance->HandleEvent(&pluginEvent, nullptr);
  2666   return NS_OK;
  2668 #endif
  2670 nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
  2672   mLastEventloopNestingLevel = GetEventloopNestingLevel();
  2674   mContent = aContent;
  2676   // Get a frame, don't reflow. If a reflow was necessary it should have been
  2677   // done at a higher level than this (content).
  2678   nsIFrame* frame = aContent->GetPrimaryFrame();
  2679   nsIObjectFrame* iObjFrame = do_QueryFrame(frame);
  2680   nsObjectFrame* objFrame =  static_cast<nsObjectFrame*>(iObjFrame);
  2681   if (objFrame) {
  2682     SetFrame(objFrame);
  2683     // Some plugins require a specific sequence of shutdown and startup when
  2684     // a page is reloaded. Shutdown happens usually when the last instance
  2685     // is destroyed. Here we make sure the plugin instance in the old
  2686     // document is destroyed before we try to create the new one.
  2687     objFrame->PresContext()->EnsureVisible();
  2688   } else {
  2689     NS_NOTREACHED("Should not be initializing plugin without a frame");
  2690     return NS_ERROR_FAILURE;
  2693   // register context menu listener
  2694   mCXMenuListener = new nsPluginDOMContextMenuListener(aContent);
  2696   mContent->AddEventListener(NS_LITERAL_STRING("focus"), this, false,
  2697                              false);
  2698   mContent->AddEventListener(NS_LITERAL_STRING("blur"), this, false,
  2699                              false);
  2700   mContent->AddEventListener(NS_LITERAL_STRING("mouseup"), this, false,
  2701                              false);
  2702   mContent->AddEventListener(NS_LITERAL_STRING("mousedown"), this, false,
  2703                              false);
  2704   mContent->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false,
  2705                              false);
  2706   mContent->AddEventListener(NS_LITERAL_STRING("click"), this, false,
  2707                              false);
  2708   mContent->AddEventListener(NS_LITERAL_STRING("dblclick"), this, false,
  2709                              false);
  2710   mContent->AddEventListener(NS_LITERAL_STRING("mouseover"), this, false,
  2711                              false);
  2712   mContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false,
  2713                              false);
  2714   mContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
  2715   mContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
  2716   mContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
  2717   mContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true);
  2718   mContent->AddEventListener(NS_LITERAL_STRING("dragdrop"), this, true);
  2719   mContent->AddEventListener(NS_LITERAL_STRING("drag"), this, true);
  2720   mContent->AddEventListener(NS_LITERAL_STRING("dragenter"), this, true);
  2721   mContent->AddEventListener(NS_LITERAL_STRING("dragover"), this, true);
  2722   mContent->AddEventListener(NS_LITERAL_STRING("dragleave"), this, true);
  2723   mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, true);
  2724   mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
  2725   mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
  2726   mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
  2728   return NS_OK; 
  2731 void* nsPluginInstanceOwner::GetPluginPortFromWidget()
  2733 //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
  2735   void* result = nullptr;
  2736   if (mWidget) {
  2737 #ifdef XP_WIN
  2738     if (mPluginWindow && (mPluginWindow->type == NPWindowTypeDrawable))
  2739       result = mWidget->GetNativeData(NS_NATIVE_GRAPHIC);
  2740     else
  2741 #endif
  2742 #ifdef XP_MACOSX
  2743     if (GetDrawingModel() == NPDrawingModelCoreGraphics || 
  2744         GetDrawingModel() == NPDrawingModelCoreAnimation ||
  2745         GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
  2746       result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG);
  2747     else
  2748 #endif
  2749       result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
  2751   return result;
  2754 void nsPluginInstanceOwner::ReleasePluginPort(void * pluginPort)
  2756 #ifdef XP_WIN
  2757   if (mWidget && mPluginWindow &&
  2758       mPluginWindow->type == NPWindowTypeDrawable) {
  2759     mWidget->FreeNativeData((HDC)pluginPort, NS_NATIVE_GRAPHIC);
  2761 #endif
  2764 NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
  2766   NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
  2768   nsresult rv = NS_ERROR_FAILURE;
  2770   // Can't call this twice!
  2771   if (mWidget) {
  2772     NS_WARNING("Trying to create a plugin widget twice!");
  2773     return NS_ERROR_FAILURE;
  2776   bool windowless = false;
  2777   mInstance->IsWindowless(&windowless);
  2778   if (!windowless && !nsIWidget::UsePuppetWidgets()) {
  2779     // Try to get a parent widget, on some platforms widget creation will fail without
  2780     // a parent.
  2781     nsCOMPtr<nsIWidget> parentWidget;
  2782     nsIDocument *doc = nullptr;
  2783     if (mContent) {
  2784       doc = mContent->OwnerDoc();
  2785       parentWidget = nsContentUtils::WidgetForDocument(doc);
  2788     mWidget = do_CreateInstance(kWidgetCID, &rv);
  2789     if (NS_FAILED(rv)) {
  2790       return rv;
  2793     nsWidgetInitData initData;
  2794     initData.mWindowType = eWindowType_plugin;
  2795     initData.mUnicode = false;
  2796     initData.clipChildren = true;
  2797     initData.clipSiblings = true;
  2798     rv = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0),
  2799                          nullptr, &initData);
  2800     if (NS_FAILED(rv)) {
  2801       mWidget->Destroy();
  2802       mWidget = nullptr;
  2803       return rv;
  2806     mWidget->EnableDragDrop(true);
  2807     mWidget->Show(false);
  2808     mWidget->Enable(false);
  2810 #ifdef XP_MACOSX
  2811     // Now that we have a widget we want to set the event model before
  2812     // any events are processed.
  2813     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  2814     if (!pluginWidget) {
  2815       return NS_ERROR_FAILURE;
  2817     pluginWidget->SetPluginEventModel(GetEventModel());
  2818     pluginWidget->SetPluginDrawingModel(GetDrawingModel());
  2820     if (GetDrawingModel() == NPDrawingModelCoreAnimation) {
  2821       AddToCARefreshTimer();
  2823 #endif
  2826   if (mObjectFrame) {
  2827     // nullptr widget is fine, will result in windowless setup.
  2828     mObjectFrame->PrepForDrawing(mWidget);
  2831   if (windowless) {
  2832     mPluginWindow->type = NPWindowTypeDrawable;
  2834     // this needs to be a HDC according to the spec, but I do
  2835     // not see the right way to release it so let's postpone
  2836     // passing HDC till paint event when it is really
  2837     // needed. Change spec?
  2838     mPluginWindow->window = nullptr;
  2839 #ifdef MOZ_X11
  2840     // Fill in the display field.
  2841     NPSetWindowCallbackStruct* ws_info = 
  2842     static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
  2843     ws_info->display = DefaultXDisplay();
  2845     nsAutoCString description;
  2846     GetPluginDescription(description);
  2847     NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
  2848     mFlash10Quirks = StringBeginsWith(description, flash10Head);
  2849 #endif
  2850   } else if (mWidget) {
  2851     // mPluginWindow->type is used in |GetPluginPort| so it must
  2852     // be initialized first
  2853     mPluginWindow->type = NPWindowTypeWindow;
  2854     mPluginWindow->window = GetPluginPortFromWidget();
  2855     // tell the plugin window about the widget
  2856     mPluginWindow->SetPluginWidget(mWidget);
  2858     // tell the widget about the current plugin instance owner.
  2859     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  2860     if (pluginWidget) {
  2861       pluginWidget->SetPluginInstanceOwner(this);
  2865   mWidgetCreationComplete = true;
  2867   return NS_OK;
  2870 // Mac specific code to fix up the port location and clipping region
  2871 #ifdef XP_MACOSX
  2873 void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
  2875   if (!mWidget || !mPluginWindow || !mInstance || !mObjectFrame)
  2876     return nullptr;
  2878   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
  2879   if (!pluginWidget)
  2880     return nullptr;
  2882   // If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
  2883   // don't want calls to SetPluginPortAndDetectChange() to step on our work.
  2884   if (mInCGPaintLevel < 1) {
  2885     SetPluginPortAndDetectChange();
  2888   // We'll need the top-level Cocoa window for the Cocoa event model.
  2889   nsIWidget* widget = mObjectFrame->GetNearestWidget();
  2890   if (!widget)
  2891     return nullptr;
  2892   void *cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW);
  2893   if (!cocoaTopLevelWindow)
  2894     return nullptr;
  2896   nsIntPoint pluginOrigin;
  2897   nsIntRect widgetClip;
  2898   bool widgetVisible;
  2899   pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible);
  2900   mWidgetVisible = widgetVisible;
  2902   // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
  2904   // This would be a lot easier if we could use obj-c here,
  2905   // but we can't. Since we have only nsIWidget and we can't
  2906   // use its native widget (an obj-c object) we have to go
  2907   // from the widget's screen coordinates to its window coords
  2908   // instead of straight to window coords.
  2909   nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
  2911   nsRect windowRect;
  2912   NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
  2914   double scaleFactor = 1.0;
  2915   GetContentsScaleFactor(&scaleFactor);
  2916   int intScaleFactor = ceil(scaleFactor);
  2918   // Convert geckoScreenCoords from device pixels to "display pixels"
  2919   // for HiDPI modes.
  2920   mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x;
  2921   mPluginWindow->y = geckoScreenCoords.y/intScaleFactor - windowRect.y;
  2923   NPRect oldClipRect = mPluginWindow->clipRect;
  2925   // fix up the clipping region
  2926   mPluginWindow->clipRect.top    = widgetClip.y;
  2927   mPluginWindow->clipRect.left   = widgetClip.x;
  2929   if (!mWidgetVisible || inPaintState == ePluginPaintDisable) {
  2930     mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
  2931     mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
  2933   else if (inPaintState == ePluginPaintEnable)
  2935     mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top + widgetClip.height;
  2936     mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left + widgetClip.width; 
  2939   // if the clip rect changed, call SetWindow()
  2940   // (RealPlayer needs this to draw correctly)
  2941   if (mPluginWindow->clipRect.left    != oldClipRect.left   ||
  2942       mPluginWindow->clipRect.top     != oldClipRect.top    ||
  2943       mPluginWindow->clipRect.right   != oldClipRect.right  ||
  2944       mPluginWindow->clipRect.bottom  != oldClipRect.bottom ||
  2945       mPluginPortChanged)
  2947     if (UseAsyncRendering()) {
  2948       mInstance->AsyncSetWindow(mPluginWindow);
  2950     else {
  2951       mPluginWindow->CallSetWindow(mInstance);
  2953     mPluginPortChanged = false;
  2956   // After the first NPP_SetWindow call we need to send an initial
  2957   // top-level window focus event.
  2958   if (!mSentInitialTopLevelWindowEvent) {
  2959     // Set this before calling ProcessEvent to avoid endless recursion.
  2960     mSentInitialTopLevelWindowEvent = true;
  2962     WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nullptr);
  2963     NPCocoaEvent cocoaEvent;
  2964     InitializeNPCocoaEvent(&cocoaEvent);
  2965     cocoaEvent.type = NPCocoaEventWindowFocusChanged;
  2966     cocoaEvent.data.focus.hasFocus = NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow);
  2967     pluginEvent.pluginEvent = &cocoaEvent;
  2968     ProcessEvent(pluginEvent);
  2971   return nullptr;
  2974 void
  2975 nsPluginInstanceOwner::HidePluginWindow()
  2977   if (!mPluginWindow || !mInstance) {
  2978     return;
  2981   mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
  2982   mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
  2983   mWidgetVisible = false;
  2984   if (UseAsyncRendering()) {
  2985     mInstance->AsyncSetWindow(mPluginWindow);
  2986   } else {
  2987     mInstance->SetWindow(mPluginWindow);
  2991 #else // XP_MACOSX
  2993 void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow)
  2995   if (!mPluginWindow)
  2996     return;
  2998   // For windowless plugins a non-empty clip rectangle will be
  2999   // passed to the plugin during paint, an additional update
  3000   // of the the clip rectangle here is not required
  3001   if (aSetWindow && !mWidget && mPluginWindowVisible && !UseAsyncRendering())
  3002     return;
  3004   const NPWindow oldWindow = *mPluginWindow;
  3006   bool windowless = (mPluginWindow->type == NPWindowTypeDrawable);
  3007   nsIntPoint origin = mObjectFrame->GetWindowOriginInPixels(windowless);
  3009   mPluginWindow->x = origin.x;
  3010   mPluginWindow->y = origin.y;
  3012   mPluginWindow->clipRect.left = 0;
  3013   mPluginWindow->clipRect.top = 0;
  3015   if (mPluginWindowVisible && mPluginDocumentActiveState) {
  3016     mPluginWindow->clipRect.right = mPluginWindow->width;
  3017     mPluginWindow->clipRect.bottom = mPluginWindow->height;
  3018   } else {
  3019     mPluginWindow->clipRect.right = 0;
  3020     mPluginWindow->clipRect.bottom = 0;
  3023   if (!aSetWindow)
  3024     return;
  3026   if (mPluginWindow->x               != oldWindow.x               ||
  3027       mPluginWindow->y               != oldWindow.y               ||
  3028       mPluginWindow->clipRect.left   != oldWindow.clipRect.left   ||
  3029       mPluginWindow->clipRect.top    != oldWindow.clipRect.top    ||
  3030       mPluginWindow->clipRect.right  != oldWindow.clipRect.right  ||
  3031       mPluginWindow->clipRect.bottom != oldWindow.clipRect.bottom) {
  3032     CallSetWindow();
  3036 void
  3037 nsPluginInstanceOwner::UpdateWindowVisibility(bool aVisible)
  3039   mPluginWindowVisible = aVisible;
  3040   UpdateWindowPositionAndClipRect(true);
  3043 void
  3044 nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
  3046   mPluginDocumentActiveState = aIsActive;
  3047   UpdateWindowPositionAndClipRect(true);
  3049 #ifdef MOZ_WIDGET_ANDROID
  3050   if (mInstance) {
  3051     if (!mPluginDocumentActiveState)
  3052       RemovePluginView();
  3054     mInstance->NotifyOnScreen(mPluginDocumentActiveState);
  3056     // This is, perhaps, incorrect. It is supposed to be sent
  3057     // when "the webview has paused or resumed". The side effect
  3058     // is that Flash video players pause or resume (if they were
  3059     // playing before) based on the value here. I personally think
  3060     // we want that on Android when switching to another tab, so
  3061     // that's why we call it here.
  3062     mInstance->NotifyForeground(mPluginDocumentActiveState);
  3064 #endif
  3066 #endif // XP_MACOSX
  3068 NS_IMETHODIMP
  3069 nsPluginInstanceOwner::CallSetWindow()
  3071   if (mObjectFrame) {
  3072     mObjectFrame->CallSetWindow(false);
  3073   } else if (mInstance) {
  3074     if (UseAsyncRendering()) {
  3075       mInstance->AsyncSetWindow(mPluginWindow);
  3076     } else {
  3077       mInstance->SetWindow(mPluginWindow);
  3081   return NS_OK;
  3084 NS_IMETHODIMP
  3085 nsPluginInstanceOwner::GetContentsScaleFactor(double *result)
  3087   NS_ENSURE_ARG_POINTER(result);
  3088   double scaleFactor = 1.0;
  3089   // On Mac, device pixels need to be translated to (and from) "display pixels"
  3090   // for plugins. On other platforms, plugin coordinates are always in device
  3091   // pixels.
  3092 #if defined(XP_MACOSX)
  3093   nsIPresShell* presShell = nsContentUtils::FindPresShellForDocument(mContent->OwnerDoc());
  3094   if (presShell) {
  3095     scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
  3096       presShell->GetPresContext()->DeviceContext()->UnscaledAppUnitsPerDevPixel();
  3098 #endif
  3099   *result = scaleFactor;
  3100   return NS_OK;
  3103 void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
  3105   // Don't do anything if the frame situation hasn't changed.
  3106   if (mObjectFrame == aFrame) {
  3107     return;
  3110   // If we already have a frame that is changing or going away...
  3111   if (mObjectFrame) {
  3112     // Make sure the old frame isn't holding a reference to us.
  3113     mObjectFrame->SetInstanceOwner(nullptr);
  3116   // Swap in the new frame (or no frame)
  3117   mObjectFrame = aFrame;
  3119   // Set up a new frame
  3120   if (mObjectFrame) {
  3121     mObjectFrame->SetInstanceOwner(this);
  3122     // Can only call PrepForDrawing on an object frame once. Don't do it here unless
  3123     // widget creation is complete. Doesn't matter if we actually have a widget.
  3124     if (mWidgetCreationComplete) {
  3125       mObjectFrame->PrepForDrawing(mWidget);
  3127     mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
  3128     mObjectFrame->InvalidateFrame();
  3130     nsFocusManager* fm = nsFocusManager::GetFocusManager();
  3131     const nsIContent* content = aFrame->GetContent();
  3132     if (fm && content) {
  3133       mContentFocused = (content == fm->GetFocusedContent());
  3138 nsObjectFrame* nsPluginInstanceOwner::GetFrame()
  3140   return mObjectFrame;
  3143 // Little helper function to resolve relative URL in
  3144 // |value| for certain inputs of |name|
  3145 void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
  3147   if (name.LowerCaseEqualsLiteral("pluginspage")) {
  3148     nsCOMPtr<nsIURI> baseURI = GetBaseURI();
  3149     nsAutoString newURL;
  3150     NS_MakeAbsoluteURI(newURL, value, baseURI);
  3151     if (!newURL.IsEmpty())
  3152       value = newURL;
  3156 NS_IMETHODIMP nsPluginInstanceOwner::PrivateModeChanged(bool aEnabled)
  3158   return mInstance ? mInstance->PrivateModeStateChanged(aEnabled) : NS_OK;
  3161 already_AddRefed<nsIURI> nsPluginInstanceOwner::GetBaseURI() const
  3163   if (!mContent) {
  3164     return nullptr;
  3166   return mContent->GetBaseURI();
  3169 // nsPluginDOMContextMenuListener class implementation
  3171 nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener(nsIContent* aContent)
  3173   aContent->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
  3176 nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener()
  3180 NS_IMPL_ISUPPORTS(nsPluginDOMContextMenuListener,
  3181                   nsIDOMEventListener)
  3183 NS_IMETHODIMP
  3184 nsPluginDOMContextMenuListener::HandleEvent(nsIDOMEvent* aEvent)
  3186   aEvent->PreventDefault(); // consume event
  3188   return NS_OK;
  3191 void nsPluginDOMContextMenuListener::Destroy(nsIContent* aContent)
  3193   // Unregister context menu listener
  3194   aContent->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true);

mercurial