LCOV - code coverage report
Current view: top level - dom/plugins/ipc - PluginInstanceChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 975 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 85 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: sw=4 ts=4 et :
       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/. */
       6             : 
       7             : #include "PluginBackgroundDestroyer.h"
       8             : #include "PluginInstanceChild.h"
       9             : #include "PluginModuleChild.h"
      10             : #include "BrowserStreamChild.h"
      11             : #include "StreamNotifyChild.h"
      12             : #include "PluginProcessChild.h"
      13             : #include "gfxASurface.h"
      14             : #include "gfxPlatform.h"
      15             : #include "gfx2DGlue.h"
      16             : #include "nsNPAPIPluginInstance.h"
      17             : #include "mozilla/gfx/2D.h"
      18             : #ifdef MOZ_X11
      19             : #include "gfxXlibSurface.h"
      20             : #endif
      21             : #ifdef XP_WIN
      22             : #include "mozilla/D3DMessageUtils.h"
      23             : #include "mozilla/gfx/SharedDIBSurface.h"
      24             : #include "nsCrashOnException.h"
      25             : #include "gfxWindowsPlatform.h"
      26             : extern const wchar_t* kFlashFullscreenClass;
      27             : using mozilla::gfx::SharedDIBSurface;
      28             : #endif
      29             : #include "gfxSharedImageSurface.h"
      30             : #include "gfxUtils.h"
      31             : #include "gfxAlphaRecovery.h"
      32             : 
      33             : #include "mozilla/ArrayUtils.h"
      34             : #include "mozilla/BasicEvents.h"
      35             : #include "mozilla/ipc/MessageChannel.h"
      36             : #include "mozilla/AutoRestore.h"
      37             : #include "mozilla/StaticPtr.h"
      38             : #include "mozilla/UniquePtr.h"
      39             : #include "ImageContainer.h"
      40             : 
      41             : using namespace mozilla;
      42             : using mozilla::ipc::ProcessChild;
      43             : using namespace mozilla::plugins;
      44             : using namespace mozilla::layers;
      45             : using namespace mozilla::gfx;
      46             : using namespace mozilla::widget;
      47             : using namespace std;
      48             : 
      49             : #ifdef MOZ_WIDGET_GTK
      50             : 
      51             : #include <gtk/gtk.h>
      52             : #include <gdk/gdkx.h>
      53             : #include <gdk/gdk.h>
      54             : #include "gtk2xtbin.h"
      55             : 
      56             : #elif defined(OS_WIN)
      57             : 
      58             : #include <windows.h>
      59             : #include <windowsx.h>
      60             : 
      61             : #include "mozilla/widget/WinMessages.h"
      62             : #include "mozilla/widget/WinModifierKeyState.h"
      63             : #include "mozilla/widget/WinNativeEventData.h"
      64             : #include "nsWindowsDllInterceptor.h"
      65             : #include "X11UndefineNone.h"
      66             : 
      67             : typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
      68             :                                             UINT uFlags,
      69             :                                             int x,
      70             :                                             int y,
      71             :                                             int nReserved,
      72             :                                             HWND hWnd,
      73             :                                             CONST RECT *prcRect);
      74             : static WindowsDllInterceptor sUser32Intercept;
      75             : static HWND sWinlessPopupSurrogateHWND = nullptr;
      76             : static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr;
      77             : 
      78             : typedef HIMC (WINAPI *Imm32ImmGetContext)(HWND hWND);
      79             : typedef BOOL (WINAPI *Imm32ImmReleaseContext)(HWND hWND, HIMC hIMC);
      80             : typedef LONG (WINAPI *Imm32ImmGetCompositionString)(HIMC hIMC,
      81             :                                                     DWORD dwIndex,
      82             :                                                     LPVOID lpBuf,
      83             :                                                     DWORD dwBufLen);
      84             : typedef BOOL (WINAPI *Imm32ImmSetCandidateWindow)(HIMC hIMC,
      85             :                                                   LPCANDIDATEFORM lpCandidate);
      86             : typedef BOOL (WINAPI *Imm32ImmNotifyIME)(HIMC hIMC, DWORD dwAction,
      87             :                                         DWORD dwIndex, DWORD dwValue);
      88             : static WindowsDllInterceptor sImm32Intercept;
      89             : static Imm32ImmGetContext sImm32ImmGetContextStub = nullptr;
      90             : static Imm32ImmReleaseContext sImm32ImmReleaseContextStub = nullptr;
      91             : static Imm32ImmGetCompositionString sImm32ImmGetCompositionStringStub = nullptr;
      92             : static Imm32ImmSetCandidateWindow sImm32ImmSetCandidateWindowStub = nullptr;
      93             : static Imm32ImmNotifyIME sImm32ImmNotifyIME = nullptr;
      94             : static PluginInstanceChild* sCurrentPluginInstance = nullptr;
      95             : static const HIMC sHookIMC = (const HIMC)0xefefefef;
      96             : 
      97             : using mozilla::gfx::SharedDIB;
      98             : 
      99             : // Flash WM_USER message delay time for PostDelayedTask. Borrowed
     100             : // from Chromium's web plugin delegate src. See 'flash msg throttling
     101             : // helpers' section for details.
     102             : const int kFlashWMUSERMessageThrottleDelayMs = 5;
     103             : 
     104             : static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty");
     105             : 
     106             : #elif defined(XP_MACOSX)
     107             : #include <ApplicationServices/ApplicationServices.h>
     108             : #include "PluginUtilsOSX.h"
     109             : #endif // defined(XP_MACOSX)
     110             : 
     111             : /**
     112             :  * We can't use gfxPlatform::CreateDrawTargetForSurface() because calling
     113             :  * gfxPlatform::GetPlatform() instantiates the prefs service, and that's not
     114             :  * allowed from processes other than the main process. So we have our own
     115             :  * version here.
     116             :  */
     117             : static RefPtr<DrawTarget>
     118           0 : CreateDrawTargetForSurface(gfxASurface *aSurface)
     119             : {
     120           0 :   SurfaceFormat format = aSurface->GetSurfaceFormat();
     121             :   RefPtr<DrawTarget> drawTarget =
     122           0 :     Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(),
     123           0 :                                              aSurface->GetSize(),
     124           0 :                                              &format);
     125           0 :   if (!drawTarget) {
     126           0 :     MOZ_CRASH("CreateDrawTargetForSurface failed in plugin");
     127             :   }
     128           0 :   return drawTarget;
     129             : }
     130             : 
     131             : bool PluginInstanceChild::sIsIMEComposing = false;
     132             : 
     133           0 : PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
     134             :                                          const nsCString& aMimeType,
     135             :                                          const InfallibleTArray<nsCString>& aNames,
     136           0 :                                          const InfallibleTArray<nsCString>& aValues)
     137             :     : mPluginIface(aPluginIface)
     138             :     , mMimeType(aMimeType)
     139             :     , mNames(aNames)
     140             :     , mValues(aValues)
     141             : #if defined(XP_DARWIN) || defined (XP_WIN)
     142             :     , mContentsScaleFactor(1.0)
     143             : #endif
     144             :     , mPostingKeyEvents(0)
     145             :     , mPostingKeyEventsOutdated(0)
     146             :     , mDrawingModel(kDefaultDrawingModel)
     147             :     , mCurrentDirectSurface(nullptr)
     148             :     , mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
     149             :     , mAsyncInvalidateTask(0)
     150             :     , mCachedWindowActor(nullptr)
     151             :     , mCachedElementActor(nullptr)
     152             : #if defined(OS_WIN)
     153             :     , mPluginWindowHWND(0)
     154             :     , mPluginWndProc(0)
     155             :     , mPluginParentHWND(0)
     156             :     , mCachedWinlessPluginHWND(0)
     157             :     , mWinlessPopupSurrogateHWND(0)
     158             :     , mWinlessThrottleOldWndProc(0)
     159             :     , mWinlessHiddenMsgHWND(0)
     160             : #endif // OS_WIN
     161             :     , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
     162             : #if defined(MOZ_WIDGET_COCOA)
     163             : #if defined(__i386__)
     164             :     , mEventModel(NPEventModelCarbon)
     165             : #endif
     166             :     , mShColorSpace(nullptr)
     167             :     , mShContext(nullptr)
     168             :     , mCGLayer(nullptr)
     169             :     , mCurrentEvent(nullptr)
     170             : #endif
     171             :     , mLayersRendering(false)
     172             : #ifdef XP_WIN
     173             :     , mCurrentSurfaceActor(nullptr)
     174             :     , mBackSurfaceActor(nullptr)
     175             : #endif
     176             :     , mAccumulatedInvalidRect(0,0,0,0)
     177             :     , mIsTransparent(false)
     178             :     , mSurfaceType(gfxSurfaceType::Max)
     179             :     , mPendingPluginCall(false)
     180             :     , mDoAlphaExtraction(false)
     181             :     , mHasPainted(false)
     182             :     , mSurfaceDifferenceRect(0,0,0,0)
     183             :     , mDestroyed(false)
     184             : #ifdef XP_WIN
     185             :     , mLastKeyEventConsumed(false)
     186             : #endif // #ifdef XP_WIN
     187           0 :     , mStackDepth(0)
     188             : {
     189           0 :     memset(&mWindow, 0, sizeof(mWindow));
     190           0 :     mWindow.type = NPWindowTypeWindow;
     191           0 :     mData.ndata = (void*) this;
     192           0 :     mData.pdata = nullptr;
     193             : #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     194           0 :     mWindow.ws_info = &mWsInfo;
     195           0 :     memset(&mWsInfo, 0, sizeof(mWsInfo));
     196             : #ifdef MOZ_WIDGET_GTK
     197           0 :     mWsInfo.display = nullptr;
     198             : #else
     199             :     mWsInfo.display = DefaultXDisplay();
     200             : #endif
     201             : #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
     202             : #if defined(OS_WIN)
     203             :     InitPopupMenuHook();
     204             :     InitImm32Hook();
     205             : #endif // OS_WIN
     206           0 : }
     207             : 
     208           0 : PluginInstanceChild::~PluginInstanceChild()
     209             : {
     210             : #if defined(OS_WIN)
     211             :     NS_ASSERTION(!mPluginWindowHWND, "Destroying PluginInstanceChild without NPP_Destroy?");
     212             :     // In the event that we registered for audio device changes, stop.
     213             :     PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
     214             :     if (chromeInstance) {
     215             :       NPError rv = chromeInstance->PluginRequiresAudioDeviceChanges(this, false);
     216             :     }
     217             : #endif
     218             : #if defined(MOZ_WIDGET_COCOA)
     219             :     if (mShColorSpace) {
     220             :         ::CGColorSpaceRelease(mShColorSpace);
     221             :     }
     222             :     if (mShContext) {
     223             :         ::CGContextRelease(mShContext);
     224             :     }
     225             :     if (mCGLayer) {
     226             :         PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
     227             :     }
     228             :     if (mDrawingModel == NPDrawingModelCoreAnimation) {
     229             :         UnscheduleTimer(mCARefreshTimer);
     230             :     }
     231             : #endif
     232           0 : }
     233             : 
     234             : NPError
     235           0 : PluginInstanceChild::DoNPP_New()
     236             : {
     237             :     // unpack the arguments into a C format
     238           0 :     int argc = mNames.Length();
     239           0 :     NS_ASSERTION(argc == (int) mValues.Length(),
     240             :                  "argn.length != argv.length");
     241             : 
     242           0 :     UniquePtr<char*[]> argn(new char*[1 + argc]);
     243           0 :     UniquePtr<char*[]> argv(new char*[1 + argc]);
     244           0 :     argn[argc] = 0;
     245           0 :     argv[argc] = 0;
     246             : 
     247           0 :     for (int i = 0; i < argc; ++i) {
     248           0 :         argn[i] = const_cast<char*>(NullableStringGet(mNames[i]));
     249           0 :         argv[i] = const_cast<char*>(NullableStringGet(mValues[i]));
     250             :     }
     251             : 
     252           0 :     NPP npp = GetNPP();
     253             : 
     254           0 :     NPError rv = mPluginIface->newp((char*)NullableStringGet(mMimeType), npp,
     255           0 :                                     NP_EMBED, argc, argn.get(), argv.get(), 0);
     256           0 :     if (NPERR_NO_ERROR != rv) {
     257           0 :         return rv;
     258             :     }
     259             : 
     260           0 :     if (!Initialize()) {
     261           0 :         rv = NPERR_MODULE_LOAD_FAILED_ERROR;
     262             :     }
     263           0 :     return rv;
     264             : }
     265             : 
     266             : int
     267           0 : PluginInstanceChild::GetQuirks()
     268             : {
     269           0 :     return PluginModuleChild::GetChrome()->GetQuirks();
     270             : }
     271             : 
     272             : NPError
     273           0 : PluginInstanceChild::InternalGetNPObjectForValue(NPNVariable aValue,
     274             :                                                  NPObject** aObject)
     275             : {
     276           0 :     PluginScriptableObjectChild* actor = nullptr;
     277           0 :     NPError result = NPERR_NO_ERROR;
     278             : 
     279           0 :     switch (aValue) {
     280             :         case NPNVWindowNPObject:
     281           0 :             if (!(actor = mCachedWindowActor)) {
     282             :                 PPluginScriptableObjectChild* actorProtocol;
     283           0 :                 CallNPN_GetValue_NPNVWindowNPObject(&actorProtocol, &result);
     284           0 :                 if (result == NPERR_NO_ERROR) {
     285           0 :                     actor = mCachedWindowActor =
     286             :                         static_cast<PluginScriptableObjectChild*>(actorProtocol);
     287           0 :                     NS_ASSERTION(actor, "Null actor!");
     288           0 :                     PluginModuleChild::sBrowserFuncs.retainobject(
     289           0 :                         actor->GetObject(false));
     290             :                 }
     291             :             }
     292           0 :             break;
     293             : 
     294             :         case NPNVPluginElementNPObject:
     295           0 :             if (!(actor = mCachedElementActor)) {
     296             :                 PPluginScriptableObjectChild* actorProtocol;
     297           0 :                 CallNPN_GetValue_NPNVPluginElementNPObject(&actorProtocol,
     298           0 :                                                            &result);
     299           0 :                 if (result == NPERR_NO_ERROR) {
     300           0 :                     actor = mCachedElementActor =
     301             :                         static_cast<PluginScriptableObjectChild*>(actorProtocol);
     302           0 :                     NS_ASSERTION(actor, "Null actor!");
     303           0 :                     PluginModuleChild::sBrowserFuncs.retainobject(
     304           0 :                         actor->GetObject(false));
     305             :                 }
     306             :             }
     307           0 :             break;
     308             : 
     309             :         default:
     310           0 :             NS_NOTREACHED("Don't know what to do with this value type!");
     311             :     }
     312             : 
     313             : #ifdef DEBUG
     314             :     {
     315             :         NPError currentResult;
     316           0 :         PPluginScriptableObjectChild* currentActor = nullptr;
     317             : 
     318           0 :         switch (aValue) {
     319             :             case NPNVWindowNPObject:
     320           0 :                 CallNPN_GetValue_NPNVWindowNPObject(&currentActor,
     321           0 :                                                     &currentResult);
     322           0 :                 break;
     323             :             case NPNVPluginElementNPObject:
     324           0 :                 CallNPN_GetValue_NPNVPluginElementNPObject(&currentActor,
     325           0 :                                                            &currentResult);
     326           0 :                 break;
     327             :             default:
     328           0 :                 MOZ_ASSERT(false);
     329             :         }
     330             : 
     331             :         // Make sure that the current actor returned by the parent matches our
     332             :         // cached actor!
     333           0 :         NS_ASSERTION(!currentActor ||
     334             :                      static_cast<PluginScriptableObjectChild*>(currentActor) ==
     335             :                      actor, "Cached actor is out of date!");
     336             :     }
     337             : #endif
     338             : 
     339           0 :     if (result != NPERR_NO_ERROR) {
     340           0 :         return result;
     341             :     }
     342             : 
     343           0 :     NPObject* object = actor->GetObject(false);
     344           0 :     NS_ASSERTION(object, "Null object?!");
     345             : 
     346           0 :     *aObject = PluginModuleChild::sBrowserFuncs.retainobject(object);
     347           0 :     return NPERR_NO_ERROR;
     348             : 
     349             : }
     350             : 
     351             : NPError
     352           0 : PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
     353             :                                   void* aValue)
     354             : {
     355           0 :     PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION, (int) aVar));
     356           0 :     AssertPluginThread();
     357           0 :     AutoStackHelper guard(this);
     358             : 
     359           0 :     switch(aVar) {
     360             : 
     361             : #if defined(MOZ_X11)
     362             :     case NPNVToolkit:
     363           0 :         *((NPNToolkitType*)aValue) = NPNVGtk2;
     364           0 :         return NPERR_NO_ERROR;
     365             : 
     366             :     case NPNVxDisplay:
     367           0 :         if (!mWsInfo.display) {
     368             :             // We are called before Initialize() so we have to call it now.
     369           0 :            if (!Initialize()) {
     370           0 :                return NPERR_GENERIC_ERROR;
     371             :            }
     372           0 :            NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
     373             :         }
     374           0 :         *(void **)aValue = mWsInfo.display;
     375           0 :         return NPERR_NO_ERROR;
     376             : 
     377             : #elif defined(OS_WIN)
     378             :     case NPNVToolkit:
     379             :         return NPERR_GENERIC_ERROR;
     380             : #endif
     381             :     case NPNVprivateModeBool: {
     382           0 :         bool v = false;
     383             :         NPError result;
     384           0 :         if (!CallNPN_GetValue_NPNVprivateModeBool(&v, &result)) {
     385           0 :             return NPERR_GENERIC_ERROR;
     386             :         }
     387           0 :         *static_cast<NPBool*>(aValue) = v;
     388           0 :         return result;
     389             :     }
     390             : 
     391             :     case NPNVdocumentOrigin: {
     392           0 :         nsCString v;
     393             :         NPError result;
     394           0 :         if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) {
     395           0 :             return NPERR_GENERIC_ERROR;
     396             :         }
     397           0 :         if (result == NPERR_NO_ERROR ||
     398           0 :             (GetQuirks() &
     399             :                 QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) {
     400           0 :             *static_cast<char**>(aValue) = ToNewCString(v);
     401             :         }
     402           0 :         return result;
     403             :     }
     404             : 
     405             :     case NPNVWindowNPObject: // Intentional fall-through
     406             :     case NPNVPluginElementNPObject: {
     407             :         NPObject* object;
     408           0 :         NPError result = InternalGetNPObjectForValue(aVar, &object);
     409           0 :         if (result == NPERR_NO_ERROR) {
     410           0 :             *((NPObject**)aValue) = object;
     411             :         }
     412           0 :         return result;
     413             :     }
     414             : 
     415             :     case NPNVnetscapeWindow: {
     416             : #ifdef XP_WIN
     417             :         if (mWindow.type == NPWindowTypeDrawable) {
     418             :             if (mCachedWinlessPluginHWND) {
     419             :               *static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND;
     420             :               return NPERR_NO_ERROR;
     421             :             }
     422             :             NPError result;
     423             :             if (!CallNPN_GetValue_NPNVnetscapeWindow(&mCachedWinlessPluginHWND, &result)) {
     424             :                 return NPERR_GENERIC_ERROR;
     425             :             }
     426             :             *static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND;
     427             :             return result;
     428             :         }
     429             :         else {
     430             :             *static_cast<HWND*>(aValue) = mPluginWindowHWND;
     431             :             return NPERR_NO_ERROR;
     432             :         }
     433             : #elif defined(MOZ_X11)
     434             :         NPError result;
     435           0 :         CallNPN_GetValue_NPNVnetscapeWindow(static_cast<XID*>(aValue), &result);
     436           0 :         return result;
     437             : #else
     438             :         return NPERR_GENERIC_ERROR;
     439             : #endif
     440             :     }
     441             : 
     442             :     case NPNVsupportsAsyncBitmapSurfaceBool: {
     443           0 :         bool value = false;
     444           0 :         CallNPN_GetValue_SupportsAsyncBitmapSurface(&value);
     445           0 :         *((NPBool*)aValue) = value;
     446           0 :         return NPERR_NO_ERROR;
     447             :     }
     448             : 
     449             : #ifdef XP_WIN
     450             :     case NPNVsupportsAsyncWindowsDXGISurfaceBool: {
     451             :         bool value = false;
     452             :         CallNPN_GetValue_SupportsAsyncDXGISurface(&value);
     453             :         *((NPBool*)aValue) = value;
     454             :         return NPERR_NO_ERROR;
     455             :     }
     456             : #endif
     457             : 
     458             : #ifdef XP_WIN
     459             :     case NPNVpreferredDXGIAdapter: {
     460             :         DxgiAdapterDesc desc;
     461             :         if (!CallNPN_GetValue_PreferredDXGIAdapter(&desc)) {
     462             :             return NPERR_GENERIC_ERROR;
     463             :         }
     464             :         *reinterpret_cast<DXGI_ADAPTER_DESC*>(aValue) = desc.ToDesc();
     465             :         return NPERR_NO_ERROR;
     466             :     }
     467             : #endif
     468             : 
     469             : #ifdef XP_MACOSX
     470             :    case NPNVsupportsCoreGraphicsBool: {
     471             :         *((NPBool*)aValue) = true;
     472             :         return NPERR_NO_ERROR;
     473             :     }
     474             : 
     475             :     case NPNVsupportsCoreAnimationBool: {
     476             :         *((NPBool*)aValue) = true;
     477             :         return NPERR_NO_ERROR;
     478             :     }
     479             : 
     480             :     case NPNVsupportsInvalidatingCoreAnimationBool: {
     481             :         *((NPBool*)aValue) = true;
     482             :         return NPERR_NO_ERROR;
     483             :     }
     484             : 
     485             :     case NPNVsupportsCompositingCoreAnimationPluginsBool: {
     486             :         *((NPBool*)aValue) = true;
     487             :         return NPERR_NO_ERROR;
     488             :     }
     489             : 
     490             :     case NPNVsupportsCocoaBool: {
     491             :         *((NPBool*)aValue) = true;
     492             :         return NPERR_NO_ERROR;
     493             :     }
     494             : 
     495             : #ifndef NP_NO_CARBON
     496             :     case NPNVsupportsCarbonBool: {
     497             :       *((NPBool*)aValue) = false;
     498             :       return NPERR_NO_ERROR;
     499             :     }
     500             : #endif
     501             : 
     502             :     case NPNVsupportsUpdatedCocoaTextInputBool: {
     503             :       *static_cast<NPBool*>(aValue) = true;
     504             :       return NPERR_NO_ERROR;
     505             :     }
     506             : 
     507             : #ifndef NP_NO_QUICKDRAW
     508             :     case NPNVsupportsQuickDrawBool: {
     509             :         *((NPBool*)aValue) = false;
     510             :         return NPERR_NO_ERROR;
     511             :     }
     512             : #endif /* NP_NO_QUICKDRAW */
     513             : #endif /* XP_MACOSX */
     514             : 
     515             : #if defined(XP_MACOSX) || defined(XP_WIN)
     516             :     case NPNVcontentsScaleFactor: {
     517             :         *static_cast<double*>(aValue) = mContentsScaleFactor;
     518             :         return NPERR_NO_ERROR;
     519             :     }
     520             : #endif /* defined(XP_MACOSX) || defined(XP_WIN) */
     521             : 
     522             :     case NPNVCSSZoomFactor: {
     523           0 :         *static_cast<double*>(aValue) = mCSSZoomFactor;
     524           0 :         return NPERR_NO_ERROR;
     525             :     }
     526             : #ifdef DEBUG
     527             :     case NPNVjavascriptEnabledBool:
     528             :     case NPNVasdEnabledBool:
     529             :     case NPNVisOfflineBool:
     530             :     case NPNVSupportsXEmbedBool:
     531             :     case NPNVSupportsWindowless:
     532           0 :         NS_NOTREACHED("NPNVariable should be handled in PluginModuleChild.");
     533             :         MOZ_FALLTHROUGH;
     534             : #endif
     535             : 
     536             :     default:
     537           0 :         MOZ_LOG(GetPluginLog(), LogLevel::Warning,
     538             :                ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
     539             :                 (int) aVar, NPNVariableToString(aVar)));
     540           0 :         return NPERR_GENERIC_ERROR;
     541             :     }
     542             : }
     543             : 
     544             : #ifdef MOZ_WIDGET_COCOA
     545             : #define DEFAULT_REFRESH_MS 20 // CoreAnimation: 50 FPS
     546             : 
     547             : void
     548             : CAUpdate(NPP npp, uint32_t timerID) {
     549             :     static_cast<PluginInstanceChild*>(npp->ndata)->Invalidate();
     550             : }
     551             : 
     552             : void
     553             : PluginInstanceChild::Invalidate()
     554             : {
     555             :     NPRect windowRect = {0, 0, uint16_t(mWindow.height),
     556             :         uint16_t(mWindow.width)};
     557             : 
     558             :     InvalidateRect(&windowRect);
     559             : }
     560             : #endif
     561             : 
     562             : NPError
     563           0 : PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
     564             : {
     565           0 :     MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s (aVar=%i, aValue=%p)",
     566             :                                       FULLFUNCTION, (int) aVar, aValue));
     567             : 
     568           0 :     AssertPluginThread();
     569             : 
     570           0 :     AutoStackHelper guard(this);
     571             : 
     572           0 :     switch (aVar) {
     573             :     case NPPVpluginWindowBool: {
     574             :         NPError rv;
     575           0 :         bool windowed = (NPBool) (intptr_t) aValue;
     576             : 
     577           0 :         if (windowed) {
     578           0 :             return NPERR_GENERIC_ERROR;
     579             :         }
     580             : 
     581           0 :         if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv))
     582           0 :             return NPERR_GENERIC_ERROR;
     583             : 
     584           0 :         mWindow.type = NPWindowTypeDrawable;
     585           0 :         return rv;
     586             :     }
     587             : 
     588             :     case NPPVpluginTransparentBool: {
     589             :         NPError rv;
     590           0 :         mIsTransparent = (!!aValue);
     591             : 
     592           0 :         if (!CallNPN_SetValue_NPPVpluginTransparent(mIsTransparent, &rv))
     593           0 :             return NPERR_GENERIC_ERROR;
     594             : 
     595           0 :         return rv;
     596             :     }
     597             : 
     598             :     case NPPVpluginUsesDOMForCursorBool: {
     599           0 :         NPError rv = NPERR_GENERIC_ERROR;
     600           0 :         if (!CallNPN_SetValue_NPPVpluginUsesDOMForCursor((NPBool)(intptr_t)aValue, &rv)) {
     601           0 :             return NPERR_GENERIC_ERROR;
     602             :         }
     603           0 :         return rv;
     604             :     }
     605             : 
     606             :     case NPPVpluginDrawingModel: {
     607             :         NPError rv;
     608           0 :         int drawingModel = (int16_t) (intptr_t) aValue;
     609             : 
     610           0 :         if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
     611           0 :             return NPERR_GENERIC_ERROR;
     612             : 
     613           0 :         mDrawingModel = drawingModel;
     614             : 
     615             : #ifdef XP_MACOSX
     616             :         if (drawingModel == NPDrawingModelCoreAnimation) {
     617             :             mCARefreshTimer = ScheduleTimer(DEFAULT_REFRESH_MS, true, CAUpdate);
     618             :         }
     619             : #endif
     620             : 
     621           0 :         PLUGIN_LOG_DEBUG(("  Plugin requested drawing model id  #%i\n",
     622             :             mDrawingModel));
     623             : 
     624           0 :         return rv;
     625             :     }
     626             : 
     627             : #ifdef XP_MACOSX
     628             :     case NPPVpluginEventModel: {
     629             :         NPError rv;
     630             :         int eventModel = (int16_t) (intptr_t) aValue;
     631             : 
     632             :         if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv))
     633             :             return NPERR_GENERIC_ERROR;
     634             : #if defined(__i386__)
     635             :         mEventModel = static_cast<NPEventModel>(eventModel);
     636             : #endif
     637             : 
     638             :         PLUGIN_LOG_DEBUG(("  Plugin requested event model id # %i\n",
     639             :             eventModel));
     640             : 
     641             :         return rv;
     642             :     }
     643             : #endif
     644             : 
     645             :     case NPPVpluginIsPlayingAudio: {
     646           0 :         NPError rv = NPERR_GENERIC_ERROR;
     647           0 :         if (!CallNPN_SetValue_NPPVpluginIsPlayingAudio((NPBool)(intptr_t)aValue, &rv)) {
     648           0 :             return NPERR_GENERIC_ERROR;
     649             :         }
     650           0 :         return rv;
     651             :     }
     652             : 
     653             : #ifdef XP_WIN
     654             :     case NPPVpluginRequiresAudioDeviceChanges: {
     655             :       // Many other NPN_SetValue variables are forwarded to our
     656             :       // PluginInstanceParent, which runs on a content process.  We
     657             :       // instead forward this message to the PluginModuleParent, which runs
     658             :       // on the chrome process.  This is because our audio
     659             :       // API calls should run the chrome proc, not content.
     660             :       NPError rv = NPERR_GENERIC_ERROR;
     661             :       PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
     662             :       if (chromeInstance) {
     663             :         rv = chromeInstance->PluginRequiresAudioDeviceChanges(this,
     664             :                                               (NPBool)(intptr_t)aValue);
     665             :       }
     666             :       return rv;
     667             :     }
     668             : #endif
     669             : 
     670             :     default:
     671           0 :         MOZ_LOG(GetPluginLog(), LogLevel::Warning,
     672             :                ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
     673             :                 (int) aVar, NPPVariableToString(aVar)));
     674           0 :         return NPERR_GENERIC_ERROR;
     675             :     }
     676             : }
     677             : 
     678             : mozilla::ipc::IPCResult
     679           0 : PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
     680             :     bool* wantsAllStreams, NPError* rv)
     681             : {
     682           0 :     AssertPluginThread();
     683           0 :     AutoStackHelper guard(this);
     684             : 
     685           0 :     uint32_t value = 0;
     686           0 :     if (!mPluginIface->getvalue) {
     687           0 :         *rv = NPERR_GENERIC_ERROR;
     688             :     }
     689             :     else {
     690           0 :         *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWantsAllNetworkStreams,
     691             :                                      &value);
     692             :     }
     693           0 :     *wantsAllStreams = value;
     694           0 :     return IPC_OK();
     695             : }
     696             : 
     697             : mozilla::ipc::IPCResult
     698           0 : PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
     699             :                                           PPluginScriptableObjectChild** aValue,
     700             :                                           NPError* aResult)
     701             : {
     702           0 :     AssertPluginThread();
     703           0 :     AutoStackHelper guard(this);
     704             : 
     705           0 :     NPObject* object = nullptr;
     706           0 :     NPError result = NPERR_GENERIC_ERROR;
     707           0 :     if (mPluginIface->getvalue) {
     708           0 :         result = mPluginIface->getvalue(GetNPP(), NPPVpluginScriptableNPObject,
     709           0 :                                         &object);
     710             :     }
     711           0 :     if (result == NPERR_NO_ERROR && object) {
     712           0 :         PluginScriptableObjectChild* actor = GetActorForNPObject(object);
     713             : 
     714             :         // If we get an actor then it has retained. Otherwise we don't need it
     715             :         // any longer.
     716           0 :         PluginModuleChild::sBrowserFuncs.releaseobject(object);
     717           0 :         if (actor) {
     718           0 :             *aValue = actor;
     719           0 :             *aResult = NPERR_NO_ERROR;
     720           0 :             return IPC_OK();
     721             :         }
     722             : 
     723           0 :         NS_ERROR("Failed to get actor!");
     724           0 :         result = NPERR_GENERIC_ERROR;
     725             :     }
     726             :     else {
     727           0 :         result = NPERR_GENERIC_ERROR;
     728             :     }
     729             : 
     730           0 :     *aValue = nullptr;
     731           0 :     *aResult = result;
     732           0 :     return IPC_OK();
     733             : }
     734             : 
     735             : mozilla::ipc::IPCResult
     736           0 : PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(
     737             :                                           nsCString* aPlugId,
     738             :                                           NPError* aResult)
     739             : {
     740           0 :     AssertPluginThread();
     741           0 :     AutoStackHelper guard(this);
     742             : 
     743             : #if MOZ_ACCESSIBILITY_ATK
     744             : 
     745           0 :     char* plugId = nullptr;
     746           0 :     NPError result = NPERR_GENERIC_ERROR;
     747           0 :     if (mPluginIface->getvalue) {
     748           0 :         result = mPluginIface->getvalue(GetNPP(),
     749             :                                         NPPVpluginNativeAccessibleAtkPlugId,
     750           0 :                                         &plugId);
     751             :     }
     752             : 
     753           0 :     *aPlugId = nsCString(plugId);
     754           0 :     *aResult = result;
     755           0 :     return IPC_OK();
     756             : 
     757             : #else
     758             : 
     759             :     NS_RUNTIMEABORT("shouldn't be called on non-ATK platforms");
     760             :     return IPC_FAIL_NO_REASON(this);
     761             : 
     762             : #endif
     763             : }
     764             : 
     765             : mozilla::ipc::IPCResult
     766           0 : PluginInstanceChild::AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value,
     767             :                                                             NPError* result)
     768             : {
     769           0 :     if (!mPluginIface->setvalue) {
     770           0 :         *result = NPERR_GENERIC_ERROR;
     771           0 :         return IPC_OK();
     772             :     }
     773             : 
     774           0 :     NPBool v = value;
     775           0 :     *result = mPluginIface->setvalue(GetNPP(), NPNVprivateModeBool, &v);
     776           0 :     return IPC_OK();
     777             : }
     778             : 
     779             : mozilla::ipc::IPCResult
     780           0 : PluginInstanceChild::AnswerNPP_SetValue_NPNVCSSZoomFactor(const double& value,
     781             :                                                           NPError* result)
     782             : {
     783           0 :     if (!mPluginIface->setvalue) {
     784           0 :         *result = NPERR_GENERIC_ERROR;
     785           0 :         return IPC_OK();
     786             :     }
     787             : 
     788           0 :     mCSSZoomFactor = value;
     789           0 :     double v = value;
     790           0 :     *result = mPluginIface->setvalue(GetNPP(), NPNVCSSZoomFactor, &v);
     791           0 :     return IPC_OK();
     792             : }
     793             : 
     794             : mozilla::ipc::IPCResult
     795           0 : PluginInstanceChild::AnswerNPP_SetValue_NPNVmuteAudioBool(const bool& value,
     796             :                                                           NPError* result)
     797             : {
     798           0 :     if (!mPluginIface->setvalue) {
     799           0 :         *result = NPERR_GENERIC_ERROR;
     800           0 :         return IPC_OK();
     801             :     }
     802             : 
     803           0 :     NPBool v = value;
     804           0 :     *result = mPluginIface->setvalue(GetNPP(), NPNVmuteAudioBool, &v);
     805           0 :     return IPC_OK();
     806             : }
     807             : 
     808             : #if defined(XP_WIN)
     809             : NPError
     810             : PluginInstanceChild::DefaultAudioDeviceChanged(NPAudioDeviceChangeDetails& details)
     811             : {
     812             :     if (!mPluginIface->setvalue) {
     813             :         return NPERR_GENERIC_ERROR;
     814             :     }
     815             :     return mPluginIface->setvalue(GetNPP(), NPNVaudioDeviceChangeDetails, (void*)&details);
     816             : }
     817             : #endif
     818             : 
     819             : 
     820             : mozilla::ipc::IPCResult
     821           0 : PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
     822             :                                            int16_t* handled)
     823             : {
     824           0 :     PLUGIN_LOG_DEBUG_FUNCTION;
     825           0 :     AssertPluginThread();
     826           0 :     AutoStackHelper guard(this);
     827             : 
     828             : #if defined(MOZ_X11) && defined(DEBUG)
     829           0 :     if (GraphicsExpose == event.event.type)
     830           0 :         PLUGIN_LOG_DEBUG(("  received drawable 0x%lx\n",
     831             :                           event.event.xgraphicsexpose.drawable));
     832             : #endif
     833             : 
     834             : #ifdef XP_MACOSX
     835             :     // Mac OS X does not define an NPEvent structure. It defines more specific types.
     836             :     NPCocoaEvent evcopy = event.event;
     837             : 
     838             :     // Make sure we reset mCurrentEvent in case of an exception
     839             :     AutoRestore<const NPCocoaEvent*> savePreviousEvent(mCurrentEvent);
     840             : 
     841             :     // Track the current event for NPN_PopUpContextMenu.
     842             :     mCurrentEvent = &event.event;
     843             : #else
     844             :     // Make a copy since we may modify values.
     845           0 :     NPEvent evcopy = event.event;
     846             : #endif
     847             : 
     848             : #if defined(XP_MACOSX) || defined(XP_WIN)
     849             :     // event.contentsScaleFactor <= 0 is a signal we shouldn't use it,
     850             :     // for example when AnswerNPP_HandleEvent() is called from elsewhere
     851             :     // in the child process (not via rpc code from the parent process).
     852             :     if (event.contentsScaleFactor > 0) {
     853             :       mContentsScaleFactor = event.contentsScaleFactor;
     854             :     }
     855             : #endif
     856             : 
     857             : #ifdef OS_WIN
     858             :     // FIXME/bug 567645: temporarily drop the "dummy event" on the floor
     859             :     if (WM_NULL == evcopy.event)
     860             :         return IPC_OK();
     861             : 
     862             :     *handled = WinlessHandleEvent(evcopy);
     863             :     return IPC_OK();
     864             : #endif
     865             : 
     866             :     // XXX A previous call to mPluginIface->event might block, e.g. right click
     867             :     // for context menu. Still, we might get here again, calling into the plugin
     868             :     // a second time while it's in the previous call.
     869           0 :     if (!mPluginIface->event)
     870           0 :         *handled = false;
     871             :     else
     872           0 :         *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
     873             : 
     874             : #ifdef XP_MACOSX
     875             :     // Release any reference counted objects created in the child process.
     876             :     if (evcopy.type == NPCocoaEventKeyDown ||
     877             :         evcopy.type == NPCocoaEventKeyUp) {
     878             :       ::CFRelease((CFStringRef)evcopy.data.key.characters);
     879             :       ::CFRelease((CFStringRef)evcopy.data.key.charactersIgnoringModifiers);
     880             :     }
     881             :     else if (evcopy.type == NPCocoaEventTextInput) {
     882             :       ::CFRelease((CFStringRef)evcopy.data.text.text);
     883             :     }
     884             : #endif
     885             : 
     886             : #ifdef MOZ_X11
     887           0 :     if (GraphicsExpose == event.event.type) {
     888             :         // Make sure the X server completes the drawing before the parent
     889             :         // draws on top and destroys the Drawable.
     890             :         //
     891             :         // XSync() waits for the X server to complete.  Really this child
     892             :         // process does not need to wait; the parent is the process that needs
     893             :         // to wait.  A possibly-slightly-better alternative would be to send
     894             :         // an X event to the parent that the parent would wait for.
     895           0 :         XSync(mWsInfo.display, False);
     896             :     }
     897             : #endif
     898             : 
     899           0 :     return IPC_OK();
     900             : }
     901             : 
     902             : #ifdef XP_MACOSX
     903             : 
     904             : mozilla::ipc::IPCResult
     905             : PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
     906             :                                                  Shmem&& mem,
     907             :                                                  int16_t* handled,
     908             :                                                  Shmem* rtnmem)
     909             : {
     910             :     PLUGIN_LOG_DEBUG_FUNCTION;
     911             :     AssertPluginThread();
     912             :     AutoStackHelper guard(this);
     913             : 
     914             :     PaintTracker pt;
     915             : 
     916             :     NPCocoaEvent evcopy = event.event;
     917             :     mContentsScaleFactor = event.contentsScaleFactor;
     918             : 
     919             :     if (evcopy.type == NPCocoaEventDrawRect) {
     920             :         int scaleFactor = ceil(mContentsScaleFactor);
     921             :         if (!mShColorSpace) {
     922             :             mShColorSpace = CreateSystemColorSpace();
     923             :             if (!mShColorSpace) {
     924             :                 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
     925             :                 *handled = false;
     926             :                 *rtnmem = mem;
     927             :                 return IPC_OK();
     928             :             }
     929             :         }
     930             :         if (!mShContext) {
     931             :             void* cgContextByte = mem.get<char>();
     932             :             mShContext = ::CGBitmapContextCreate(cgContextByte,
     933             :                               mWindow.width * scaleFactor,
     934             :                               mWindow.height * scaleFactor, 8,
     935             :                               mWindow.width * 4 * scaleFactor, mShColorSpace,
     936             :                               kCGImageAlphaPremultipliedFirst |
     937             :                               kCGBitmapByteOrder32Host);
     938             : 
     939             :             if (!mShContext) {
     940             :                 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
     941             :                 *handled = false;
     942             :                 *rtnmem = mem;
     943             :                 return IPC_OK();
     944             :             }
     945             :         }
     946             :         CGRect clearRect = ::CGRectMake(0, 0, mWindow.width, mWindow.height);
     947             :         ::CGContextClearRect(mShContext, clearRect);
     948             :         evcopy.data.draw.context = mShContext;
     949             :     } else {
     950             :         PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem."));
     951             :         *handled = false;
     952             :         *rtnmem = mem;
     953             :         return IPC_OK();
     954             :     }
     955             : 
     956             :     if (!mPluginIface->event) {
     957             :         *handled = false;
     958             :     } else {
     959             :         ::CGContextSaveGState(evcopy.data.draw.context);
     960             :         *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
     961             :         ::CGContextRestoreGState(evcopy.data.draw.context);
     962             :     }
     963             : 
     964             :     *rtnmem = mem;
     965             :     return IPC_OK();
     966             : }
     967             : 
     968             : #else
     969             : mozilla::ipc::IPCResult
     970           0 : PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
     971             :                                                  Shmem&& mem,
     972             :                                                  int16_t* handled,
     973             :                                                  Shmem* rtnmem)
     974             : {
     975           0 :     MOZ_CRASH("not reached.");
     976             :     *rtnmem = mem;
     977             :     return IPC_OK();
     978             : }
     979             : #endif
     980             : 
     981             : #ifdef XP_MACOSX
     982             : 
     983             : void CallCGDraw(CGContextRef ref, void* aPluginInstance, nsIntRect aUpdateRect) {
     984             :   PluginInstanceChild* pluginInstance = (PluginInstanceChild*)aPluginInstance;
     985             : 
     986             :   pluginInstance->CGDraw(ref, aUpdateRect);
     987             : }
     988             : 
     989             : bool
     990             : PluginInstanceChild::CGDraw(CGContextRef ref, nsIntRect aUpdateRect) {
     991             : 
     992             :   NPCocoaEvent drawEvent;
     993             :   drawEvent.type = NPCocoaEventDrawRect;
     994             :   drawEvent.version = 0;
     995             :   drawEvent.data.draw.x = aUpdateRect.x;
     996             :   drawEvent.data.draw.y = aUpdateRect.y;
     997             :   drawEvent.data.draw.width = aUpdateRect.width;
     998             :   drawEvent.data.draw.height = aUpdateRect.height;
     999             :   drawEvent.data.draw.context = ref;
    1000             : 
    1001             :   NPRemoteEvent remoteDrawEvent = {drawEvent};
    1002             :   // Signal to AnswerNPP_HandleEvent() not to use this value
    1003             :   remoteDrawEvent.contentsScaleFactor = -1.0;
    1004             : 
    1005             :   int16_t handled;
    1006             :   AnswerNPP_HandleEvent(remoteDrawEvent, &handled);
    1007             :   return handled == true;
    1008             : }
    1009             : 
    1010             : mozilla::ipc::IPCResult
    1011             : PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
    1012             :                                                      const uint32_t &surfaceid,
    1013             :                                                      int16_t* handled)
    1014             : {
    1015             :     PLUGIN_LOG_DEBUG_FUNCTION;
    1016             :     AssertPluginThread();
    1017             :     AutoStackHelper guard(this);
    1018             : 
    1019             :     PaintTracker pt;
    1020             : 
    1021             :     NPCocoaEvent evcopy = event.event;
    1022             :     mContentsScaleFactor = event.contentsScaleFactor;
    1023             :     RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid,
    1024             :                                                             mContentsScaleFactor);
    1025             :     if (!surf) {
    1026             :         NS_ERROR("Invalid IOSurface.");
    1027             :         *handled = false;
    1028             :         return IPC_FAIL_NO_REASON(this);
    1029             :     }
    1030             : 
    1031             :     if (!mCARenderer) {
    1032             :       mCARenderer = new nsCARenderer();
    1033             :     }
    1034             : 
    1035             :     if (evcopy.type == NPCocoaEventDrawRect) {
    1036             :         mCARenderer->AttachIOSurface(surf);
    1037             :         if (!mCARenderer->isInit()) {
    1038             :             void *caLayer = nullptr;
    1039             :             NPError result = mPluginIface->getvalue(GetNPP(),
    1040             :                                      NPPVpluginCoreAnimationLayer,
    1041             :                                      &caLayer);
    1042             : 
    1043             :             if (result != NPERR_NO_ERROR || !caLayer) {
    1044             :                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
    1045             :                                   "provide CALayer."));
    1046             :                 *handled = false;
    1047             :                 return IPC_FAIL_NO_REASON(this);
    1048             :             }
    1049             : 
    1050             :             mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height,
    1051             :                             mContentsScaleFactor,
    1052             :                             GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
    1053             :                             ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
    1054             : 
    1055             :             // Flash needs to have the window set again after this step
    1056             :             if (mPluginIface->setwindow)
    1057             :                 (void) mPluginIface->setwindow(&mData, &mWindow);
    1058             :         }
    1059             :     } else {
    1060             :         PLUGIN_LOG_DEBUG(("Invalid event type for "
    1061             :                           "AnswerNNP_HandleEvent_IOSurface."));
    1062             :         *handled = false;
    1063             :         return IPC_FAIL_NO_REASON(this);
    1064             :     }
    1065             : 
    1066             :     mCARenderer->Render(mWindow.width, mWindow.height,
    1067             :                         mContentsScaleFactor, nullptr);
    1068             : 
    1069             :     return IPC_OK();
    1070             : 
    1071             : }
    1072             : 
    1073             : #else
    1074             : mozilla::ipc::IPCResult
    1075           0 : PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
    1076             :                                                      const uint32_t &surfaceid,
    1077             :                                                      int16_t* handled)
    1078             : {
    1079           0 :     NS_RUNTIMEABORT("NPP_HandleEvent_IOSurface is a OSX-only message");
    1080           0 :     return IPC_FAIL_NO_REASON(this);
    1081             : }
    1082             : #endif
    1083             : 
    1084             : mozilla::ipc::IPCResult
    1085           0 : PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
    1086             : {
    1087           0 :     NS_ASSERTION(!mLayersRendering && !mPendingPluginCall,
    1088             :                  "Shouldn't be receiving WindowPosChanged with layer rendering");
    1089             : 
    1090             : #ifdef OS_WIN
    1091             :     int16_t dontcare;
    1092             :     return AnswerNPP_HandleEvent(event, &dontcare);
    1093             : #else
    1094           0 :     NS_RUNTIMEABORT("WindowPosChanged is a windows-only message");
    1095           0 :     return IPC_FAIL_NO_REASON(this);
    1096             : #endif
    1097             : }
    1098             : 
    1099             : mozilla::ipc::IPCResult
    1100           0 : PluginInstanceChild::RecvContentsScaleFactorChanged(const double& aContentsScaleFactor)
    1101             : {
    1102             : #if defined(XP_MACOSX) || defined(XP_WIN)
    1103             :     mContentsScaleFactor = aContentsScaleFactor;
    1104             : #if defined(XP_MACOSX)
    1105             :     if (mShContext) {
    1106             :         // Release the shared context so that it is reallocated
    1107             :         // with the new size.
    1108             :         ::CGContextRelease(mShContext);
    1109             :         mShContext = nullptr;
    1110             :     }
    1111             : #endif
    1112             :     return IPC_OK();
    1113             : #else
    1114           0 :     NS_RUNTIMEABORT("ContentsScaleFactorChanged is an Windows or OSX only message");
    1115           0 :     return IPC_FAIL_NO_REASON(this);
    1116             : #endif
    1117             : }
    1118             : 
    1119             : mozilla::ipc::IPCResult
    1120           0 : PluginInstanceChild::AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow)
    1121             : {
    1122             : #if defined(XP_WIN)
    1123             :     MOZ_ASSERT(!mPluginWindowHWND);
    1124             : 
    1125             :     if (!CreatePluginWindow()) {
    1126             :         return IPC_FAIL_NO_REASON(this);
    1127             :     }
    1128             : 
    1129             :     MOZ_ASSERT(mPluginWindowHWND);
    1130             : 
    1131             :     *aChildPluginWindow = mPluginWindowHWND;
    1132             :     return IPC_OK();
    1133             : #else
    1134           0 :     NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!");
    1135           0 :     return IPC_FAIL_NO_REASON(this);
    1136             : #endif
    1137             : }
    1138             : 
    1139             : mozilla::ipc::IPCResult
    1140           0 : PluginInstanceChild::RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow)
    1141             : {
    1142             : #if defined(XP_WIN)
    1143             :     mCachedWinlessPluginHWND = aNetscapeWindow;
    1144             :     CreateWinlessPopupSurrogate();
    1145             :     return IPC_OK();
    1146             : #else
    1147           0 :     NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!");
    1148           0 :     return IPC_FAIL_NO_REASON(this);
    1149             : #endif
    1150             : }
    1151             : 
    1152             : mozilla::ipc::IPCResult
    1153           0 : PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
    1154             : {
    1155           0 :     PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%" PRIx64 ", x: %d, y: %d, width: %d, height: %d>)",
    1156             :                       FULLFUNCTION,
    1157             :                       aWindow.window,
    1158             :                       aWindow.x, aWindow.y,
    1159             :                       aWindow.width, aWindow.height));
    1160           0 :     NS_ASSERTION(!mLayersRendering && !mPendingPluginCall,
    1161             :                  "Shouldn't be receiving NPP_SetWindow with layer rendering");
    1162           0 :     AssertPluginThread();
    1163           0 :     AutoStackHelper guard(this);
    1164             : 
    1165             : #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
    1166           0 :     NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
    1167             : 
    1168             :     // The minimum info is sent over IPC to allow this
    1169             :     // code to determine the rest.
    1170             : 
    1171           0 :     mWindow.x = aWindow.x;
    1172           0 :     mWindow.y = aWindow.y;
    1173           0 :     mWindow.width = aWindow.width;
    1174           0 :     mWindow.height = aWindow.height;
    1175           0 :     mWindow.clipRect = aWindow.clipRect;
    1176           0 :     mWindow.type = aWindow.type;
    1177             : 
    1178           0 :     mWsInfo.colormap = aWindow.colormap;
    1179             :     int depth;
    1180           0 :     FindVisualAndDepth(mWsInfo.display, aWindow.visualID,
    1181           0 :                        &mWsInfo.visual, &depth);
    1182           0 :     mWsInfo.depth = depth;
    1183             : 
    1184           0 :     PLUGIN_LOG_DEBUG(
    1185             :         ("[InstanceChild][%p] Answer_SetWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
    1186             :          this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
    1187             :          mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
    1188             : 
    1189           0 :     if (mPluginIface->setwindow)
    1190           0 :         (void) mPluginIface->setwindow(&mData, &mWindow);
    1191             : 
    1192             : #elif defined(OS_WIN)
    1193             :     switch (aWindow.type) {
    1194             :       case NPWindowTypeWindow:
    1195             :       {
    1196             :           MOZ_ASSERT(mPluginWindowHWND,
    1197             :                      "Child plugin window must exist before call to SetWindow");
    1198             : 
    1199             :           HWND parentHWND =  reinterpret_cast<HWND>(aWindow.window);
    1200             :           if (mPluginWindowHWND != parentHWND) {
    1201             :               mPluginParentHWND = parentHWND;
    1202             :               ShowWindow(mPluginWindowHWND, SW_SHOWNA);
    1203             :           }
    1204             : 
    1205             :           SizePluginWindow(aWindow.width, aWindow.height);
    1206             : 
    1207             :           mWindow.window = (void*)mPluginWindowHWND;
    1208             :           mWindow.x = aWindow.x;
    1209             :           mWindow.y = aWindow.y;
    1210             :           mWindow.width = aWindow.width;
    1211             :           mWindow.height = aWindow.height;
    1212             :           mWindow.type = aWindow.type;
    1213             :           mContentsScaleFactor = aWindow.contentsScaleFactor;
    1214             : 
    1215             :           if (mPluginIface->setwindow) {
    1216             :               SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
    1217             :               (void) mPluginIface->setwindow(&mData, &mWindow);
    1218             :               WNDPROC wndProc = reinterpret_cast<WNDPROC>(
    1219             :                   GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
    1220             :               if (wndProc != PluginWindowProc) {
    1221             :                   mPluginWndProc = reinterpret_cast<WNDPROC>(
    1222             :                       SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
    1223             :                                        reinterpret_cast<LONG_PTR>(PluginWindowProc)));
    1224             :                   NS_ASSERTION(mPluginWndProc != PluginWindowProc, "WTF?");
    1225             :               }
    1226             :               RemoveProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty);
    1227             :               HookSetWindowLongPtr();
    1228             :           }
    1229             :       }
    1230             :       break;
    1231             : 
    1232             :       default:
    1233             :           NS_NOTREACHED("Bad plugin window type.");
    1234             :           return IPC_FAIL_NO_REASON(this);
    1235             :       break;
    1236             :     }
    1237             : 
    1238             : #elif defined(XP_MACOSX)
    1239             : 
    1240             :     mWindow.x = aWindow.x;
    1241             :     mWindow.y = aWindow.y;
    1242             :     mWindow.width = aWindow.width;
    1243             :     mWindow.height = aWindow.height;
    1244             :     mWindow.clipRect = aWindow.clipRect;
    1245             :     mWindow.type = aWindow.type;
    1246             :     mContentsScaleFactor = aWindow.contentsScaleFactor;
    1247             : 
    1248             :     if (mShContext) {
    1249             :         // Release the shared context so that it is reallocated
    1250             :         // with the new size.
    1251             :         ::CGContextRelease(mShContext);
    1252             :         mShContext = nullptr;
    1253             :     }
    1254             : 
    1255             :     if (mPluginIface->setwindow)
    1256             :         (void) mPluginIface->setwindow(&mData, &mWindow);
    1257             : 
    1258             : #elif defined(ANDROID)
    1259             :     // TODO: Need Android impl
    1260             : #elif defined(MOZ_WIDGET_UIKIT)
    1261             :     // Don't care
    1262             : #else
    1263             : #  error Implement me for your OS
    1264             : #endif
    1265             : 
    1266           0 :     return IPC_OK();
    1267             : }
    1268             : 
    1269             : bool
    1270           0 : PluginInstanceChild::Initialize()
    1271             : {
    1272             : #ifdef MOZ_WIDGET_GTK
    1273           0 :     if (mWsInfo.display) {
    1274             :         // Already initialized
    1275           0 :         return true;
    1276             :     }
    1277             : 
    1278             :     // Request for windowless plugins is set in newp(), before this call.
    1279           0 :     if (mWindow.type == NPWindowTypeWindow) {
    1280           0 :         return false;
    1281             :     }
    1282             : 
    1283           0 :     mWsInfo.display = DefaultXDisplay();
    1284             : #endif
    1285             : 
    1286             : #if defined(XP_MACOSX) && defined(__i386__)
    1287             :     // If an i386 Mac OS X plugin has selected the Carbon event model then
    1288             :     // we have to fail. We do not support putting Carbon event model plugins
    1289             :     // out of process. Note that Carbon is the default model so out of process
    1290             :     // plugins need to actively negotiate something else in order to work
    1291             :     // out of process.
    1292             :     if (EventModel() == NPEventModelCarbon) {
    1293             :         return false;
    1294             :     }
    1295             : #endif
    1296             : 
    1297           0 :     return true;
    1298             : }
    1299             : 
    1300             : mozilla::ipc::IPCResult
    1301           0 : PluginInstanceChild::RecvHandledWindowedPluginKeyEvent(
    1302             :                        const NativeEventData& aKeyEventData,
    1303             :                        const bool& aIsConsumed)
    1304             : {
    1305             : #if defined(OS_WIN)
    1306             :     const WinNativeKeyEventData* eventData =
    1307             :         static_cast<const WinNativeKeyEventData*>(aKeyEventData);
    1308             :     switch (eventData->mMessage) {
    1309             :         case WM_KEYDOWN:
    1310             :         case WM_SYSKEYDOWN:
    1311             :         case WM_KEYUP:
    1312             :         case WM_SYSKEYUP:
    1313             :             mLastKeyEventConsumed = aIsConsumed;
    1314             :             break;
    1315             :         case WM_CHAR:
    1316             :         case WM_SYSCHAR:
    1317             :         case WM_DEADCHAR:
    1318             :         case WM_SYSDEADCHAR:
    1319             :             // If preceding keydown or keyup event is consumed by the chrome
    1320             :             // process, we should consume WM_*CHAR messages too.
    1321             :             if (mLastKeyEventConsumed) {
    1322             :                 return IPC_OK();
    1323             :             }
    1324             :         default:
    1325             :             MOZ_CRASH("Needs to handle all messages posted to the parent");
    1326             :     }
    1327             : #endif // #if defined(OS_WIN)
    1328             : 
    1329             :     // Unknown key input shouldn't be sent to plugin for security.
    1330             :     // XXX Is this possible if a plugin process which posted the message
    1331             :     //     already crashed and this plugin process is recreated?
    1332           0 :     if (NS_WARN_IF(!mPostingKeyEvents && !mPostingKeyEventsOutdated)) {
    1333           0 :         return IPC_OK();
    1334             :     }
    1335             : 
    1336             :     // If there is outdated posting key events, we should consume the key
    1337             :     // events.
    1338           0 :     if (mPostingKeyEventsOutdated) {
    1339           0 :         mPostingKeyEventsOutdated--;
    1340           0 :         return IPC_OK();
    1341             :     }
    1342             : 
    1343           0 :     mPostingKeyEvents--;
    1344             : 
    1345             :     // If composition has been started after posting the key event,
    1346             :     // we should discard the event since if we send the event to plugin,
    1347             :     // the plugin may be confused and the result may be broken because
    1348             :     // the event order is shuffled.
    1349           0 :     if (aIsConsumed || sIsIMEComposing) {
    1350           0 :         return IPC_OK();
    1351             :     }
    1352             : 
    1353             : #if defined(OS_WIN)
    1354             :     UINT message = 0;
    1355             :     switch (eventData->mMessage) {
    1356             :         case WM_KEYDOWN:
    1357             :             message = MOZ_WM_KEYDOWN;
    1358             :             break;
    1359             :         case WM_SYSKEYDOWN:
    1360             :             message = MOZ_WM_SYSKEYDOWN;
    1361             :             break;
    1362             :         case WM_KEYUP:
    1363             :             message = MOZ_WM_KEYUP;
    1364             :             break;
    1365             :         case WM_SYSKEYUP:
    1366             :             message = MOZ_WM_SYSKEYUP;
    1367             :             break;
    1368             :         case WM_CHAR:
    1369             :             message = MOZ_WM_CHAR;
    1370             :             break;
    1371             :         case WM_SYSCHAR:
    1372             :             message = MOZ_WM_SYSCHAR;
    1373             :             break;
    1374             :         case WM_DEADCHAR:
    1375             :             message = MOZ_WM_DEADCHAR;
    1376             :             break;
    1377             :         case WM_SYSDEADCHAR:
    1378             :             message = MOZ_WM_SYSDEADCHAR;
    1379             :             break;
    1380             :         default:
    1381             :             MOZ_CRASH("Needs to handle all messages posted to the parent");
    1382             :     }
    1383             :     PluginWindowProcInternal(mPluginWindowHWND, message,
    1384             :                              eventData->mWParam, eventData->mLParam);
    1385             : #endif
    1386           0 :     return IPC_OK();
    1387             : }
    1388             : 
    1389             : #if defined(OS_WIN)
    1390             : 
    1391             : static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow");
    1392             : static const TCHAR kPluginInstanceChildProperty[] = TEXT("PluginInstanceChildProperty");
    1393             : static const TCHAR kFlashThrottleProperty[] = TEXT("MozillaFlashThrottleProperty");
    1394             : 
    1395             : // static
    1396             : bool
    1397             : PluginInstanceChild::RegisterWindowClass()
    1398             : {
    1399             :     static bool alreadyRegistered = false;
    1400             :     if (alreadyRegistered)
    1401             :         return true;
    1402             : 
    1403             :     alreadyRegistered = true;
    1404             : 
    1405             :     WNDCLASSEX wcex;
    1406             :     wcex.cbSize         = sizeof(WNDCLASSEX);
    1407             :     wcex.style          = CS_DBLCLKS;
    1408             :     wcex.lpfnWndProc    = DummyWindowProc;
    1409             :     wcex.cbClsExtra     = 0;
    1410             :     wcex.cbWndExtra     = 0;
    1411             :     wcex.hInstance      = GetModuleHandle(nullptr);
    1412             :     wcex.hIcon          = 0;
    1413             :     wcex.hCursor        = 0;
    1414             :     wcex.hbrBackground  = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
    1415             :     wcex.lpszMenuName   = 0;
    1416             :     wcex.lpszClassName  = kWindowClassName;
    1417             :     wcex.hIconSm        = 0;
    1418             : 
    1419             :     return RegisterClassEx(&wcex) ? true : false;
    1420             : }
    1421             : 
    1422             : bool
    1423             : PluginInstanceChild::CreatePluginWindow()
    1424             : {
    1425             :     // already initialized
    1426             :     if (mPluginWindowHWND)
    1427             :         return true;
    1428             : 
    1429             :     if (!RegisterWindowClass())
    1430             :         return false;
    1431             : 
    1432             :     mPluginWindowHWND =
    1433             :         CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING |
    1434             :                        WS_EX_NOPARENTNOTIFY | // XXXbent Get rid of this!
    1435             :                        WS_EX_RIGHTSCROLLBAR,
    1436             :                        kWindowClassName, 0,
    1437             :                        WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
    1438             :                        0, 0, nullptr, 0, GetModuleHandle(nullptr), 0);
    1439             :     if (!mPluginWindowHWND)
    1440             :         return false;
    1441             :     if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this))
    1442             :         return false;
    1443             : 
    1444             :     // Apparently some plugins require an ASCII WndProc.
    1445             :     SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
    1446             :                       reinterpret_cast<LONG_PTR>(DefWindowProcA));
    1447             : 
    1448             :     return true;
    1449             : }
    1450             : 
    1451             : void
    1452             : PluginInstanceChild::DestroyPluginWindow()
    1453             : {
    1454             :     if (mPluginWindowHWND) {
    1455             :         // Unsubclass the window.
    1456             :         WNDPROC wndProc = reinterpret_cast<WNDPROC>(
    1457             :             GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
    1458             :         // Removed prior to SetWindowLongPtr, see HookSetWindowLongPtr.
    1459             :         RemoveProp(mPluginWindowHWND, kPluginInstanceChildProperty);
    1460             :         if (wndProc == PluginWindowProc) {
    1461             :             NS_ASSERTION(mPluginWndProc, "Should have old proc here!");
    1462             :             SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
    1463             :                              reinterpret_cast<LONG_PTR>(mPluginWndProc));
    1464             :             mPluginWndProc = 0;
    1465             :         }
    1466             :         DestroyWindow(mPluginWindowHWND);
    1467             :         mPluginWindowHWND = 0;
    1468             :     }
    1469             : }
    1470             : 
    1471             : void
    1472             : PluginInstanceChild::SizePluginWindow(int width,
    1473             :                                       int height)
    1474             : {
    1475             :     if (mPluginWindowHWND) {
    1476             :         mPluginSize.x = width;
    1477             :         mPluginSize.y = height;
    1478             :         SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height,
    1479             :                      SWP_NOZORDER | SWP_NOREPOSITION);
    1480             :     }
    1481             : }
    1482             : 
    1483             : // See chromium's webplugin_delegate_impl.cc for explanation of this function.
    1484             : // static
    1485             : LRESULT CALLBACK
    1486             : PluginInstanceChild::DummyWindowProc(HWND hWnd,
    1487             :                                      UINT message,
    1488             :                                      WPARAM wParam,
    1489             :                                      LPARAM lParam)
    1490             : {
    1491             :     return CallWindowProc(DefWindowProc, hWnd, message, wParam, lParam);
    1492             : }
    1493             : 
    1494             : // static
    1495             : LRESULT CALLBACK
    1496             : PluginInstanceChild::PluginWindowProc(HWND hWnd,
    1497             :                                       UINT message,
    1498             :                                       WPARAM wParam,
    1499             :                                       LPARAM lParam)
    1500             : {
    1501             :   return mozilla::CallWindowProcCrashProtected(PluginWindowProcInternal, hWnd, message, wParam, lParam);
    1502             : }
    1503             : 
    1504             : // static
    1505             : LRESULT CALLBACK
    1506             : PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
    1507             :                                               UINT message,
    1508             :                                               WPARAM wParam,
    1509             :                                               LPARAM lParam)
    1510             : {
    1511             :     NS_ASSERTION(!mozilla::ipc::MessageChannel::IsPumpingMessages(),
    1512             :                  "Failed to prevent a nonqueued message from running!");
    1513             :     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
    1514             :         GetProp(hWnd, kPluginInstanceChildProperty));
    1515             :     if (!self) {
    1516             :         NS_NOTREACHED("Badness!");
    1517             :         return 0;
    1518             :     }
    1519             : 
    1520             :     NS_ASSERTION(self->mPluginWindowHWND == hWnd, "Wrong window!");
    1521             :     NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Self-referential windowproc. Infinite recursion will happen soon.");
    1522             : 
    1523             :     bool isIMECompositionMessage = false;
    1524             :     switch (message) {
    1525             :         // Adobe's shockwave positions the plugin window relative to the browser
    1526             :         // frame when it initializes. With oopp disabled, this wouldn't have an
    1527             :         // effect. With oopp, GeckoPluginWindow is a child of the parent plugin
    1528             :         // window, so the move offsets the child within the parent. Generally
    1529             :         // we don't want plugins moving or sizing our window, so we prevent
    1530             :         // these changes here.
    1531             :         case WM_WINDOWPOSCHANGING: {
    1532             :             WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(lParam);
    1533             :             if (pos &&
    1534             :                 (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE))) {
    1535             :                 pos->x = pos->y = 0;
    1536             :                 pos->cx = self->mPluginSize.x;
    1537             :                 pos->cy = self->mPluginSize.y;
    1538             :                 LRESULT res = CallWindowProc(self->mPluginWndProc,
    1539             :                                              hWnd, message, wParam, lParam);
    1540             :                 pos->x = pos->y = 0;
    1541             :                 pos->cx = self->mPluginSize.x;
    1542             :                 pos->cy = self->mPluginSize.y;
    1543             :                 return res;
    1544             :             }
    1545             :             break;
    1546             :         }
    1547             : 
    1548             :         case WM_SETFOCUS:
    1549             :             // If this gets focus, ensure that there is no pending key events.
    1550             :             // Even if there were, we should ignore them for performance reason.
    1551             :             // Although, such case shouldn't occur.
    1552             :             NS_WARNING_ASSERTION(self->mPostingKeyEvents == 0,
    1553             :                                  "pending events");
    1554             :             self->mPostingKeyEvents = 0;
    1555             :             self->mLastKeyEventConsumed = false;
    1556             :             break;
    1557             : 
    1558             :         case WM_KEYDOWN:
    1559             :         case WM_SYSKEYDOWN:
    1560             :         case WM_KEYUP:
    1561             :         case WM_SYSKEYUP:
    1562             :             if (self->MaybePostKeyMessage(message, wParam, lParam)) {
    1563             :                 // If PreHandleKeyMessage() posts the message to the parent
    1564             :                 // process, we need to wait RecvOnKeyEventHandledBeforePlugin()
    1565             :                 // to be called.
    1566             :                 return 0; // Consume current message temporarily.
    1567             :             }
    1568             :             break;
    1569             : 
    1570             :         case MOZ_WM_KEYDOWN:
    1571             :             message = WM_KEYDOWN;
    1572             :             break;
    1573             :         case MOZ_WM_SYSKEYDOWN:
    1574             :             message = WM_SYSKEYDOWN;
    1575             :             break;
    1576             :         case MOZ_WM_KEYUP:
    1577             :             message = WM_KEYUP;
    1578             :             break;
    1579             :         case MOZ_WM_SYSKEYUP:
    1580             :             message = WM_SYSKEYUP;
    1581             :             break;
    1582             :         case MOZ_WM_CHAR:
    1583             :             message = WM_CHAR;
    1584             :             break;
    1585             :         case MOZ_WM_SYSCHAR:
    1586             :             message = WM_SYSCHAR;
    1587             :             break;
    1588             :         case MOZ_WM_DEADCHAR:
    1589             :             message = WM_DEADCHAR;
    1590             :             break;
    1591             :         case MOZ_WM_SYSDEADCHAR:
    1592             :             message = WM_SYSDEADCHAR;
    1593             :             break;
    1594             : 
    1595             :         case WM_IME_STARTCOMPOSITION:
    1596             :             isIMECompositionMessage = true;
    1597             :             sIsIMEComposing = true;
    1598             :             break;
    1599             :         case WM_IME_ENDCOMPOSITION:
    1600             :             isIMECompositionMessage = true;
    1601             :             sIsIMEComposing = false;
    1602             :             break;
    1603             :         case WM_IME_COMPOSITION:
    1604             :             isIMECompositionMessage = true;
    1605             :             // XXX Some old IME may not send WM_IME_COMPOSITION_START or
    1606             :             //     WM_IME_COMPSOITION_END properly.  So, we need to check
    1607             :             //     WM_IME_COMPSOITION and if it includes commit string.
    1608             :             sIsIMEComposing = !(lParam & GCS_RESULTSTR);
    1609             :             break;
    1610             : 
    1611             :         // The plugin received keyboard focus, let the parent know so the dom
    1612             :         // is up to date.
    1613             :         case WM_MOUSEACTIVATE:
    1614             :             self->CallPluginFocusChange(true);
    1615             :             break;
    1616             :     }
    1617             : 
    1618             :     // When a composition is committed, there may be pending key
    1619             :     // events which were posted to the parent process before starting
    1620             :     // the composition.  Then, we shouldn't handle it since they are
    1621             :     // now outdated.
    1622             :     if (isIMECompositionMessage && !sIsIMEComposing) {
    1623             :         self->mPostingKeyEventsOutdated += self->mPostingKeyEvents;
    1624             :         self->mPostingKeyEvents = 0;
    1625             :     }
    1626             : 
    1627             :     // Prevent lockups due to plugins making rpc calls when the parent
    1628             :     // is making a synchronous SendMessage call to the child window. Add
    1629             :     // more messages as needed.
    1630             :     if ((InSendMessageEx(nullptr)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
    1631             :         switch(message) {
    1632             :             case WM_CHILDACTIVATE:
    1633             :             case WM_KILLFOCUS:
    1634             :             ReplyMessage(0);
    1635             :             break;
    1636             :         }
    1637             :     }
    1638             : 
    1639             :     if (message == WM_KILLFOCUS) {
    1640             :       self->CallPluginFocusChange(false);
    1641             :     }
    1642             : 
    1643             :     if (message == WM_USER+1 &&
    1644             :         (self->GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) {
    1645             :         self->FlashThrottleMessage(hWnd, message, wParam, lParam, true);
    1646             :         return 0;
    1647             :     }
    1648             : 
    1649             :     NS_ASSERTION(self->mPluginWndProc != PluginWindowProc,
    1650             :       "Self-referential windowproc happened inside our hook proc. "
    1651             :       "Infinite recursion will happen soon.");
    1652             : 
    1653             :     LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
    1654             :                                  lParam);
    1655             : 
    1656             :     // Make sure capture is released by the child on mouse events. Fixes a
    1657             :     // problem with flash full screen mode mouse input. Appears to be
    1658             :     // caused by a bug in flash, since we are not setting the capture
    1659             :     // on the window.
    1660             :     if (message == WM_LBUTTONDOWN &&
    1661             :         self->GetQuirks() & QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) {
    1662             :       wchar_t szClass[26];
    1663             :       HWND hwnd = GetForegroundWindow();
    1664             :       if (hwnd && GetClassNameW(hwnd, szClass,
    1665             :                                 sizeof(szClass)/sizeof(char16_t)) &&
    1666             :           !wcscmp(szClass, kFlashFullscreenClass)) {
    1667             :         ReleaseCapture();
    1668             :         SetFocus(hwnd);
    1669             :       }
    1670             :     }
    1671             : 
    1672             :     if (message == WM_CLOSE) {
    1673             :         self->DestroyPluginWindow();
    1674             :     }
    1675             : 
    1676             :     if (message == WM_NCDESTROY) {
    1677             :         RemoveProp(hWnd, kPluginInstanceChildProperty);
    1678             :     }
    1679             : 
    1680             :     return res;
    1681             : }
    1682             : 
    1683             : bool
    1684             : PluginInstanceChild::ShouldPostKeyMessage(UINT message,
    1685             :                                           WPARAM wParam,
    1686             :                                           LPARAM lParam)
    1687             : {
    1688             :     // If there is a composition, we shouldn't post the key message to the
    1689             :     // parent process because we cannot handle IME messages asynchronously.
    1690             :     // Therefore, if we posted key events to the parent process, the event
    1691             :     // order of the posted key events and IME events are shuffled.
    1692             :     if (sIsIMEComposing) {
    1693             :       return false;
    1694             :     }
    1695             : 
    1696             :     // If there are some pending keyboard events which are not handled in
    1697             :     // the parent process, we should post the message for avoiding to shuffle
    1698             :     // the key event order.
    1699             :     if (mPostingKeyEvents) {
    1700             :         return true;
    1701             :     }
    1702             : 
    1703             :     // If we are not waiting calls of RecvOnKeyEventHandledBeforePlugin(),
    1704             :     // we don't need to post WM_*CHAR messages.
    1705             :     switch (message) {
    1706             :         case WM_CHAR:
    1707             :         case WM_SYSCHAR:
    1708             :         case WM_DEADCHAR:
    1709             :         case WM_SYSDEADCHAR:
    1710             :             return false;
    1711             :     }
    1712             : 
    1713             :     // Otherwise, we should post key message which might match with a
    1714             :     // shortcut key.
    1715             :     ModifierKeyState modifierState;
    1716             :     if (!modifierState.MaybeMatchShortcutKey()) {
    1717             :         // For better UX, we shouldn't use IPC when user tries to
    1718             :         // input character(s).
    1719             :         return false;
    1720             :     }
    1721             : 
    1722             :     // Ignore modifier key events and keys already handled by IME.
    1723             :     switch (wParam) {
    1724             :         case VK_SHIFT:
    1725             :         case VK_CONTROL:
    1726             :         case VK_MENU:
    1727             :         case VK_LWIN:
    1728             :         case VK_RWIN:
    1729             :         case VK_CAPITAL:
    1730             :         case VK_NUMLOCK:
    1731             :         case VK_SCROLL:
    1732             :         // Following virtual keycodes shouldn't come with WM_(SYS)KEY* message
    1733             :         // but check it for avoiding unnecessary cross process communication.
    1734             :         case VK_LSHIFT:
    1735             :         case VK_RSHIFT:
    1736             :         case VK_LCONTROL:
    1737             :         case VK_RCONTROL:
    1738             :         case VK_LMENU:
    1739             :         case VK_RMENU:
    1740             :         case VK_PROCESSKEY:
    1741             :         case VK_PACKET:
    1742             :         case 0xFF: // 0xFF could be sent with unidentified key by the layout.
    1743             :             return false;
    1744             :         default:
    1745             :             break;
    1746             :     }
    1747             :     return true;
    1748             : }
    1749             : 
    1750             : bool
    1751             : PluginInstanceChild::MaybePostKeyMessage(UINT message,
    1752             :                                          WPARAM wParam,
    1753             :                                          LPARAM lParam)
    1754             : {
    1755             :     if (!ShouldPostKeyMessage(message, wParam, lParam)) {
    1756             :         return false;
    1757             :     }
    1758             : 
    1759             :     ModifierKeyState modifierState;
    1760             :     WinNativeKeyEventData winNativeKeyData(message, wParam, lParam,
    1761             :                                            modifierState);
    1762             :     NativeEventData nativeKeyData;
    1763             :     nativeKeyData.Copy(winNativeKeyData);
    1764             :     if (NS_WARN_IF(!SendOnWindowedPluginKeyEvent(nativeKeyData))) {
    1765             :         return false;
    1766             :      }
    1767             : 
    1768             :     mPostingKeyEvents++;
    1769             :     return true;
    1770             : }
    1771             : 
    1772             : /* set window long ptr hook for flash */
    1773             : 
    1774             : /*
    1775             :  * Flash will reset the subclass of our widget at various times.
    1776             :  * (Notably when entering and exiting full screen mode.) This
    1777             :  * occurs independent of the main plugin window event procedure.
    1778             :  * We trap these subclass calls to prevent our subclass hook from
    1779             :  * getting dropped.
    1780             :  * Note, ascii versions can be nixed once flash versions < 10.1
    1781             :  * are considered obsolete.
    1782             :  */
    1783             : 
    1784             : #ifdef _WIN64
    1785             : typedef LONG_PTR
    1786             :   (WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
    1787             :                                     int nIndex,
    1788             :                                     LONG_PTR dwNewLong);
    1789             : typedef LONG_PTR
    1790             :   (WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
    1791             :                                     int nIndex,
    1792             :                                     LONG_PTR dwNewLong);
    1793             : static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
    1794             : static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
    1795             : #else
    1796             : typedef LONG
    1797             : (WINAPI *User32SetWindowLongA)(HWND hWnd,
    1798             :                                int nIndex,
    1799             :                                LONG dwNewLong);
    1800             : typedef LONG
    1801             : (WINAPI *User32SetWindowLongW)(HWND hWnd,
    1802             :                                int nIndex,
    1803             :                                LONG dwNewLong);
    1804             : static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
    1805             : static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
    1806             : #endif
    1807             : 
    1808             : extern LRESULT CALLBACK
    1809             : NeuteredWindowProc(HWND hwnd,
    1810             :                    UINT uMsg,
    1811             :                    WPARAM wParam,
    1812             :                    LPARAM lParam);
    1813             : 
    1814             : const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
    1815             : 
    1816             : // static
    1817             : bool
    1818             : PluginInstanceChild::SetWindowLongHookCheck(HWND hWnd,
    1819             :                                             int nIndex,
    1820             :                                             LONG_PTR newLong)
    1821             : {
    1822             :       // Let this go through if it's not a subclass
    1823             :   if (nIndex != GWLP_WNDPROC ||
    1824             :       // if it's not a subclassed plugin window
    1825             :       !GetProp(hWnd, kPluginInstanceChildProperty) ||
    1826             :       // if we're not disabled
    1827             :       GetProp(hWnd, kPluginIgnoreSubclassProperty) ||
    1828             :       // if the subclass is set to a known procedure
    1829             :       newLong == reinterpret_cast<LONG_PTR>(PluginWindowProc) ||
    1830             :       newLong == reinterpret_cast<LONG_PTR>(NeuteredWindowProc) ||
    1831             :       newLong == reinterpret_cast<LONG_PTR>(DefWindowProcA) ||
    1832             :       newLong == reinterpret_cast<LONG_PTR>(DefWindowProcW) ||
    1833             :       // if the subclass is a WindowsMessageLoop subclass restore
    1834             :       GetProp(hWnd, kOldWndProcProp))
    1835             :       return true;
    1836             :   // prevent the subclass
    1837             :   return false;
    1838             : }
    1839             : 
    1840             : #ifdef _WIN64
    1841             : LONG_PTR WINAPI
    1842             : PluginInstanceChild::SetWindowLongPtrAHook(HWND hWnd,
    1843             :                                            int nIndex,
    1844             :                                            LONG_PTR newLong)
    1845             : #else
    1846             : LONG WINAPI
    1847             : PluginInstanceChild::SetWindowLongAHook(HWND hWnd,
    1848             :                                         int nIndex,
    1849             :                                         LONG newLong)
    1850             : #endif
    1851             : {
    1852             :     if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
    1853             :         return sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
    1854             : 
    1855             :     // Set flash's new subclass to get the result.
    1856             :     LONG_PTR proc = sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
    1857             : 
    1858             :     // We already checked this in SetWindowLongHookCheck
    1859             :     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
    1860             :         GetProp(hWnd, kPluginInstanceChildProperty));
    1861             : 
    1862             :     // Hook our subclass back up, just like we do on setwindow.
    1863             :     WNDPROC currentProc =
    1864             :         reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
    1865             :     if (currentProc != PluginWindowProc) {
    1866             :         self->mPluginWndProc =
    1867             :             reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex,
    1868             :                 reinterpret_cast<LONG_PTR>(PluginWindowProc)));
    1869             :         NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
    1870             :     }
    1871             :     return proc;
    1872             : }
    1873             : 
    1874             : #ifdef _WIN64
    1875             : LONG_PTR WINAPI
    1876             : PluginInstanceChild::SetWindowLongPtrWHook(HWND hWnd,
    1877             :                                            int nIndex,
    1878             :                                            LONG_PTR newLong)
    1879             : #else
    1880             : LONG WINAPI
    1881             : PluginInstanceChild::SetWindowLongWHook(HWND hWnd,
    1882             :                                         int nIndex,
    1883             :                                         LONG newLong)
    1884             : #endif
    1885             : {
    1886             :     if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
    1887             :         return sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
    1888             : 
    1889             :     // Set flash's new subclass to get the result.
    1890             :     LONG_PTR proc = sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
    1891             : 
    1892             :     // We already checked this in SetWindowLongHookCheck
    1893             :     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
    1894             :         GetProp(hWnd, kPluginInstanceChildProperty));
    1895             : 
    1896             :     // Hook our subclass back up, just like we do on setwindow.
    1897             :     WNDPROC currentProc =
    1898             :         reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
    1899             :     if (currentProc != PluginWindowProc) {
    1900             :         self->mPluginWndProc =
    1901             :             reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex,
    1902             :                 reinterpret_cast<LONG_PTR>(PluginWindowProc)));
    1903             :         NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
    1904             :     }
    1905             :     return proc;
    1906             : }
    1907             : 
    1908             : void
    1909             : PluginInstanceChild::HookSetWindowLongPtr()
    1910             : {
    1911             :     if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR))
    1912             :         return;
    1913             : 
    1914             :     sUser32Intercept.Init("user32.dll");
    1915             : #ifdef _WIN64
    1916             :     if (!sUser32SetWindowLongAHookStub)
    1917             :         sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
    1918             :                                  (void**) &sUser32SetWindowLongAHookStub);
    1919             :     if (!sUser32SetWindowLongWHookStub)
    1920             :         sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
    1921             :                                  (void**) &sUser32SetWindowLongWHookStub);
    1922             : #else
    1923             :     if (!sUser32SetWindowLongAHookStub)
    1924             :         sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook),
    1925             :                                  (void**) &sUser32SetWindowLongAHookStub);
    1926             :     if (!sUser32SetWindowLongWHookStub)
    1927             :         sUser32Intercept.AddHook("SetWindowLongW", reinterpret_cast<intptr_t>(SetWindowLongWHook),
    1928             :                                  (void**) &sUser32SetWindowLongWHookStub);
    1929             : #endif
    1930             : }
    1931             : 
    1932             : /* windowless track popup menu helpers */
    1933             : 
    1934             : BOOL
    1935             : WINAPI
    1936             : PluginInstanceChild::TrackPopupHookProc(HMENU hMenu,
    1937             :                                         UINT uFlags,
    1938             :                                         int x,
    1939             :                                         int y,
    1940             :                                         int nReserved,
    1941             :                                         HWND hWnd,
    1942             :                                         CONST RECT *prcRect)
    1943             : {
    1944             :   if (!sUser32TrackPopupMenuStub) {
    1945             :       NS_ERROR("TrackPopupMenu stub isn't set! Badness!");
    1946             :       return 0;
    1947             :   }
    1948             : 
    1949             :   // Only change the parent when we know this is a context on the plugin
    1950             :   // surface within the browser. Prevents resetting the parent on child ui
    1951             :   // displayed by plugins that have working parent-child relationships.
    1952             :   wchar_t szClass[21];
    1953             :   bool haveClass = GetClassNameW(hWnd, szClass, ArrayLength(szClass));
    1954             :   if (!haveClass ||
    1955             :       (wcscmp(szClass, L"MozillaWindowClass") &&
    1956             :        wcscmp(szClass, L"SWFlash_Placeholder"))) {
    1957             :       // Unrecognized parent
    1958             :       return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved,
    1959             :                                        hWnd, prcRect);
    1960             :   }
    1961             : 
    1962             :   // Called on an unexpected event, warn.
    1963             :   if (!sWinlessPopupSurrogateHWND) {
    1964             :       NS_WARNING(
    1965             :           "Untraced TrackPopupHookProc call! Menu might not work right!");
    1966             :       return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved,
    1967             :                                        hWnd, prcRect);
    1968             :   }
    1969             : 
    1970             :   HWND surrogateHwnd = sWinlessPopupSurrogateHWND;
    1971             :   sWinlessPopupSurrogateHWND = nullptr;
    1972             : 
    1973             :   // Popups that don't use TPM_RETURNCMD expect a final command message
    1974             :   // when an item is selected and the context closes. Since we replace
    1975             :   // the parent, we need to forward this back to the real parent so it
    1976             :   // can act on the menu item selected.
    1977             :   bool isRetCmdCall = (uFlags & TPM_RETURNCMD);
    1978             : 
    1979             :   DWORD res = sUser32TrackPopupMenuStub(hMenu, uFlags|TPM_RETURNCMD, x, y,
    1980             :                                         nReserved, surrogateHwnd, prcRect);
    1981             : 
    1982             :   if (!isRetCmdCall && res) {
    1983             :       SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(res, 0), 0);
    1984             :   }
    1985             : 
    1986             :   return res;
    1987             : }
    1988             : 
    1989             : void
    1990             : PluginInstanceChild::InitPopupMenuHook()
    1991             : {
    1992             :     if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) ||
    1993             :         sUser32TrackPopupMenuStub)
    1994             :         return;
    1995             : 
    1996             :     // Note, once WindowsDllInterceptor is initialized for a module,
    1997             :     // it remains initialized for that particular module for it's
    1998             :     // lifetime. Additional instances are needed if other modules need
    1999             :     // to be hooked.
    2000             :     if (!sUser32TrackPopupMenuStub) {
    2001             :         sUser32Intercept.Init("user32.dll");
    2002             :         sUser32Intercept.AddHook("TrackPopupMenu", reinterpret_cast<intptr_t>(TrackPopupHookProc),
    2003             :                                  (void**) &sUser32TrackPopupMenuStub);
    2004             :     }
    2005             : }
    2006             : 
    2007             : void
    2008             : PluginInstanceChild::CreateWinlessPopupSurrogate()
    2009             : {
    2010             :     // already initialized
    2011             :     if (mWinlessPopupSurrogateHWND)
    2012             :         return;
    2013             : 
    2014             :     mWinlessPopupSurrogateHWND =
    2015             :         CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_POPUP,
    2016             :                        0, 0, 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0);
    2017             :     if (!mWinlessPopupSurrogateHWND) {
    2018             :         NS_ERROR("CreateWindowEx failed for winless placeholder!");
    2019             :         return;
    2020             :     }
    2021             : 
    2022             :     SendSetNetscapeWindowAsParent(mWinlessPopupSurrogateHWND);
    2023             : }
    2024             : 
    2025             : // static
    2026             : HIMC
    2027             : PluginInstanceChild::ImmGetContextProc(HWND aWND)
    2028             : {
    2029             :     if (!sCurrentPluginInstance) {
    2030             :         return sImm32ImmGetContextStub(aWND);
    2031             :     }
    2032             : 
    2033             :     wchar_t szClass[21];
    2034             :     int haveClass = GetClassNameW(aWND, szClass, ArrayLength(szClass));
    2035             :     if (!haveClass || wcscmp(szClass, L"SWFlash_PlaceholderX")) {
    2036             :         NS_WARNING("We cannot recongnize hooked window class");
    2037             :         return sImm32ImmGetContextStub(aWND);
    2038             :     }
    2039             : 
    2040             :     return sHookIMC;
    2041             : }
    2042             : 
    2043             : // static
    2044             : BOOL
    2045             : PluginInstanceChild::ImmReleaseContextProc(HWND aWND, HIMC aIMC)
    2046             : {
    2047             :     if (aIMC == sHookIMC) {
    2048             :         return TRUE;
    2049             :     }
    2050             : 
    2051             :     return sImm32ImmReleaseContextStub(aWND, aIMC);
    2052             : }
    2053             : 
    2054             : // static
    2055             : LONG
    2056             : PluginInstanceChild::ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex,
    2057             :                                                  LPVOID aBuf, DWORD aLen)
    2058             : {
    2059             :     if (aIMC != sHookIMC) {
    2060             :         return sImm32ImmGetCompositionStringStub(aIMC, aIndex, aBuf, aLen);
    2061             :     }
    2062             :     if (!sCurrentPluginInstance) {
    2063             :         return IMM_ERROR_GENERAL;
    2064             :     }
    2065             :     AutoTArray<uint8_t, 16> dist;
    2066             :     int32_t length = 0; // IMM_ERROR_NODATA
    2067             :     sCurrentPluginInstance->SendGetCompositionString(aIndex, &dist, &length);
    2068             :     if (length == IMM_ERROR_NODATA || length == IMM_ERROR_GENERAL) {
    2069             :       return length;
    2070             :     }
    2071             : 
    2072             :     if (aBuf && aLen >= static_cast<DWORD>(length)) {
    2073             :         memcpy(aBuf, dist.Elements(), length);
    2074             :     }
    2075             :     return length;
    2076             : }
    2077             : 
    2078             : // staitc
    2079             : BOOL
    2080             : PluginInstanceChild::ImmSetCandidateWindowProc(HIMC aIMC, LPCANDIDATEFORM aForm)
    2081             : {
    2082             :     if (aIMC != sHookIMC) {
    2083             :         return sImm32ImmSetCandidateWindowStub(aIMC, aForm);
    2084             :     }
    2085             : 
    2086             :     if (!sCurrentPluginInstance ||
    2087             :         aForm->dwIndex != 0) {
    2088             :         return FALSE;
    2089             :     }
    2090             : 
    2091             :     CandidateWindowPosition position;
    2092             :     position.mPoint.x = aForm->ptCurrentPos.x;
    2093             :     position.mPoint.y = aForm->ptCurrentPos.y;
    2094             :     position.mExcludeRect = !!(aForm->dwStyle & CFS_EXCLUDE);
    2095             :     if (position.mExcludeRect) {
    2096             :       position.mRect.x = aForm->rcArea.left;
    2097             :       position.mRect.y = aForm->rcArea.top;
    2098             :       position.mRect.width = aForm->rcArea.right - aForm->rcArea.left;
    2099             :       position.mRect.height = aForm->rcArea.bottom - aForm->rcArea.top;
    2100             :     }
    2101             : 
    2102             :     sCurrentPluginInstance->SendSetCandidateWindow(position);
    2103             :     return TRUE;
    2104             : }
    2105             : 
    2106             : // static
    2107             : BOOL
    2108             : PluginInstanceChild::ImmNotifyIME(HIMC aIMC, DWORD aAction, DWORD aIndex,
    2109             :                                   DWORD aValue)
    2110             : {
    2111             :     if (aIMC != sHookIMC) {
    2112             :         return sImm32ImmNotifyIME(aIMC, aAction, aIndex, aValue);
    2113             :     }
    2114             : 
    2115             :     // We only supports NI_COMPOSITIONSTR because Flash uses it only
    2116             :     if (!sCurrentPluginInstance ||
    2117             :         aAction != NI_COMPOSITIONSTR ||
    2118             :         (aIndex != CPS_COMPLETE && aIndex != CPS_CANCEL)) {
    2119             :         return FALSE;
    2120             :     }
    2121             : 
    2122             :     sCurrentPluginInstance->SendRequestCommitOrCancel(aAction == CPS_COMPLETE);
    2123             :     return TRUE;
    2124             : }
    2125             : 
    2126             : void
    2127             : PluginInstanceChild::InitImm32Hook()
    2128             : {
    2129             :     if (!(GetQuirks() & QUIRK_WINLESS_HOOK_IME)) {
    2130             :         return;
    2131             :     }
    2132             : 
    2133             :     if (sImm32ImmGetContextStub) {
    2134             :         return;
    2135             :     }
    2136             : 
    2137             :     // When using windowless plugin, IMM API won't work due ot OOP.
    2138             : 
    2139             :     sImm32Intercept.Init("imm32.dll");
    2140             :     sImm32Intercept.AddHook(
    2141             :         "ImmGetContext",
    2142             :         reinterpret_cast<intptr_t>(ImmGetContextProc),
    2143             :         (void**)&sImm32ImmGetContextStub);
    2144             :     sImm32Intercept.AddHook(
    2145             :         "ImmReleaseContext",
    2146             :         reinterpret_cast<intptr_t>(ImmReleaseContextProc),
    2147             :         (void**)&sImm32ImmReleaseContextStub);
    2148             :     sImm32Intercept.AddHook(
    2149             :         "ImmGetCompositionStringW",
    2150             :         reinterpret_cast<intptr_t>(ImmGetCompositionStringProc),
    2151             :         (void**)&sImm32ImmGetCompositionStringStub);
    2152             :     sImm32Intercept.AddHook(
    2153             :         "ImmSetCandidateWindow",
    2154             :         reinterpret_cast<intptr_t>(ImmSetCandidateWindowProc),
    2155             :         (void**)&sImm32ImmSetCandidateWindowStub);
    2156             :     sImm32Intercept.AddHook(
    2157             :         "ImmNotifyIME",
    2158             :         reinterpret_cast<intptr_t>(ImmNotifyIME),
    2159             :         (void**)&sImm32ImmNotifyIME);
    2160             : }
    2161             : 
    2162             : void
    2163             : PluginInstanceChild::DestroyWinlessPopupSurrogate()
    2164             : {
    2165             :     if (mWinlessPopupSurrogateHWND)
    2166             :         DestroyWindow(mWinlessPopupSurrogateHWND);
    2167             :     mWinlessPopupSurrogateHWND = nullptr;
    2168             : }
    2169             : 
    2170             : int16_t
    2171             : PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
    2172             : {
    2173             :     if (!mPluginIface->event)
    2174             :         return false;
    2175             : 
    2176             :     // Events that might generate nested event dispatch loops need
    2177             :     // special handling during delivery.
    2178             :     int16_t handled;
    2179             : 
    2180             :     HWND focusHwnd = nullptr;
    2181             : 
    2182             :     // TrackPopupMenu will fail if the parent window is not associated with
    2183             :     // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
    2184             :     // parent created in the child process.
    2185             :     if ((GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default?
    2186             :           (event.event == WM_RBUTTONDOWN || // flash
    2187             :            event.event == WM_RBUTTONUP)) {  // silverlight
    2188             :       sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND;
    2189             : 
    2190             :       // A little trick scrounged from chromium's code - set the focus
    2191             :       // to our surrogate parent so keyboard nav events go to the menu.
    2192             :       focusHwnd = SetFocus(mWinlessPopupSurrogateHWND);
    2193             :     }
    2194             : 
    2195             :     AutoRestore<PluginInstanceChild *> pluginInstance(sCurrentPluginInstance);
    2196             :     if (event.event == WM_IME_STARTCOMPOSITION ||
    2197             :         event.event == WM_IME_COMPOSITION ||
    2198             :         event.event == WM_KILLFOCUS) {
    2199             :       sCurrentPluginInstance = this;
    2200             :     }
    2201             : 
    2202             :     MessageLoop* loop = MessageLoop::current();
    2203             :     AutoRestore<bool> modalLoop(loop->os_modal_loop());
    2204             : 
    2205             :     handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
    2206             : 
    2207             :     sWinlessPopupSurrogateHWND = nullptr;
    2208             : 
    2209             :     if (IsWindow(focusHwnd)) {
    2210             :       SetFocus(focusHwnd);
    2211             :     }
    2212             : 
    2213             :     return handled;
    2214             : }
    2215             : 
    2216             : /* flash msg throttling helpers */
    2217             : 
    2218             : // Flash has the unfortunate habit of flooding dispatch loops with custom
    2219             : // windowing events they use for timing. We throttle these by dropping the
    2220             : // delivery priority below any other event, including pending ipc io
    2221             : // notifications. We do this for both windowed and windowless controls.
    2222             : // Note flash's windowless msg window can last longer than our instance,
    2223             : // so we try to unhook when the window is destroyed and in NPP_Destroy.
    2224             : 
    2225             : void
    2226             : PluginInstanceChild::UnhookWinlessFlashThrottle()
    2227             : {
    2228             :   // We may have already unhooked
    2229             :   if (!mWinlessThrottleOldWndProc)
    2230             :       return;
    2231             : 
    2232             :   WNDPROC tmpProc = mWinlessThrottleOldWndProc;
    2233             :   mWinlessThrottleOldWndProc = nullptr;
    2234             : 
    2235             :   NS_ASSERTION(mWinlessHiddenMsgHWND,
    2236             :                "Missing mWinlessHiddenMsgHWND w/subclass set??");
    2237             : 
    2238             :   // reset the subclass
    2239             :   SetWindowLongPtr(mWinlessHiddenMsgHWND, GWLP_WNDPROC,
    2240             :                    reinterpret_cast<LONG_PTR>(tmpProc));
    2241             : 
    2242             :   // Remove our instance prop
    2243             :   RemoveProp(mWinlessHiddenMsgHWND, kFlashThrottleProperty);
    2244             :   mWinlessHiddenMsgHWND = nullptr;
    2245             : }
    2246             : 
    2247             : // static
    2248             : LRESULT CALLBACK
    2249             : PluginInstanceChild::WinlessHiddenFlashWndProc(HWND hWnd,
    2250             :                                                UINT message,
    2251             :                                                WPARAM wParam,
    2252             :                                                LPARAM lParam)
    2253             : {
    2254             :     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
    2255             :         GetProp(hWnd, kFlashThrottleProperty));
    2256             :     if (!self) {
    2257             :         NS_NOTREACHED("Badness!");
    2258             :         return 0;
    2259             :     }
    2260             : 
    2261             :     NS_ASSERTION(self->mWinlessThrottleOldWndProc,
    2262             :                  "Missing subclass procedure!!");
    2263             : 
    2264             :     // Throttle
    2265             :     if (message == WM_USER+1) {
    2266             :         self->FlashThrottleMessage(hWnd, message, wParam, lParam, false);
    2267             :         return 0;
    2268             :      }
    2269             : 
    2270             :     // Unhook
    2271             :     if (message == WM_CLOSE || message == WM_NCDESTROY) {
    2272             :         WNDPROC tmpProc = self->mWinlessThrottleOldWndProc;
    2273             :         self->UnhookWinlessFlashThrottle();
    2274             :         LRESULT res = CallWindowProc(tmpProc, hWnd, message, wParam, lParam);
    2275             :         return res;
    2276             :     }
    2277             : 
    2278             :     return CallWindowProc(self->mWinlessThrottleOldWndProc,
    2279             :                           hWnd, message, wParam, lParam);
    2280             : }
    2281             : 
    2282             : // Enumerate all thread windows looking for flash's hidden message window.
    2283             : // Once we find it, sub class it so we can throttle user msgs.
    2284             : // static
    2285             : BOOL CALLBACK
    2286             : PluginInstanceChild::EnumThreadWindowsCallback(HWND hWnd,
    2287             :                                                LPARAM aParam)
    2288             : {
    2289             :     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(aParam);
    2290             :     if (!self) {
    2291             :         NS_NOTREACHED("Enum befuddled!");
    2292             :         return FALSE;
    2293             :     }
    2294             : 
    2295             :     wchar_t className[64];
    2296             :     if (!GetClassNameW(hWnd, className, sizeof(className)/sizeof(char16_t)))
    2297             :       return TRUE;
    2298             : 
    2299             :     if (!wcscmp(className, L"SWFlash_PlaceholderX")) {
    2300             :         WNDPROC oldWndProc =
    2301             :             reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC));
    2302             :         // Only set this if we haven't already.
    2303             :         if (oldWndProc != WinlessHiddenFlashWndProc) {
    2304             :             if (self->mWinlessThrottleOldWndProc) {
    2305             :                 NS_WARNING("mWinlessThrottleWndProc already set???");
    2306             :                 return FALSE;
    2307             :             }
    2308             :             // Subsclass and store self as a property
    2309             :             self->mWinlessHiddenMsgHWND = hWnd;
    2310             :             self->mWinlessThrottleOldWndProc =
    2311             :                 reinterpret_cast<WNDPROC>(SetWindowLongPtr(hWnd, GWLP_WNDPROC,
    2312             :                 reinterpret_cast<LONG_PTR>(WinlessHiddenFlashWndProc)));
    2313             :             SetProp(hWnd, kFlashThrottleProperty, self);
    2314             :             NS_ASSERTION(self->mWinlessThrottleOldWndProc,
    2315             :                          "SetWindowLongPtr failed?!");
    2316             :         }
    2317             :         // Return no matter what once we find the right window.
    2318             :         return FALSE;
    2319             :     }
    2320             : 
    2321             :     return TRUE;
    2322             : }
    2323             : 
    2324             : void
    2325             : PluginInstanceChild::SetupFlashMsgThrottle()
    2326             : {
    2327             :     if (mWindow.type == NPWindowTypeDrawable) {
    2328             :         // Search for the flash hidden message window and subclass it. Only
    2329             :         // search for flash windows belonging to our ui thread!
    2330             :         if (mWinlessThrottleOldWndProc)
    2331             :             return;
    2332             :         EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsCallback,
    2333             :                           reinterpret_cast<LPARAM>(this));
    2334             :     }
    2335             :     else {
    2336             :         // Already setup through quirks and the subclass.
    2337             :         return;
    2338             :     }
    2339             : }
    2340             : 
    2341             : WNDPROC
    2342             : PluginInstanceChild::FlashThrottleAsyncMsg::GetProc()
    2343             : {
    2344             :     if (mInstance) {
    2345             :         return mWindowed ? mInstance->mPluginWndProc :
    2346             :                            mInstance->mWinlessThrottleOldWndProc;
    2347             :     }
    2348             :     return nullptr;
    2349             : }
    2350             : 
    2351             : NS_IMETHODIMP
    2352             : PluginInstanceChild::FlashThrottleAsyncMsg::Run()
    2353             : {
    2354             :     RemoveFromAsyncList();
    2355             : 
    2356             :     // GetProc() checks mInstance, and pulls the procedure from
    2357             :     // PluginInstanceChild. We don't transport sub-class procedure
    2358             :     // ptrs around in FlashThrottleAsyncMsg msgs.
    2359             :     if (!GetProc())
    2360             :         return NS_OK;
    2361             : 
    2362             :     // deliver the event to flash
    2363             :     CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam());
    2364             :     return NS_OK;
    2365             : }
    2366             : 
    2367             : void
    2368             : PluginInstanceChild::FlashThrottleMessage(HWND aWnd,
    2369             :                                           UINT aMsg,
    2370             :                                           WPARAM aWParam,
    2371             :                                           LPARAM aLParam,
    2372             :                                           bool isWindowed)
    2373             : {
    2374             :     // We reuse ChildAsyncCall so we get the cancelation work
    2375             :     // that's done in Destroy.
    2376             :     RefPtr<FlashThrottleAsyncMsg> task =
    2377             :         new FlashThrottleAsyncMsg(this, aWnd, aMsg, aWParam,
    2378             :                                   aLParam, isWindowed);
    2379             :     {
    2380             :         MutexAutoLock lock(mAsyncCallMutex);
    2381             :         mPendingAsyncCalls.AppendElement(task);
    2382             :     }
    2383             :     MessageLoop::current()->PostDelayedTask(task.forget(),
    2384             :                                             kFlashWMUSERMessageThrottleDelayMs);
    2385             : }
    2386             : 
    2387             : #endif // OS_WIN
    2388             : 
    2389             : mozilla::ipc::IPCResult
    2390           0 : PluginInstanceChild::AnswerSetPluginFocus()
    2391             : {
    2392           0 :     MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s", FULLFUNCTION));
    2393             : 
    2394             : #if defined(OS_WIN)
    2395             :     // Parent is letting us know the dom set focus to the plugin. Note,
    2396             :     // focus can change during transit in certain edge cases, for example
    2397             :     // when a button click brings up a full screen window. Since we send
    2398             :     // this in response to a WM_SETFOCUS event on our parent, the parent
    2399             :     // should have focus when we receive this. If not, ignore the call.
    2400             :     if (::GetFocus() == mPluginWindowHWND)
    2401             :         return IPC_OK();
    2402             :     ::SetFocus(mPluginWindowHWND);
    2403             :     return IPC_OK();
    2404             : #else
    2405           0 :     NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!");
    2406           0 :     return IPC_FAIL_NO_REASON(this);
    2407             : #endif
    2408             : }
    2409             : 
    2410             : mozilla::ipc::IPCResult
    2411           0 : PluginInstanceChild::AnswerUpdateWindow()
    2412             : {
    2413           0 :     MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s", FULLFUNCTION));
    2414             : 
    2415             : #if defined(OS_WIN)
    2416             :     if (mPluginWindowHWND) {
    2417             :         RECT rect;
    2418             :         if (GetUpdateRect(GetParent(mPluginWindowHWND), &rect, FALSE)) {
    2419             :             ::InvalidateRect(mPluginWindowHWND, &rect, FALSE);
    2420             :         }
    2421             :         UpdateWindow(mPluginWindowHWND);
    2422             :     }
    2423             :     return IPC_OK();
    2424             : #else
    2425           0 :     NS_NOTREACHED("PluginInstanceChild::AnswerUpdateWindow not implemented!");
    2426           0 :     return IPC_FAIL_NO_REASON(this);
    2427             : #endif
    2428             : }
    2429             : 
    2430             : mozilla::ipc::IPCResult
    2431           0 : PluginInstanceChild::RecvNPP_DidComposite()
    2432             : {
    2433           0 :   if (mPluginIface->didComposite) {
    2434           0 :     mPluginIface->didComposite(GetNPP());
    2435             :   }
    2436           0 :   return IPC_OK();
    2437             : }
    2438             : 
    2439             : PPluginScriptableObjectChild*
    2440           0 : PluginInstanceChild::AllocPPluginScriptableObjectChild()
    2441             : {
    2442           0 :     AssertPluginThread();
    2443           0 :     return new PluginScriptableObjectChild(Proxy);
    2444             : }
    2445             : 
    2446             : bool
    2447           0 : PluginInstanceChild::DeallocPPluginScriptableObjectChild(
    2448             :     PPluginScriptableObjectChild* aObject)
    2449             : {
    2450           0 :     AssertPluginThread();
    2451           0 :     delete aObject;
    2452           0 :     return true;
    2453             : }
    2454             : 
    2455             : mozilla::ipc::IPCResult
    2456           0 : PluginInstanceChild::RecvPPluginScriptableObjectConstructor(
    2457             :                                            PPluginScriptableObjectChild* aActor)
    2458             : {
    2459           0 :     AssertPluginThread();
    2460             : 
    2461             :     // This is only called in response to the parent process requesting the
    2462             :     // creation of an actor. This actor will represent an NPObject that is
    2463             :     // created by the browser and returned to the plugin.
    2464             :     PluginScriptableObjectChild* actor =
    2465           0 :         static_cast<PluginScriptableObjectChild*>(aActor);
    2466           0 :     NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!");
    2467             : 
    2468           0 :     actor->InitializeProxy();
    2469           0 :     NS_ASSERTION(actor->GetObject(false), "Actor should have an object!");
    2470             : 
    2471           0 :     return IPC_OK();
    2472             : }
    2473             : 
    2474             : mozilla::ipc::IPCResult
    2475           0 : PluginInstanceChild::RecvPBrowserStreamConstructor(
    2476             :     PBrowserStreamChild* aActor,
    2477             :     const nsCString& url,
    2478             :     const uint32_t& length,
    2479             :     const uint32_t& lastmodified,
    2480             :     PStreamNotifyChild* notifyData,
    2481             :     const nsCString& headers)
    2482             : {
    2483           0 :     return IPC_OK();
    2484             : }
    2485             : 
    2486             : NPError
    2487           0 : PluginInstanceChild::DoNPP_NewStream(BrowserStreamChild* actor,
    2488             :                                      const nsCString& mimeType,
    2489             :                                      const bool& seekable,
    2490             :                                      uint16_t* stype)
    2491             : {
    2492           0 :     AssertPluginThread();
    2493           0 :     AutoStackHelper guard(this);
    2494           0 :     NPError rv = actor->StreamConstructed(mimeType, seekable, stype);
    2495           0 :     return rv;
    2496             : }
    2497             : 
    2498             : mozilla::ipc::IPCResult
    2499           0 : PluginInstanceChild::AnswerNPP_NewStream(PBrowserStreamChild* actor,
    2500             :                                          const nsCString& mimeType,
    2501             :                                          const bool& seekable,
    2502             :                                          NPError* rv,
    2503             :                                          uint16_t* stype)
    2504             : {
    2505           0 :     *rv = DoNPP_NewStream(static_cast<BrowserStreamChild*>(actor), mimeType,
    2506             :                           seekable, stype);
    2507           0 :     return IPC_OK();
    2508             : }
    2509             : 
    2510             : PBrowserStreamChild*
    2511           0 : PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url,
    2512             :                                               const uint32_t& length,
    2513             :                                               const uint32_t& lastmodified,
    2514             :                                               PStreamNotifyChild* notifyData,
    2515             :                                               const nsCString& headers)
    2516             : {
    2517           0 :     AssertPluginThread();
    2518             :     return new BrowserStreamChild(this, url, length, lastmodified,
    2519             :                                   static_cast<StreamNotifyChild*>(notifyData),
    2520           0 :                                   headers);
    2521             : }
    2522             : 
    2523             : bool
    2524           0 : PluginInstanceChild::DeallocPBrowserStreamChild(PBrowserStreamChild* stream)
    2525             : {
    2526           0 :     AssertPluginThread();
    2527           0 :     delete stream;
    2528           0 :     return true;
    2529             : }
    2530             : 
    2531             : 
    2532             : PStreamNotifyChild*
    2533           0 : PluginInstanceChild::AllocPStreamNotifyChild(const nsCString& url,
    2534             :                                              const nsCString& target,
    2535             :                                              const bool& post,
    2536             :                                              const nsCString& buffer,
    2537             :                                              const bool& file,
    2538             :                                              NPError* result)
    2539             : {
    2540           0 :     AssertPluginThread();
    2541           0 :     MOZ_CRASH("not reached");
    2542             :     return nullptr;
    2543             : }
    2544             : 
    2545             : void
    2546           0 : StreamNotifyChild::ActorDestroy(ActorDestroyReason why)
    2547             : {
    2548           0 :     if (AncestorDeletion == why && mBrowserStream) {
    2549           0 :         NS_ERROR("Pending NPP_URLNotify not called when closing an instance.");
    2550             : 
    2551             :         // reclaim responsibility for deleting ourself
    2552           0 :         mBrowserStream->mStreamNotify = nullptr;
    2553           0 :         mBrowserStream = nullptr;
    2554             :     }
    2555           0 : }
    2556             : 
    2557             : void
    2558           0 : StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs)
    2559             : {
    2560           0 :     NS_ASSERTION(!mBrowserStream, "Two streams for one streamnotify?");
    2561             : 
    2562           0 :     mBrowserStream = bs;
    2563           0 : }
    2564             : 
    2565             : mozilla::ipc::IPCResult
    2566           0 : StreamNotifyChild::Recv__delete__(const NPReason& reason)
    2567             : {
    2568           0 :     AssertPluginThread();
    2569             : 
    2570           0 :     if (mBrowserStream)
    2571           0 :         mBrowserStream->NotifyPending();
    2572             :     else
    2573           0 :         NPP_URLNotify(reason);
    2574             : 
    2575           0 :     return IPC_OK();
    2576             : }
    2577             : 
    2578             : mozilla::ipc::IPCResult
    2579           0 : StreamNotifyChild::RecvRedirectNotify(const nsCString& url, const int32_t& status)
    2580             : {
    2581             :     // NPP_URLRedirectNotify requires a non-null closure. Since core logic
    2582             :     // assumes that all out-of-process notify streams have non-null closure
    2583             :     // data it will assume that the plugin was notified at this point and
    2584             :     // expect a response otherwise the redirect will hang indefinitely.
    2585           0 :     if (!mClosure) {
    2586           0 :         SendRedirectNotifyResponse(false);
    2587             :     }
    2588             : 
    2589           0 :     PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager());
    2590           0 :     if (instance->mPluginIface->urlredirectnotify)
    2591           0 :       instance->mPluginIface->urlredirectnotify(instance->GetNPP(), url.get(), status, mClosure);
    2592             : 
    2593           0 :     return IPC_OK();
    2594             : }
    2595             : 
    2596             : void
    2597           0 : StreamNotifyChild::NPP_URLNotify(NPReason reason)
    2598             : {
    2599           0 :     PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager());
    2600             : 
    2601           0 :     if (mClosure)
    2602           0 :         instance->mPluginIface->urlnotify(instance->GetNPP(), mURL.get(),
    2603           0 :                                           reason, mClosure);
    2604           0 : }
    2605             : 
    2606             : bool
    2607           0 : PluginInstanceChild::DeallocPStreamNotifyChild(PStreamNotifyChild* notifyData)
    2608             : {
    2609           0 :     AssertPluginThread();
    2610             : 
    2611           0 :     if (!static_cast<StreamNotifyChild*>(notifyData)->mBrowserStream)
    2612           0 :         delete notifyData;
    2613           0 :     return true;
    2614             : }
    2615             : 
    2616             : PluginScriptableObjectChild*
    2617           0 : PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
    2618             : {
    2619           0 :     AssertPluginThread();
    2620           0 :     NS_ASSERTION(aObject, "Null pointer!");
    2621             : 
    2622           0 :     if (aObject->_class == PluginScriptableObjectChild::GetClass()) {
    2623             :         // One of ours! It's a browser-provided object.
    2624           0 :         ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
    2625           0 :         NS_ASSERTION(object->parent, "Null actor!");
    2626           0 :         return object->parent;
    2627             :     }
    2628             : 
    2629             :     PluginScriptableObjectChild* actor =
    2630           0 :         PluginScriptableObjectChild::GetActorForNPObject(aObject);
    2631           0 :     if (actor) {
    2632             :         // Plugin-provided object that we've previously wrapped.
    2633           0 :         return actor;
    2634             :     }
    2635             : 
    2636           0 :     actor = new PluginScriptableObjectChild(LocalObject);
    2637           0 :     if (!SendPPluginScriptableObjectConstructor(actor)) {
    2638           0 :         NS_ERROR("Failed to send constructor message!");
    2639           0 :         return nullptr;
    2640             :     }
    2641             : 
    2642           0 :     actor->InitializeLocal(aObject);
    2643           0 :     return actor;
    2644             : }
    2645             : 
    2646             : void
    2647           0 : PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData, NPBool allow)
    2648             : {
    2649           0 :     if (!notifyData) {
    2650           0 :         return;
    2651             :     }
    2652             : 
    2653           0 :     InfallibleTArray<PStreamNotifyChild*> notifyStreams;
    2654           0 :     ManagedPStreamNotifyChild(notifyStreams);
    2655           0 :     uint32_t notifyStreamCount = notifyStreams.Length();
    2656           0 :     for (uint32_t i = 0; i < notifyStreamCount; i++) {
    2657           0 :         StreamNotifyChild* sn = static_cast<StreamNotifyChild*>(notifyStreams[i]);
    2658           0 :         if (sn->mClosure == notifyData) {
    2659           0 :             sn->SendRedirectNotifyResponse(static_cast<bool>(allow));
    2660           0 :             return;
    2661             :         }
    2662             :     }
    2663           0 :     NS_ASSERTION(false, "Couldn't find stream for redirect response!");
    2664             : }
    2665             : 
    2666             : bool
    2667           0 : PluginInstanceChild::IsUsingDirectDrawing()
    2668             : {
    2669           0 :     return IsDrawingModelDirect(mDrawingModel);
    2670             : }
    2671             : 
    2672           0 : PluginInstanceChild::DirectBitmap::DirectBitmap(PluginInstanceChild* aOwner, const Shmem& shmem,
    2673           0 :                                                 const IntSize& size, uint32_t stride, SurfaceFormat format)
    2674             :   : mOwner(aOwner),
    2675             :     mShmem(shmem),
    2676             :     mFormat(format),
    2677             :     mSize(size),
    2678           0 :     mStride(stride)
    2679             : {
    2680           0 : }
    2681             : 
    2682           0 : PluginInstanceChild::DirectBitmap::~DirectBitmap()
    2683             : {
    2684           0 :     mOwner->DeallocShmem(mShmem);
    2685           0 : }
    2686             : 
    2687             : static inline SurfaceFormat
    2688           0 : NPImageFormatToSurfaceFormat(NPImageFormat aFormat)
    2689             : {
    2690           0 :     switch (aFormat) {
    2691             :     case NPImageFormatBGRA32:
    2692           0 :         return SurfaceFormat::B8G8R8A8;
    2693             :     case NPImageFormatBGRX32:
    2694           0 :         return SurfaceFormat::B8G8R8X8;
    2695             :     default:
    2696           0 :         MOZ_ASSERT_UNREACHABLE("unknown NPImageFormat");
    2697             :         return SurfaceFormat::UNKNOWN;
    2698             :     }
    2699             : }
    2700             : 
    2701             : static inline gfx::IntRect
    2702           0 : NPRectToIntRect(const NPRect& in)
    2703             : {
    2704           0 :     return IntRect(in.left, in.top, in.right - in.left, in.bottom - in.top);
    2705             : }
    2706             : 
    2707             : NPError
    2708           0 : PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
    2709             :                                           void *initData, NPAsyncSurface *surface)
    2710             : {
    2711           0 :     AssertPluginThread();
    2712           0 :     AutoStackHelper guard(this);
    2713             : 
    2714           0 :     if (!IsUsingDirectDrawing()) {
    2715           0 :         return NPERR_INVALID_PARAM;
    2716             :     }
    2717           0 :     if (format != NPImageFormatBGRA32 && format != NPImageFormatBGRX32) {
    2718           0 :         return NPERR_INVALID_PARAM;
    2719             :     }
    2720             : 
    2721           0 :     PodZero(surface);
    2722             : 
    2723             :     // NPAPI guarantees that the SetCurrentAsyncSurface call will release the
    2724             :     // previous surface if it was different. However, no functionality exists
    2725             :     // within content to synchronize a non-shadow-layers transaction with the
    2726             :     // compositor.
    2727             :     //
    2728             :     // To get around this, we allocate two surfaces: a child copy, which we
    2729             :     // hand off to the plugin, and a parent copy, which we will hand off to
    2730             :     // the compositor. Each call to SetCurrentAsyncSurface will copy the
    2731             :     // invalid region from the child surface to its parent.
    2732           0 :     switch (mDrawingModel) {
    2733             :     case NPDrawingModelAsyncBitmapSurface: {
    2734             :         // Validate that the caller does not expect initial data to be set.
    2735           0 :         if (initData) {
    2736           0 :             return NPERR_INVALID_PARAM;
    2737             :         }
    2738             : 
    2739             :         // Validate that we're not double-allocating a surface.
    2740           0 :         RefPtr<DirectBitmap> holder;
    2741           0 :         if (mDirectBitmaps.Get(surface, getter_AddRefs(holder))) {
    2742           0 :             return NPERR_INVALID_PARAM;
    2743             :         }
    2744             : 
    2745           0 :         SurfaceFormat mozformat = NPImageFormatToSurfaceFormat(format);
    2746           0 :         int32_t bytesPerPixel = BytesPerPixel(mozformat);
    2747             : 
    2748           0 :         if (size->width <= 0 || size->height <= 0) {
    2749           0 :             return NPERR_INVALID_PARAM;
    2750             :         }
    2751             : 
    2752           0 :         CheckedInt<uint32_t> nbytes = SafeBytesForBitmap(size->width, size->height, bytesPerPixel);
    2753           0 :         if (!nbytes.isValid()) {
    2754           0 :             return NPERR_INVALID_PARAM;
    2755             :         }
    2756             : 
    2757           0 :         Shmem shmem;
    2758           0 :         if (!AllocUnsafeShmem(nbytes.value(), SharedMemory::TYPE_BASIC, &shmem)) {
    2759           0 :             return NPERR_OUT_OF_MEMORY_ERROR;
    2760             :         }
    2761           0 :         MOZ_ASSERT(shmem.Size<uint8_t>() == nbytes.value());
    2762             : 
    2763           0 :         surface->version = 0;
    2764           0 :         surface->size = *size;
    2765           0 :         surface->format = format;
    2766           0 :         surface->bitmap.data = shmem.get<unsigned char>();
    2767           0 :         surface->bitmap.stride = size->width * bytesPerPixel;
    2768             : 
    2769             :         // Hold the shmem alive until Finalize() is called or this actor dies.
    2770             :         holder = new DirectBitmap(this, shmem,
    2771           0 :                                   IntSize(size->width, size->height),
    2772           0 :                                   surface->bitmap.stride, mozformat);
    2773           0 :         mDirectBitmaps.Put(surface, holder);
    2774           0 :         return NPERR_NO_ERROR;
    2775             :     }
    2776             : #if defined(XP_WIN)
    2777             :     case NPDrawingModelAsyncWindowsDXGISurface: {
    2778             :         // Validate that the caller does not expect initial data to be set.
    2779             :         if (initData) {
    2780             :             return NPERR_INVALID_PARAM;
    2781             :         }
    2782             : 
    2783             :         // Validate that we're not double-allocating a surface.
    2784             :         WindowsHandle handle = 0;
    2785             :         if (mDxgiSurfaces.Get(surface, &handle)) {
    2786             :             return NPERR_INVALID_PARAM;
    2787             :         }
    2788             : 
    2789             :         NPError error = NPERR_NO_ERROR;
    2790             :         SurfaceFormat mozformat = NPImageFormatToSurfaceFormat(format);
    2791             :         if (!SendInitDXGISurface(mozformat,
    2792             :                                   IntSize(size->width, size->height),
    2793             :                                   &handle,
    2794             :                                   &error))
    2795             :         {
    2796             :             return NPERR_GENERIC_ERROR;
    2797             :         }
    2798             :         if (error != NPERR_NO_ERROR) {
    2799             :             return error;
    2800             :         }
    2801             : 
    2802             :         surface->version = 0;
    2803             :         surface->size = *size;
    2804             :         surface->format = format;
    2805             :         surface->sharedHandle = reinterpret_cast<HANDLE>(handle);
    2806             : 
    2807             :         mDxgiSurfaces.Put(surface, handle);
    2808             :         return NPERR_NO_ERROR;
    2809             :     }
    2810             : #endif
    2811             :     default:
    2812           0 :         MOZ_ASSERT_UNREACHABLE("unknown drawing model");
    2813             :     }
    2814             : 
    2815             :     return NPERR_INVALID_PARAM;
    2816             : }
    2817             : 
    2818             : NPError
    2819           0 : PluginInstanceChild::NPN_FinalizeAsyncSurface(NPAsyncSurface *surface)
    2820             : {
    2821           0 :     AssertPluginThread();
    2822             : 
    2823           0 :     if (!IsUsingDirectDrawing()) {
    2824           0 :         return NPERR_GENERIC_ERROR;
    2825             :     }
    2826             : 
    2827           0 :     switch (mDrawingModel) {
    2828             :     case NPDrawingModelAsyncBitmapSurface: {
    2829           0 :         RefPtr<DirectBitmap> bitmap;
    2830           0 :         if (!mDirectBitmaps.Get(surface, getter_AddRefs(bitmap))) {
    2831           0 :             return NPERR_INVALID_PARAM;
    2832             :         }
    2833             : 
    2834           0 :         PodZero(surface);
    2835           0 :         mDirectBitmaps.Remove(surface);
    2836           0 :         return NPERR_NO_ERROR;
    2837             :     }
    2838             : #if defined(XP_WIN)
    2839             :     case NPDrawingModelAsyncWindowsDXGISurface: {
    2840             :         WindowsHandle handle;
    2841             :         if (!mDxgiSurfaces.Get(surface, &handle)) {
    2842             :             return NPERR_INVALID_PARAM;
    2843             :         }
    2844             : 
    2845             :         SendFinalizeDXGISurface(handle);
    2846             :         mDxgiSurfaces.Remove(surface);
    2847             :         return NPERR_NO_ERROR;
    2848             :     }
    2849             : #endif
    2850             :     default:
    2851           0 :         MOZ_ASSERT_UNREACHABLE("unknown drawing model");
    2852             :     }
    2853             : 
    2854             :     return NPERR_INVALID_PARAM;
    2855             : }
    2856             : 
    2857             : void
    2858           0 : PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
    2859             : {
    2860           0 :     AssertPluginThread();
    2861             : 
    2862           0 :     if (!IsUsingDirectDrawing()) {
    2863           0 :         return;
    2864             :     }
    2865             : 
    2866           0 :     mCurrentDirectSurface = surface;
    2867             : 
    2868           0 :     if (!surface) {
    2869           0 :         SendRevokeCurrentDirectSurface();
    2870           0 :         return;
    2871             :     }
    2872             : 
    2873           0 :     switch (mDrawingModel) {
    2874             :     case NPDrawingModelAsyncBitmapSurface: {
    2875           0 :         RefPtr<DirectBitmap> bitmap;
    2876           0 :         if (!mDirectBitmaps.Get(surface, getter_AddRefs(bitmap))) {
    2877           0 :             return;
    2878             :         }
    2879             : 
    2880             :         IntRect dirty = changed
    2881             :                         ? NPRectToIntRect(*changed)
    2882           0 :                         : IntRect(IntPoint(0, 0), bitmap->mSize);
    2883             : 
    2884             :         // Need a holder since IPDL zaps the object for mysterious reasons.
    2885           0 :         Shmem shmemHolder = bitmap->mShmem;
    2886           0 :         SendShowDirectBitmap(shmemHolder, bitmap->mFormat, bitmap->mStride, bitmap->mSize, dirty);
    2887           0 :         break;
    2888             :     }
    2889             : #if defined(XP_WIN)
    2890             :     case NPDrawingModelAsyncWindowsDXGISurface: {
    2891             :         WindowsHandle handle;
    2892             :         if (!mDxgiSurfaces.Get(surface, &handle)) {
    2893             :             return;
    2894             :         }
    2895             : 
    2896             :         IntRect dirty = changed
    2897             :                         ? NPRectToIntRect(*changed)
    2898             :                         : IntRect(IntPoint(0, 0), IntSize(surface->size.width, surface->size.height));
    2899             : 
    2900             :         SendShowDirectDXGISurface(handle, dirty);
    2901             :         break;
    2902             :     }
    2903             : #endif
    2904             :     default:
    2905           0 :         MOZ_ASSERT_UNREACHABLE("unknown drawing model");
    2906             :     }
    2907             : }
    2908             : 
    2909             : void
    2910           0 : PluginInstanceChild::DoAsyncRedraw()
    2911             : {
    2912             :     {
    2913           0 :         MutexAutoLock autoLock(mAsyncInvalidateMutex);
    2914           0 :         mAsyncInvalidateTask = nullptr;
    2915             :     }
    2916             : 
    2917           0 :     SendRedrawPlugin();
    2918           0 : }
    2919             : 
    2920             : mozilla::ipc::IPCResult
    2921           0 : PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
    2922             :                                         const NPRemoteWindow& aWindow)
    2923             : {
    2924           0 :     AssertPluginThread();
    2925             : 
    2926           0 :     AutoStackHelper guard(this);
    2927           0 :     NS_ASSERTION(!aWindow.window, "Remote window should be null.");
    2928             : 
    2929           0 :     if (mCurrentAsyncSetWindowTask) {
    2930           0 :         mCurrentAsyncSetWindowTask->Cancel();
    2931           0 :         mCurrentAsyncSetWindowTask = nullptr;
    2932             :     }
    2933             : 
    2934             :     // We shouldn't process this now because it may be received within a nested
    2935             :     // RPC call, and both Flash and Java don't expect to receive setwindow calls
    2936             :     // at arbitrary times.
    2937             :     mCurrentAsyncSetWindowTask =
    2938             :       NewNonOwningCancelableRunnableMethod<gfxSurfaceType,
    2939             :                                            NPRemoteWindow,
    2940           0 :                                            bool>(
    2941             :         "plugins::PluginInstanceChild::DoAsyncSetWindow",
    2942             :         this,
    2943             :         &PluginInstanceChild::DoAsyncSetWindow,
    2944             :         aSurfaceType,
    2945             :         aWindow,
    2946           0 :         true);
    2947           0 :     RefPtr<Runnable> addrefedTask = mCurrentAsyncSetWindowTask;
    2948           0 :     MessageLoop::current()->PostTask(addrefedTask.forget());
    2949             : 
    2950           0 :     return IPC_OK();
    2951             : }
    2952             : 
    2953             : void
    2954           0 : PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
    2955             :                                       const NPRemoteWindow& aWindow,
    2956             :                                       bool aIsAsync)
    2957             : {
    2958           0 :     PLUGIN_LOG_DEBUG(
    2959             :         ("[InstanceChild][%p] AsyncSetWindow to <x=%d,y=%d, w=%d,h=%d>",
    2960             :          this, aWindow.x, aWindow.y, aWindow.width, aWindow.height));
    2961             : 
    2962           0 :     AssertPluginThread();
    2963           0 :     NS_ASSERTION(!aWindow.window, "Remote window should be null.");
    2964           0 :     NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!");
    2965             : 
    2966           0 :     if (aIsAsync) {
    2967           0 :         if (!mCurrentAsyncSetWindowTask) {
    2968           0 :             return;
    2969             :         }
    2970           0 :         mCurrentAsyncSetWindowTask = nullptr;
    2971             :     }
    2972             : 
    2973           0 :     mWindow.window = nullptr;
    2974           0 :     if (mWindow.width != aWindow.width || mWindow.height != aWindow.height ||
    2975           0 :         mWindow.clipRect.top != aWindow.clipRect.top ||
    2976           0 :         mWindow.clipRect.left != aWindow.clipRect.left ||
    2977           0 :         mWindow.clipRect.bottom != aWindow.clipRect.bottom ||
    2978           0 :         mWindow.clipRect.right != aWindow.clipRect.right)
    2979           0 :         mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
    2980             : 
    2981           0 :     mWindow.x = aWindow.x;
    2982           0 :     mWindow.y = aWindow.y;
    2983           0 :     mWindow.width = aWindow.width;
    2984           0 :     mWindow.height = aWindow.height;
    2985           0 :     mWindow.clipRect = aWindow.clipRect;
    2986           0 :     mWindow.type = aWindow.type;
    2987             : #if defined(XP_MACOSX) || defined(XP_WIN)
    2988             :     mContentsScaleFactor = aWindow.contentsScaleFactor;
    2989             : #endif
    2990             : 
    2991           0 :     mLayersRendering = true;
    2992           0 :     mSurfaceType = aSurfaceType;
    2993           0 :     UpdateWindowAttributes(true);
    2994             : 
    2995             : #ifdef XP_WIN
    2996             :     if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
    2997             :         SetupFlashMsgThrottle();
    2998             : #endif
    2999             : 
    3000           0 :     if (!mAccumulatedInvalidRect.IsEmpty()) {
    3001           0 :         AsyncShowPluginFrame();
    3002             :     }
    3003             : }
    3004             : 
    3005             : bool
    3006           0 : PluginInstanceChild::CreateOptSurface(void)
    3007             : {
    3008           0 :     MOZ_ASSERT(mSurfaceType != gfxSurfaceType::Max,
    3009             :                "Need a valid surface type here");
    3010           0 :     NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
    3011             : 
    3012             :     // Use an opaque surface unless we're transparent and *don't* have
    3013             :     // a background to source from.
    3014             :     gfxImageFormat format =
    3015           0 :         (mIsTransparent && !mBackground) ? SurfaceFormat::A8R8G8B8_UINT32 :
    3016           0 :                                            SurfaceFormat::X8R8G8B8_UINT32;
    3017             : 
    3018             : #ifdef MOZ_X11
    3019           0 :     Display* dpy = mWsInfo.display;
    3020           0 :     Screen* screen = DefaultScreenOfDisplay(dpy);
    3021           0 :     if (format == SurfaceFormat::X8R8G8B8_UINT32 &&
    3022           0 :         DefaultDepth(dpy, DefaultScreen(dpy)) == 16) {
    3023           0 :         format = SurfaceFormat::R5G6B5_UINT16;
    3024             :     }
    3025             : 
    3026           0 :     if (mSurfaceType == gfxSurfaceType::Xlib) {
    3027           0 :         if (!mIsTransparent  || mBackground) {
    3028           0 :             Visual* defaultVisual = DefaultVisualOfScreen(screen);
    3029             :             mCurrentSurface =
    3030           0 :                 gfxXlibSurface::Create(screen, defaultVisual,
    3031           0 :                                        IntSize(mWindow.width, mWindow.height));
    3032           0 :             return mCurrentSurface != nullptr;
    3033             :         }
    3034             : 
    3035           0 :         XRenderPictFormat* xfmt = XRenderFindStandardFormat(dpy, PictStandardARGB32);
    3036           0 :         if (!xfmt) {
    3037           0 :             NS_ERROR("Need X falback surface, but FindRenderFormat failed");
    3038           0 :             return false;
    3039             :         }
    3040             :         mCurrentSurface =
    3041           0 :             gfxXlibSurface::Create(screen, xfmt,
    3042           0 :                                    IntSize(mWindow.width, mWindow.height));
    3043           0 :         return mCurrentSurface != nullptr;
    3044             :     }
    3045             : #endif
    3046             : 
    3047             : #ifdef XP_WIN
    3048             :     if (mSurfaceType == gfxSurfaceType::Win32) {
    3049             :         bool willHaveTransparentPixels = mIsTransparent && !mBackground;
    3050             : 
    3051             :         SharedDIBSurface* s = new SharedDIBSurface();
    3052             :         if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
    3053             :                        mWindow.width, mWindow.height,
    3054             :                        willHaveTransparentPixels))
    3055             :             return false;
    3056             : 
    3057             :         mCurrentSurface = s;
    3058             :         return true;
    3059             :     }
    3060             : 
    3061             :     MOZ_CRASH("Shared-memory drawing not expected on Windows.");
    3062             : #endif
    3063             : 
    3064             :     // Make common shmem implementation working for any platform
    3065             :     mCurrentSurface =
    3066           0 :         gfxSharedImageSurface::CreateUnsafe(this, IntSize(mWindow.width, mWindow.height), format);
    3067           0 :     return !!mCurrentSurface;
    3068             : }
    3069             : 
    3070             : bool
    3071           0 : PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
    3072             : {
    3073           0 :     if (!mCurrentSurface) {
    3074           0 :         NS_ERROR("Cannot create helper surface without mCurrentSurface");
    3075           0 :         return false;
    3076             :     }
    3077             : 
    3078             : #ifdef MOZ_X11
    3079           0 :     bool supportNonDefaultVisual = false;
    3080           0 :     Screen* screen = DefaultScreenOfDisplay(mWsInfo.display);
    3081           0 :     Visual* defaultVisual = DefaultVisualOfScreen(screen);
    3082           0 :     Visual* visual = nullptr;
    3083           0 :     Colormap colormap = 0;
    3084           0 :     mDoAlphaExtraction = false;
    3085           0 :     bool createHelperSurface = false;
    3086             : 
    3087           0 :     if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) {
    3088           0 :         static_cast<gfxXlibSurface*>(mCurrentSurface.get())->
    3089           0 :             GetColormapAndVisual(&colormap, &visual);
    3090             :         // Create helper surface if layer surface visual not same as default
    3091             :         // and we don't support non-default visual rendering
    3092           0 :         if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) {
    3093           0 :             createHelperSurface = true;
    3094           0 :             visual = defaultVisual;
    3095           0 :             mDoAlphaExtraction = mIsTransparent;
    3096             :         }
    3097           0 :     } else if (mCurrentSurface->GetType() == gfxSurfaceType::Image) {
    3098             :         // For image layer surface we should always create helper surface
    3099           0 :         createHelperSurface = true;
    3100             :         // Check if we can create helper surface with non-default visual
    3101           0 :         visual = gfxXlibSurface::FindVisual(screen,
    3102           0 :             static_cast<gfxImageSurface*>(mCurrentSurface.get())->Format());
    3103           0 :         if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) {
    3104           0 :             visual = defaultVisual;
    3105           0 :             mDoAlphaExtraction = mIsTransparent;
    3106             :         }
    3107             :     }
    3108             : 
    3109           0 :     if (createHelperSurface) {
    3110           0 :         if (!visual) {
    3111           0 :             NS_ERROR("Need X falback surface, but visual failed");
    3112           0 :             return false;
    3113             :         }
    3114             :         mHelperSurface =
    3115           0 :             gfxXlibSurface::Create(screen, visual,
    3116           0 :                                    mCurrentSurface->GetSize());
    3117           0 :         if (!mHelperSurface) {
    3118           0 :             NS_WARNING("Fail to create create helper surface");
    3119           0 :             return false;
    3120             :         }
    3121             :     }
    3122             : #elif defined(XP_WIN)
    3123             :     mDoAlphaExtraction = mIsTransparent && !mBackground;
    3124             : #endif
    3125             : 
    3126           0 :     return true;
    3127             : }
    3128             : 
    3129             : bool
    3130           0 : PluginInstanceChild::EnsureCurrentBuffer(void)
    3131             : {
    3132             : #ifndef XP_DARWIN
    3133           0 :     nsIntRect toInvalidate(0, 0, 0, 0);
    3134           0 :     IntSize winSize = IntSize(mWindow.width, mWindow.height);
    3135             : 
    3136           0 :     if (mBackground && mBackground->GetSize() != winSize) {
    3137             :         // It would be nice to keep the old background here, but doing
    3138             :         // so can lead to cases in which we permanently keep the old
    3139             :         // background size.
    3140           0 :         mBackground = nullptr;
    3141             :         toInvalidate.UnionRect(toInvalidate,
    3142           0 :                                nsIntRect(0, 0, winSize.width, winSize.height));
    3143             :     }
    3144             : 
    3145           0 :     if (mCurrentSurface) {
    3146           0 :         IntSize surfSize = mCurrentSurface->GetSize();
    3147           0 :         if (winSize != surfSize ||
    3148           0 :             (mBackground && !CanPaintOnBackground()) ||
    3149           0 :             (mBackground &&
    3150           0 :              gfxContentType::COLOR != mCurrentSurface->GetContentType()) ||
    3151           0 :             (!mBackground && mIsTransparent &&
    3152           0 :              gfxContentType::COLOR == mCurrentSurface->GetContentType())) {
    3153             :             // Don't try to use an old, invalid DC.
    3154           0 :             mWindow.window = nullptr;
    3155           0 :             ClearCurrentSurface();
    3156             :             toInvalidate.UnionRect(toInvalidate,
    3157           0 :                                    nsIntRect(0, 0, winSize.width, winSize.height));
    3158             :         }
    3159             :     }
    3160             : 
    3161           0 :     mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
    3162             : 
    3163           0 :     if (mCurrentSurface) {
    3164           0 :         return true;
    3165             :     }
    3166             : 
    3167           0 :     if (!CreateOptSurface()) {
    3168           0 :         NS_ERROR("Cannot create optimized surface");
    3169           0 :         return false;
    3170             :     }
    3171             : 
    3172           0 :     if (!MaybeCreatePlatformHelperSurface()) {
    3173           0 :         NS_ERROR("Cannot create helper surface");
    3174           0 :         return false;
    3175             :     }
    3176             : 
    3177           0 :     return true;
    3178             : #elif defined(XP_MACOSX)
    3179             : 
    3180             :     if (!mDoubleBufferCARenderer.HasCALayer()) {
    3181             :         void *caLayer = nullptr;
    3182             :         if (mDrawingModel == NPDrawingModelCoreGraphics) {
    3183             :             if (!mCGLayer) {
    3184             :                 caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw,
    3185             :                                                                        this,
    3186             :                                                                        mContentsScaleFactor);
    3187             : 
    3188             :                 if (!caLayer) {
    3189             :                     PLUGIN_LOG_DEBUG(("GetCGLayer failed."));
    3190             :                     return false;
    3191             :                 }
    3192             :             }
    3193             :             mCGLayer = caLayer;
    3194             :         } else {
    3195             :             NPError result = mPluginIface->getvalue(GetNPP(),
    3196             :                                      NPPVpluginCoreAnimationLayer,
    3197             :                                      &caLayer);
    3198             :             if (result != NPERR_NO_ERROR || !caLayer) {
    3199             :                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
    3200             :                                   "provide CALayer."));
    3201             :                 return false;
    3202             :             }
    3203             :         }
    3204             :         mDoubleBufferCARenderer.SetCALayer(caLayer);
    3205             :     }
    3206             : 
    3207             :     if (mDoubleBufferCARenderer.HasFrontSurface() &&
    3208             :         (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != mWindow.width ||
    3209             :          mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height ||
    3210             :          mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) {
    3211             :         mDoubleBufferCARenderer.ClearFrontSurface();
    3212             :     }
    3213             : 
    3214             :     if (!mDoubleBufferCARenderer.HasFrontSurface()) {
    3215             :         bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface(
    3216             :                                 mWindow.width, mWindow.height, mContentsScaleFactor,
    3217             :                                 GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
    3218             :                                 ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
    3219             :         if (!allocSurface) {
    3220             :             PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface"));
    3221             :             return false;
    3222             :         }
    3223             : 
    3224             :         if (mPluginIface->setwindow)
    3225             :             (void) mPluginIface->setwindow(&mData, &mWindow);
    3226             : 
    3227             :         nsIntRect toInvalidate(0, 0, mWindow.width, mWindow.height);
    3228             :         mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
    3229             :     }
    3230             : #endif
    3231             :     return true;
    3232             : }
    3233             : 
    3234             : void
    3235           0 : PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
    3236             : {
    3237             : #if defined(MOZ_X11) || defined(XP_WIN)
    3238           0 :     RefPtr<gfxASurface> curSurface = mHelperSurface ? mHelperSurface : mCurrentSurface;
    3239             : #endif // Only used within MOZ_X11 or XP_WIN blocks. Unused variable otherwise
    3240           0 :     bool needWindowUpdate = aForceSetWindow;
    3241             : #ifdef MOZ_X11
    3242           0 :     Visual* visual = nullptr;
    3243           0 :     Colormap colormap = 0;
    3244           0 :     if (curSurface && curSurface->GetType() == gfxSurfaceType::Xlib) {
    3245           0 :         static_cast<gfxXlibSurface*>(curSurface.get())->
    3246           0 :             GetColormapAndVisual(&colormap, &visual);
    3247           0 :         if (visual != mWsInfo.visual || colormap != mWsInfo.colormap) {
    3248           0 :             mWsInfo.visual = visual;
    3249           0 :             mWsInfo.colormap = colormap;
    3250           0 :             needWindowUpdate = true;
    3251             :         }
    3252             :     }
    3253             : #endif // MOZ_X11
    3254             : #ifdef XP_WIN
    3255             :     HDC dc = nullptr;
    3256             : 
    3257             :     if (curSurface) {
    3258             :         if (!SharedDIBSurface::IsSharedDIBSurface(curSurface))
    3259             :             MOZ_CRASH("Expected SharedDIBSurface!");
    3260             : 
    3261             :         SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get());
    3262             :         dc = dibsurf->GetHDC();
    3263             :     }
    3264             :     if (mWindow.window != dc) {
    3265             :         mWindow.window = dc;
    3266             :         needWindowUpdate = true;
    3267             :     }
    3268             : #endif // XP_WIN
    3269             : 
    3270           0 :     if (!needWindowUpdate) {
    3271           0 :         return;
    3272             :     }
    3273             : 
    3274             : #ifndef XP_MACOSX
    3275             :     // Adjusting the window isn't needed for OSX
    3276             : #ifndef XP_WIN
    3277             :     // On Windows, we translate the device context, in order for the window
    3278             :     // origin to be correct.
    3279           0 :     mWindow.x = mWindow.y = 0;
    3280             : #endif
    3281             : 
    3282           0 :     if (IsVisible()) {
    3283             :         // The clip rect is relative to drawable top-left.
    3284           0 :         nsIntRect clipRect;
    3285             : 
    3286             :         // Don't ask the plugin to draw outside the drawable. The clip rect
    3287             :         // is in plugin coordinates, not window coordinates.
    3288             :         // This also ensures that the unsigned clip rectangle offsets won't be -ve.
    3289           0 :         clipRect.SetRect(0, 0, mWindow.width, mWindow.height);
    3290             : 
    3291           0 :         mWindow.clipRect.left = 0;
    3292           0 :         mWindow.clipRect.top = 0;
    3293           0 :         mWindow.clipRect.right = clipRect.XMost();
    3294           0 :         mWindow.clipRect.bottom = clipRect.YMost();
    3295             :     }
    3296             : #endif // XP_MACOSX
    3297             : 
    3298             : #ifdef XP_WIN
    3299             :     // Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update
    3300             :     // their location... or at least Flash does: Silverlight uses the
    3301             :     // window.x/y passed to NPP_SetWindow
    3302             : 
    3303             :     if (mPluginIface->event) {
    3304             :         WINDOWPOS winpos = {
    3305             :             0, 0,
    3306             :             mWindow.x, mWindow.y,
    3307             :             mWindow.width, mWindow.height,
    3308             :             0
    3309             :         };
    3310             :         NPEvent pluginEvent = {
    3311             :             WM_WINDOWPOSCHANGED, 0,
    3312             :             (LPARAM) &winpos
    3313             :         };
    3314             :         mPluginIface->event(&mData, &pluginEvent);
    3315             :     }
    3316             : #endif
    3317             : 
    3318           0 :     PLUGIN_LOG_DEBUG(
    3319             :         ("[InstanceChild][%p] UpdateWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
    3320             :          this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
    3321             :          mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
    3322             : 
    3323           0 :     if (mPluginIface->setwindow) {
    3324           0 :         mPluginIface->setwindow(&mData, &mWindow);
    3325             :     }
    3326             : }
    3327             : 
    3328             : void
    3329           0 : PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
    3330             :                                                 gfxASurface* aSurface)
    3331             : {
    3332           0 :     UpdateWindowAttributes();
    3333             : 
    3334             :     // We should not send an async surface if we're using direct rendering.
    3335           0 :     MOZ_ASSERT(!IsUsingDirectDrawing());
    3336             : 
    3337             : #ifdef MOZ_X11
    3338             :     {
    3339           0 :         NS_ASSERTION(aSurface->GetType() == gfxSurfaceType::Xlib,
    3340             :                      "Non supported platform surface type");
    3341             : 
    3342             :         NPEvent pluginEvent;
    3343           0 :         XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
    3344           0 :         exposeEvent.type = GraphicsExpose;
    3345           0 :         exposeEvent.display = mWsInfo.display;
    3346           0 :         exposeEvent.drawable = static_cast<gfxXlibSurface*>(aSurface)->XDrawable();
    3347           0 :         exposeEvent.x = aRect.x;
    3348           0 :         exposeEvent.y = aRect.y;
    3349           0 :         exposeEvent.width = aRect.width;
    3350           0 :         exposeEvent.height = aRect.height;
    3351           0 :         exposeEvent.count = 0;
    3352             :         // information not set:
    3353           0 :         exposeEvent.serial = 0;
    3354           0 :         exposeEvent.send_event = False;
    3355           0 :         exposeEvent.major_code = 0;
    3356           0 :         exposeEvent.minor_code = 0;
    3357           0 :         mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
    3358             :     }
    3359             : #elif defined(XP_WIN)
    3360             :     NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface),
    3361             :                  "Expected (SharedDIB) image surface.");
    3362             : 
    3363             :     // This rect is in the window coordinate space. aRect is in the plugin
    3364             :     // coordinate space.
    3365             :     RECT rect = {
    3366             :         mWindow.x + aRect.x,
    3367             :         mWindow.y + aRect.y,
    3368             :         mWindow.x + aRect.XMost(),
    3369             :         mWindow.y + aRect.YMost()
    3370             :     };
    3371             :     NPEvent paintEvent = {
    3372             :         WM_PAINT,
    3373             :         uintptr_t(mWindow.window),
    3374             :         uintptr_t(&rect)
    3375             :     };
    3376             : 
    3377             :     ::SetViewportOrgEx((HDC) mWindow.window, -mWindow.x, -mWindow.y, nullptr);
    3378             :     ::SelectClipRgn((HDC) mWindow.window, nullptr);
    3379             :     ::IntersectClipRect((HDC) mWindow.window, rect.left, rect.top, rect.right, rect.bottom);
    3380             :     mPluginIface->event(&mData, reinterpret_cast<void*>(&paintEvent));
    3381             : #else
    3382             :     MOZ_CRASH("Surface type not implemented.");
    3383             : #endif
    3384           0 : }
    3385             : 
    3386             : void
    3387           0 : PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
    3388             :                                         gfxASurface* aSurface,
    3389             :                                         const Color& aColor)
    3390             : {
    3391             :     // Render using temporary X surface, with copy to image surface
    3392           0 :     nsIntRect plPaintRect(aRect);
    3393           0 :     RefPtr<gfxASurface> renderSurface = aSurface;
    3394             : #ifdef MOZ_X11
    3395           0 :     if (mIsTransparent && (GetQuirks() & QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) {
    3396             :         // Work around a bug in Flash up to 10.1 d51 at least, where expose event
    3397             :         // top left coordinates within the plugin-rect and not at the drawable
    3398             :         // origin are misinterpreted.  (We can move the top left coordinate
    3399             :         // provided it is within the clipRect.), see bug 574583
    3400           0 :         plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost());
    3401             :     }
    3402           0 :     if (mHelperSurface) {
    3403             :         // On X11 we can paint to non Xlib surface only with HelperSurface
    3404           0 :         renderSurface = mHelperSurface;
    3405             :     }
    3406             : #endif
    3407             : 
    3408           0 :     if (mIsTransparent && !CanPaintOnBackground()) {
    3409           0 :         RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(renderSurface);
    3410           0 :         gfx::Rect rect(plPaintRect.x, plPaintRect.y,
    3411           0 :                        plPaintRect.width, plPaintRect.height);
    3412             :         // Moz2D treats OP_SOURCE operations as unbounded, so we need to
    3413             :         // clip to the rect that we want to fill:
    3414           0 :         dt->PushClipRect(rect);
    3415           0 :         dt->FillRect(rect, ColorPattern(aColor), // aColor is already a device color
    3416           0 :                      DrawOptions(1.f, CompositionOp::OP_SOURCE));
    3417           0 :         dt->PopClip();
    3418           0 :         dt->Flush();
    3419             :     }
    3420             : 
    3421           0 :     PaintRectToPlatformSurface(plPaintRect, renderSurface);
    3422             : 
    3423           0 :     if (renderSurface != aSurface) {
    3424           0 :       RefPtr<DrawTarget> dt;
    3425           0 :       if (aSurface == mCurrentSurface &&
    3426           0 :           aSurface->GetType() == gfxSurfaceType::Image &&
    3427           0 :           aSurface->GetSurfaceFormat() == SurfaceFormat::B8G8R8X8) {
    3428           0 :         gfxImageSurface* imageSurface = static_cast<gfxImageSurface*>(aSurface);
    3429             :         // Bug 1196927 - Reinterpret target surface as BGRA to fill alpha with opaque.
    3430             :         // Certain backends (i.e. Skia) may not truly support BGRX formats, so they must
    3431             :         // be emulated by filling the alpha channel opaque as if it was BGRA data. Cairo
    3432             :         // leaves the alpha zeroed out for BGRX, so we cause Cairo to fill it as opaque
    3433             :         // by handling the copy target as a BGRA surface.
    3434           0 :         dt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
    3435             :                                               imageSurface->Data(),
    3436           0 :                                               imageSurface->GetSize(),
    3437             :                                               imageSurface->Stride(),
    3438           0 :                                               SurfaceFormat::B8G8R8A8);
    3439             :       } else {
    3440             :         // Copy helper surface content to target
    3441           0 :         dt = CreateDrawTargetForSurface(aSurface);
    3442             :       }
    3443           0 :       if (dt && dt->IsValid()) {
    3444             :           RefPtr<SourceSurface> surface =
    3445           0 :               gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
    3446           0 :           dt->CopySurface(surface, aRect, aRect.TopLeft());
    3447             :       } else {
    3448           0 :           gfxWarning() << "PluginInstanceChild::PaintRectToSurface failure";
    3449             :       }
    3450             :     }
    3451           0 : }
    3452             : 
    3453             : void
    3454           0 : PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
    3455             :                                                   gfxASurface* aSurface)
    3456             : {
    3457           0 :     MOZ_ASSERT(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
    3458             :                "Refusing to pointlessly recover alpha");
    3459             : 
    3460           0 :     nsIntRect rect(aRect);
    3461             :     // If |aSurface| can be used to paint and can have alpha values
    3462             :     // recovered directly to it, do that to save a tmp surface and
    3463             :     // copy.
    3464           0 :     bool useSurfaceSubimageForBlack = false;
    3465           0 :     if (gfxSurfaceType::Image == aSurface->GetType()) {
    3466             :         gfxImageSurface* surfaceAsImage =
    3467           0 :             static_cast<gfxImageSurface*>(aSurface);
    3468           0 :         useSurfaceSubimageForBlack =
    3469           0 :             (surfaceAsImage->Format() == SurfaceFormat::A8R8G8B8_UINT32);
    3470             :         // If we're going to use a subimage, nudge the rect so that we
    3471             :         // can use optimal alpha recovery.  If we're not using a
    3472             :         // subimage, the temporaries should automatically get
    3473             :         // fast-path alpha recovery so we don't need to do anything.
    3474           0 :         if (useSurfaceSubimageForBlack) {
    3475             :             rect =
    3476             :                 gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect,
    3477           0 :                                                                surfaceAsImage);
    3478             :         }
    3479             :     }
    3480             : 
    3481           0 :     RefPtr<gfxImageSurface> whiteImage;
    3482           0 :     RefPtr<gfxImageSurface> blackImage;
    3483           0 :     gfxRect targetRect(rect.x, rect.y, rect.width, rect.height);
    3484           0 :     IntSize targetSize(rect.width, rect.height);
    3485           0 :     gfxPoint deviceOffset = -targetRect.TopLeft();
    3486             : 
    3487             :     // We always use a temporary "white image"
    3488           0 :     whiteImage = new gfxImageSurface(targetSize, SurfaceFormat::X8R8G8B8_UINT32);
    3489           0 :     if (whiteImage->CairoStatus()) {
    3490           0 :         return;
    3491             :     }
    3492             : 
    3493             : #ifdef XP_WIN
    3494             :     // On windows, we need an HDC and so can't paint directly to
    3495             :     // vanilla image surfaces.  Bifurcate this painting code so that
    3496             :     // we don't accidentally attempt that.
    3497             :     if (!SharedDIBSurface::IsSharedDIBSurface(aSurface))
    3498             :         MOZ_CRASH("Expected SharedDIBSurface!");
    3499             : 
    3500             :     // Paint the plugin directly onto the target, with a white
    3501             :     // background and copy the result
    3502             :     PaintRectToSurface(rect, aSurface, Color(1.f, 1.f, 1.f));
    3503             :     {
    3504             :         RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(whiteImage);
    3505             :         RefPtr<SourceSurface> surface =
    3506             :             gfxPlatform::GetSourceSurfaceForSurface(dt, aSurface);
    3507             :         dt->CopySurface(surface, rect, IntPoint());
    3508             :     }
    3509             : 
    3510             :     // Paint the plugin directly onto the target, with a black
    3511             :     // background
    3512             :     PaintRectToSurface(rect, aSurface, Color(0.f, 0.f, 0.f));
    3513             : 
    3514             :     // Don't copy the result, just extract a subimage so that we can
    3515             :     // recover alpha directly into the target
    3516             :     gfxImageSurface *image = static_cast<gfxImageSurface*>(aSurface);
    3517             :     blackImage = image->GetSubimage(targetRect);
    3518             : 
    3519             : #else
    3520             :     // Paint onto white background
    3521           0 :     whiteImage->SetDeviceOffset(deviceOffset);
    3522           0 :     PaintRectToSurface(rect, whiteImage, Color(1.f, 1.f, 1.f));
    3523             : 
    3524           0 :     if (useSurfaceSubimageForBlack) {
    3525           0 :         gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
    3526           0 :         blackImage = surface->GetSubimage(targetRect);
    3527             :     } else {
    3528             :         blackImage = new gfxImageSurface(targetSize,
    3529           0 :                                          SurfaceFormat::A8R8G8B8_UINT32);
    3530             :     }
    3531             : 
    3532             :     // Paint onto black background
    3533           0 :     blackImage->SetDeviceOffset(deviceOffset);
    3534           0 :     PaintRectToSurface(rect, blackImage, Color(0.f, 0.f, 0.f));
    3535             : #endif
    3536             : 
    3537           0 :     MOZ_ASSERT(whiteImage && blackImage, "Didn't paint enough!");
    3538             : 
    3539             :     // Extract alpha from black and white image and store to black
    3540             :     // image
    3541           0 :     if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
    3542           0 :         return;
    3543             :     }
    3544             : 
    3545             :     // If we had to use a temporary black surface, copy the pixels
    3546             :     // with alpha back to the target
    3547           0 :     if (!useSurfaceSubimageForBlack) {
    3548           0 :         RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(aSurface);
    3549             :         RefPtr<SourceSurface> surface =
    3550           0 :             gfxPlatform::GetSourceSurfaceForSurface(dt, blackImage);
    3551           0 :         dt->CopySurface(surface,
    3552           0 :                         IntRect(0, 0, rect.width, rect.height),
    3553           0 :                         rect.TopLeft());
    3554             :     }
    3555             : }
    3556             : 
    3557             : bool
    3558           0 : PluginInstanceChild::CanPaintOnBackground()
    3559             : {
    3560           0 :     return (mBackground &&
    3561           0 :             mCurrentSurface &&
    3562           0 :             mCurrentSurface->GetSize() == mBackground->GetSize());
    3563             : }
    3564             : 
    3565             : bool
    3566           0 : PluginInstanceChild::ShowPluginFrame()
    3567             : {
    3568             :     // mLayersRendering can be false if we somehow get here without
    3569             :     // receiving AsyncSetWindow() first.  mPendingPluginCall is our
    3570             :     // re-entrancy guard; we can't paint while nested inside another
    3571             :     // paint.
    3572           0 :     if (!mLayersRendering || mPendingPluginCall) {
    3573           0 :         return false;
    3574             :     }
    3575             : 
    3576             :     // We should not attempt to asynchronously show the plugin if we're using
    3577             :     // direct rendering.
    3578           0 :     MOZ_ASSERT(!IsUsingDirectDrawing());
    3579             : 
    3580           0 :     AutoRestore<bool> pending(mPendingPluginCall);
    3581           0 :     mPendingPluginCall = true;
    3582             : 
    3583           0 :     bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
    3584           0 :     if (temporarilyMakeVisible && mWindow.width && mWindow.height) {
    3585           0 :         mWindow.clipRect.right = mWindow.width;
    3586           0 :         mWindow.clipRect.bottom = mWindow.height;
    3587           0 :     } else if (!IsVisible()) {
    3588             :         // If we're not visible, don't bother painting a <0,0,0,0>
    3589             :         // rect.  If we're eventually made visible, the visibility
    3590             :         // change will invalidate our window.
    3591           0 :         ClearCurrentSurface();
    3592           0 :         return true;
    3593             :     }
    3594             : 
    3595           0 :     if (!EnsureCurrentBuffer()) {
    3596           0 :         return false;
    3597             :     }
    3598             : 
    3599             : #ifdef MOZ_WIDGET_COCOA
    3600             :     // We can't use the thebes code with CoreAnimation so we will
    3601             :     // take a different code path.
    3602             :     if (mDrawingModel == NPDrawingModelCoreAnimation ||
    3603             :         mDrawingModel == NPDrawingModelInvalidatingCoreAnimation ||
    3604             :         mDrawingModel == NPDrawingModelCoreGraphics) {
    3605             : 
    3606             :         if (!IsVisible()) {
    3607             :             return true;
    3608             :         }
    3609             : 
    3610             :         if (!mDoubleBufferCARenderer.HasFrontSurface()) {
    3611             :             NS_ERROR("CARenderer not initialized for rendering");
    3612             :             return false;
    3613             :         }
    3614             : 
    3615             :         // Clear accRect here to be able to pass
    3616             :         // test_invalidate_during_plugin_paint  test
    3617             :         nsIntRect rect = mAccumulatedInvalidRect;
    3618             :         mAccumulatedInvalidRect.SetEmpty();
    3619             : 
    3620             :         // Fix up old invalidations that might have been made when our
    3621             :         // surface was a different size
    3622             :         rect.IntersectRect(rect,
    3623             :                           nsIntRect(0, 0,
    3624             :                           mDoubleBufferCARenderer.GetFrontSurfaceWidth(),
    3625             :                           mDoubleBufferCARenderer.GetFrontSurfaceHeight()));
    3626             : 
    3627             :         if (mDrawingModel == NPDrawingModelCoreGraphics) {
    3628             :             mozilla::plugins::PluginUtilsOSX::Repaint(mCGLayer, rect);
    3629             :         }
    3630             : 
    3631             :         mDoubleBufferCARenderer.Render();
    3632             : 
    3633             :         NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
    3634             :                      (uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
    3635             :         SurfaceDescriptor currSurf;
    3636             :         currSurf = IOSurfaceDescriptor(mDoubleBufferCARenderer.GetFrontSurfaceID(),
    3637             :                                        mDoubleBufferCARenderer.GetContentsScaleFactor());
    3638             : 
    3639             :         mHasPainted = true;
    3640             : 
    3641             :         SurfaceDescriptor returnSurf;
    3642             : 
    3643             :         if (!SendShow(r, currSurf, &returnSurf)) {
    3644             :             return false;
    3645             :         }
    3646             : 
    3647             :         SwapSurfaces();
    3648             :         return true;
    3649             :     } else {
    3650             :         NS_ERROR("Unsupported drawing model for async layer rendering");
    3651             :         return false;
    3652             :     }
    3653             : #endif
    3654             : 
    3655           0 :     NS_ASSERTION(mWindow.width == uint32_t(mWindow.clipRect.right - mWindow.clipRect.left) &&
    3656             :                  mWindow.height == uint32_t(mWindow.clipRect.bottom - mWindow.clipRect.top),
    3657             :                  "Clip rect should be same size as window when using layers");
    3658             : 
    3659             :     // Clear accRect here to be able to pass
    3660             :     // test_invalidate_during_plugin_paint  test
    3661           0 :     nsIntRect rect = mAccumulatedInvalidRect;
    3662           0 :     mAccumulatedInvalidRect.SetEmpty();
    3663             : 
    3664             :     // Fix up old invalidations that might have been made when our
    3665             :     // surface was a different size
    3666           0 :     IntSize surfaceSize = mCurrentSurface->GetSize();
    3667             :     rect.IntersectRect(rect,
    3668           0 :                        nsIntRect(0, 0, surfaceSize.width, surfaceSize.height));
    3669             : 
    3670           0 :     if (!ReadbackDifferenceRect(rect)) {
    3671             :         // We couldn't read back the pixels that differ between the
    3672             :         // current surface and last, so we have to invalidate the
    3673             :         // entire window.
    3674           0 :         rect.SetRect(0, 0, mWindow.width, mWindow.height);
    3675             :     }
    3676             : 
    3677             :     bool haveTransparentPixels =
    3678           0 :         gfxContentType::COLOR_ALPHA == mCurrentSurface->GetContentType();
    3679           0 :     PLUGIN_LOG_DEBUG(
    3680             :         ("[InstanceChild][%p] Painting%s <x=%d,y=%d, w=%d,h=%d> on surface <w=%d,h=%d>",
    3681             :          this, haveTransparentPixels ? " with alpha" : "",
    3682             :          rect.x, rect.y, rect.width, rect.height,
    3683             :          mCurrentSurface->GetSize().width, mCurrentSurface->GetSize().height));
    3684             : 
    3685           0 :     if (CanPaintOnBackground()) {
    3686           0 :         PLUGIN_LOG_DEBUG(("  (on background)"));
    3687             :         // Source the background pixels ...
    3688             :         {
    3689             :             RefPtr<gfxASurface> surface =
    3690           0 :                 mHelperSurface ? mHelperSurface : mCurrentSurface;
    3691           0 :             RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(surface);
    3692             :             RefPtr<SourceSurface> backgroundSurface =
    3693           0 :                 gfxPlatform::GetSourceSurfaceForSurface(dt, mBackground);
    3694           0 :             dt->CopySurface(backgroundSurface, rect, rect.TopLeft());
    3695             :         }
    3696             :         // ... and hand off to the plugin
    3697             :         // BEWARE: mBackground may die during this call
    3698           0 :         PaintRectToSurface(rect, mCurrentSurface, Color());
    3699           0 :     } else if (!temporarilyMakeVisible && mDoAlphaExtraction) {
    3700             :         // We don't want to pay the expense of alpha extraction for
    3701             :         // phony paints.
    3702           0 :         PLUGIN_LOG_DEBUG(("  (with alpha recovery)"));
    3703           0 :         PaintRectWithAlphaExtraction(rect, mCurrentSurface);
    3704             :     } else {
    3705           0 :         PLUGIN_LOG_DEBUG(("  (onto opaque surface)"));
    3706             : 
    3707             :         // If we're on a platform that needs helper surfaces for
    3708             :         // plugins, and we're forcing a throwaway paint of a
    3709             :         // wmode=transparent plugin, then make sure to use the helper
    3710             :         // surface here.
    3711             :         RefPtr<gfxASurface> target =
    3712           0 :             (temporarilyMakeVisible && mHelperSurface) ?
    3713           0 :             mHelperSurface : mCurrentSurface;
    3714             : 
    3715           0 :         PaintRectToSurface(rect, target, Color());
    3716             :     }
    3717           0 :     mHasPainted = true;
    3718             : 
    3719           0 :     if (temporarilyMakeVisible) {
    3720           0 :         mWindow.clipRect.right = mWindow.clipRect.bottom = 0;
    3721             : 
    3722           0 :         PLUGIN_LOG_DEBUG(
    3723             :             ("[InstanceChild][%p] Undoing temporary clipping w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
    3724             :              this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
    3725             :              mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
    3726             : 
    3727           0 :         if (mPluginIface->setwindow) {
    3728           0 :             mPluginIface->setwindow(&mData, &mWindow);
    3729             :         }
    3730             : 
    3731             :         // Skip forwarding the results of the phony paint to the
    3732             :         // browser.  We may have painted a transparent plugin using
    3733             :         // the opaque-plugin path, which can result in wrong pixels.
    3734             :         // We also don't want to pay the expense of forwarding the
    3735             :         // surface for plugins that might really be invisible.
    3736           0 :         mAccumulatedInvalidRect.SetRect(0, 0, mWindow.width, mWindow.height);
    3737           0 :         return true;
    3738             :     }
    3739             : 
    3740           0 :     NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
    3741           0 :                  (uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
    3742           0 :     SurfaceDescriptor currSurf;
    3743             : #ifdef MOZ_X11
    3744           0 :     if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) {
    3745           0 :         gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get());
    3746           0 :         currSurf = SurfaceDescriptorX11(xsurf);
    3747             :         // Need to sync all pending x-paint requests
    3748             :         // before giving drawable to another process
    3749           0 :         XSync(mWsInfo.display, False);
    3750             :     } else
    3751             : #endif
    3752             : #ifdef XP_WIN
    3753             :     if (SharedDIBSurface::IsSharedDIBSurface(mCurrentSurface)) {
    3754             :         SharedDIBSurface* s = static_cast<SharedDIBSurface*>(mCurrentSurface.get());
    3755             :         if (!mCurrentSurfaceActor) {
    3756             :             base::SharedMemoryHandle handle = nullptr;
    3757             :             s->ShareToProcess(OtherPid(), &handle);
    3758             : 
    3759             :             mCurrentSurfaceActor =
    3760             :                 SendPPluginSurfaceConstructor(handle,
    3761             :                                               mCurrentSurface->GetSize(),
    3762             :                                               haveTransparentPixels);
    3763             :         }
    3764             :         currSurf = mCurrentSurfaceActor;
    3765             :         s->Flush();
    3766             :     } else
    3767             : #endif
    3768           0 :     if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
    3769           0 :         currSurf = static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
    3770             :     } else {
    3771           0 :         MOZ_CRASH("Surface type is not remotable");
    3772             :         return false;
    3773             :     }
    3774             : 
    3775             :     // Unused, except to possibly return a shmem to us
    3776           0 :     SurfaceDescriptor returnSurf;
    3777             : 
    3778           0 :     if (!SendShow(r, currSurf, &returnSurf)) {
    3779           0 :         return false;
    3780             :     }
    3781             : 
    3782           0 :     SwapSurfaces();
    3783           0 :     mSurfaceDifferenceRect = rect;
    3784           0 :     return true;
    3785             : }
    3786             : 
    3787             : bool
    3788           0 : PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
    3789             : {
    3790           0 :     if (!mBackSurface)
    3791           0 :         return false;
    3792             : 
    3793             :     // We can read safely from XSurface,SharedDIBSurface and Unsafe SharedMemory,
    3794             :     // because PluginHost is not able to modify that surface
    3795             : #if defined(MOZ_X11)
    3796           0 :     if (mBackSurface->GetType() != gfxSurfaceType::Xlib &&
    3797           0 :         !gfxSharedImageSurface::IsSharedImage(mBackSurface))
    3798           0 :         return false;
    3799             : #elif defined(XP_WIN)
    3800             :     if (!SharedDIBSurface::IsSharedDIBSurface(mBackSurface))
    3801             :         return false;
    3802             : #endif
    3803             : 
    3804             : #if defined(MOZ_X11) || defined(XP_WIN)
    3805           0 :     if (mCurrentSurface->GetContentType() != mBackSurface->GetContentType())
    3806           0 :         return false;
    3807             : 
    3808           0 :     if (mSurfaceDifferenceRect.IsEmpty())
    3809           0 :         return true;
    3810             : 
    3811           0 :     PLUGIN_LOG_DEBUG(
    3812             :         ("[InstanceChild][%p] Reading back part of <x=%d,y=%d, w=%d,h=%d>",
    3813             :          this, mSurfaceDifferenceRect.x, mSurfaceDifferenceRect.y,
    3814             :          mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height));
    3815             : 
    3816             :     // Read back previous content
    3817           0 :     RefPtr<DrawTarget> dt = CreateDrawTargetForSurface(mCurrentSurface);
    3818             :     RefPtr<SourceSurface> source =
    3819           0 :         gfxPlatform::GetSourceSurfaceForSurface(dt, mBackSurface);
    3820             :     // Subtract from mSurfaceDifferenceRect area which is overlapping with rect
    3821           0 :     nsIntRegion result;
    3822           0 :     result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect));
    3823           0 :     for (auto iter = result.RectIter(); !iter.Done(); iter.Next()) {
    3824           0 :         const nsIntRect& r = iter.Get();
    3825           0 :         dt->CopySurface(source, r, r.TopLeft());
    3826             :     }
    3827             : 
    3828           0 :     return true;
    3829             : #else
    3830             :     return false;
    3831             : #endif
    3832             : }
    3833             : 
    3834             : void
    3835           0 : PluginInstanceChild::InvalidateRectDelayed(void)
    3836             : {
    3837           0 :     if (!mCurrentInvalidateTask) {
    3838           0 :         return;
    3839             :     }
    3840             : 
    3841           0 :     mCurrentInvalidateTask = nullptr;
    3842             : 
    3843             :     // When this method is run asynchronously, we can end up switching to
    3844             :     // direct drawing before while we wait to run.  In that case, bail.
    3845           0 :     if (IsUsingDirectDrawing()) {
    3846           0 :         return;
    3847             :     }
    3848             : 
    3849           0 :     if (mAccumulatedInvalidRect.IsEmpty()) {
    3850           0 :         return;
    3851             :     }
    3852             : 
    3853           0 :     if (!ShowPluginFrame()) {
    3854           0 :         AsyncShowPluginFrame();
    3855             :     }
    3856             : }
    3857             : 
    3858             : void
    3859           0 : PluginInstanceChild::AsyncShowPluginFrame(void)
    3860             : {
    3861           0 :     if (mCurrentInvalidateTask) {
    3862           0 :         return;
    3863             :     }
    3864             : 
    3865             :     // When the plugin is using direct surfaces to draw, it is not driving
    3866             :     // paints via paint events - it will drive painting via its own events
    3867             :     // and/or DidComposite callbacks.
    3868           0 :     if (IsUsingDirectDrawing()) {
    3869           0 :         return;
    3870             :     }
    3871             : 
    3872           0 :     mCurrentInvalidateTask = NewNonOwningCancelableRunnableMethod(
    3873             :       "plugins::PluginInstanceChild::InvalidateRectDelayed",
    3874             :       this,
    3875           0 :       &PluginInstanceChild::InvalidateRectDelayed);
    3876           0 :     RefPtr<Runnable> addrefedTask = mCurrentInvalidateTask;
    3877           0 :     MessageLoop::current()->PostTask(addrefedTask.forget());
    3878             : }
    3879             : 
    3880             : void
    3881           0 : PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
    3882             : {
    3883           0 :     NS_ASSERTION(aInvalidRect, "Null pointer!");
    3884             : 
    3885             : #ifdef OS_WIN
    3886             :     // Invalidate and draw locally for windowed plugins.
    3887             :     if (mWindow.type == NPWindowTypeWindow) {
    3888             :       NS_ASSERTION(IsWindow(mPluginWindowHWND), "Bad window?!");
    3889             :       RECT rect = { aInvalidRect->left, aInvalidRect->top,
    3890             :                     aInvalidRect->right, aInvalidRect->bottom };
    3891             :       ::InvalidateRect(mPluginWindowHWND, &rect, FALSE);
    3892             :       return;
    3893             :     }
    3894             : #endif
    3895             : 
    3896           0 :     if (IsUsingDirectDrawing()) {
    3897           0 :         NS_ASSERTION(false, "Should not call InvalidateRect() in direct surface mode!");
    3898           0 :         return;
    3899             :     }
    3900             : 
    3901           0 :     if (mLayersRendering) {
    3902           0 :         nsIntRect r(aInvalidRect->left, aInvalidRect->top,
    3903           0 :                     aInvalidRect->right - aInvalidRect->left,
    3904           0 :                     aInvalidRect->bottom - aInvalidRect->top);
    3905             : 
    3906           0 :         mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect);
    3907             :         // If we are able to paint and invalidate sent, then reset
    3908             :         // accumulated rectangle
    3909           0 :         AsyncShowPluginFrame();
    3910           0 :         return;
    3911             :     }
    3912             : 
    3913             :     // If we were going to use layers rendering but it's not set up
    3914             :     // yet, and the plugin happens to call this first, we'll forward
    3915             :     // the invalidation to the browser.  It's unclear whether
    3916             :     // non-layers plugins need this rect forwarded when their window
    3917             :     // width or height is 0, which it would be for layers plugins
    3918             :     // before their first SetWindow().
    3919           0 :     SendNPN_InvalidateRect(*aInvalidRect);
    3920             : }
    3921             : 
    3922             : mozilla::ipc::IPCResult
    3923           0 : PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground,
    3924             :                                           const nsIntRect& aRect)
    3925             : {
    3926           0 :     MOZ_ASSERT(mIsTransparent, "Only transparent plugins use backgrounds");
    3927             : 
    3928           0 :     if (!mBackground) {
    3929             :         // XXX refactor me
    3930           0 :         switch (aBackground.type()) {
    3931             : #ifdef MOZ_X11
    3932             :         case SurfaceDescriptor::TSurfaceDescriptorX11: {
    3933           0 :             mBackground = aBackground.get_SurfaceDescriptorX11().OpenForeign();
    3934           0 :             break;
    3935             :         }
    3936             : #endif
    3937             :         case SurfaceDescriptor::TShmem: {
    3938           0 :             mBackground = gfxSharedImageSurface::Open(aBackground.get_Shmem());
    3939           0 :             break;
    3940             :         }
    3941             :         default:
    3942           0 :             MOZ_CRASH("Unexpected background surface descriptor");
    3943             :         }
    3944             : 
    3945           0 :         if (!mBackground) {
    3946           0 :             return IPC_FAIL_NO_REASON(this);
    3947             :         }
    3948             : 
    3949           0 :         IntSize bgSize = mBackground->GetSize();
    3950           0 :         mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect,
    3951           0 :                                           nsIntRect(0, 0, bgSize.width, bgSize.height));
    3952           0 :         AsyncShowPluginFrame();
    3953           0 :         return IPC_OK();
    3954             :     }
    3955             : 
    3956             :     // XXX refactor me
    3957           0 :     mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect);
    3958             : 
    3959             :     // This must be asynchronous, because we may be nested within RPC messages
    3960             :     // which do not expect to receiving paint events.
    3961           0 :     AsyncShowPluginFrame();
    3962             : 
    3963           0 :     return IPC_OK();
    3964             : }
    3965             : 
    3966             : PPluginBackgroundDestroyerChild*
    3967           0 : PluginInstanceChild::AllocPPluginBackgroundDestroyerChild()
    3968             : {
    3969           0 :     return new PluginBackgroundDestroyerChild();
    3970             : }
    3971             : 
    3972             : mozilla::ipc::IPCResult
    3973           0 : PluginInstanceChild::RecvPPluginBackgroundDestroyerConstructor(
    3974             :     PPluginBackgroundDestroyerChild* aActor)
    3975             : {
    3976             :     // Our background changed, so we have to invalidate the area
    3977             :     // painted with the old background.  If the background was
    3978             :     // destroyed because we have a new background, then we expect to
    3979             :     // be notified of that "soon", before processing the asynchronous
    3980             :     // invalidation here.  If we're *not* getting a new background,
    3981             :     // our current front surface is stale and we want to repaint
    3982             :     // "soon" so that we can hand the browser back a surface with
    3983             :     // alpha values.  (We should be notified of that invalidation soon
    3984             :     // too, but we don't assume that here.)
    3985           0 :     if (mBackground) {
    3986           0 :         IntSize bgsize = mBackground->GetSize();
    3987           0 :         mAccumulatedInvalidRect.UnionRect(
    3988           0 :             nsIntRect(0, 0, bgsize.width, bgsize.height), mAccumulatedInvalidRect);
    3989             : 
    3990             :         // NB: we don't have to XSync here because only ShowPluginFrame()
    3991             :         // uses mBackground, and it always XSyncs after finishing.
    3992           0 :         mBackground = nullptr;
    3993           0 :         AsyncShowPluginFrame();
    3994             :     }
    3995             : 
    3996           0 :     if (!PPluginBackgroundDestroyerChild::Send__delete__(aActor)) {
    3997           0 :       return IPC_FAIL_NO_REASON(this);
    3998             :     }
    3999           0 :     return IPC_OK();
    4000             : }
    4001             : 
    4002             : bool
    4003           0 : PluginInstanceChild::DeallocPPluginBackgroundDestroyerChild(
    4004             :     PPluginBackgroundDestroyerChild* aActor)
    4005             : {
    4006           0 :     delete aActor;
    4007           0 :     return true;
    4008             : }
    4009             : 
    4010             : uint32_t
    4011           0 : PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat,
    4012             :                                    TimerFunc func)
    4013             : {
    4014           0 :     auto* t = new ChildTimer(this, interval, repeat, func);
    4015           0 :     if (0 == t->ID()) {
    4016           0 :         delete t;
    4017           0 :         return 0;
    4018             :     }
    4019             : 
    4020           0 :     mTimers.AppendElement(t);
    4021           0 :     return t->ID();
    4022             : }
    4023             : 
    4024             : void
    4025           0 : PluginInstanceChild::UnscheduleTimer(uint32_t id)
    4026             : {
    4027           0 :     if (0 == id)
    4028           0 :         return;
    4029             : 
    4030           0 :     mTimers.RemoveElement(id, ChildTimer::IDComparator());
    4031             : }
    4032             : 
    4033             : void
    4034           0 : PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData)
    4035             : {
    4036           0 :     RefPtr<ChildAsyncCall> task = new ChildAsyncCall(this, aFunc, aUserData);
    4037           0 :     PostChildAsyncCall(task.forget());
    4038           0 : }
    4039             : 
    4040             : void
    4041           0 : PluginInstanceChild::PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask)
    4042             : {
    4043           0 :     RefPtr<ChildAsyncCall> task = aTask;
    4044             : 
    4045             :     {
    4046           0 :         MutexAutoLock lock(mAsyncCallMutex);
    4047           0 :         mPendingAsyncCalls.AppendElement(task);
    4048             :     }
    4049           0 :     ProcessChild::message_loop()->PostTask(task.forget());
    4050           0 : }
    4051             : 
    4052             : void
    4053           0 : PluginInstanceChild::SwapSurfaces()
    4054             : {
    4055           0 :     RefPtr<gfxASurface> tmpsurf = mCurrentSurface;
    4056             : #ifdef XP_WIN
    4057             :     PPluginSurfaceChild* tmpactor = mCurrentSurfaceActor;
    4058             : #endif
    4059             : 
    4060           0 :     mCurrentSurface = mBackSurface;
    4061             : #ifdef XP_WIN
    4062             :     mCurrentSurfaceActor = mBackSurfaceActor;
    4063             : #endif
    4064             : 
    4065           0 :     mBackSurface = tmpsurf;
    4066             : #ifdef XP_WIN
    4067             :     mBackSurfaceActor = tmpactor;
    4068             : #endif
    4069             : 
    4070             : #ifdef MOZ_WIDGET_COCOA
    4071             :     mDoubleBufferCARenderer.SwapSurfaces();
    4072             : 
    4073             :     // Outdated back surface... not usable anymore due to changed plugin size.
    4074             :     // Dropping obsolete surface
    4075             :     if (mDoubleBufferCARenderer.HasFrontSurface() &&
    4076             :         mDoubleBufferCARenderer.HasBackSurface() &&
    4077             :         (mDoubleBufferCARenderer.GetFrontSurfaceWidth() !=
    4078             :             mDoubleBufferCARenderer.GetBackSurfaceWidth() ||
    4079             :         mDoubleBufferCARenderer.GetFrontSurfaceHeight() !=
    4080             :             mDoubleBufferCARenderer.GetBackSurfaceHeight() ||
    4081             :         mDoubleBufferCARenderer.GetFrontSurfaceContentsScaleFactor() !=
    4082             :             mDoubleBufferCARenderer.GetBackSurfaceContentsScaleFactor())) {
    4083             : 
    4084             :         mDoubleBufferCARenderer.ClearFrontSurface();
    4085             :     }
    4086             : #else
    4087           0 :     if (mCurrentSurface && mBackSurface &&
    4088           0 :         (mCurrentSurface->GetSize() != mBackSurface->GetSize() ||
    4089           0 :          mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) {
    4090           0 :         ClearCurrentSurface();
    4091             :     }
    4092             : #endif
    4093           0 : }
    4094             : 
    4095             : void
    4096           0 : PluginInstanceChild::ClearCurrentSurface()
    4097             : {
    4098           0 :     mCurrentSurface = nullptr;
    4099             : #ifdef MOZ_WIDGET_COCOA
    4100             :     if (mDoubleBufferCARenderer.HasFrontSurface()) {
    4101             :         mDoubleBufferCARenderer.ClearFrontSurface();
    4102             :     }
    4103             : #endif
    4104             : #ifdef XP_WIN
    4105             :     if (mCurrentSurfaceActor) {
    4106             :         PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor);
    4107             :         mCurrentSurfaceActor = nullptr;
    4108             :     }
    4109             : #endif
    4110           0 :     mHelperSurface = nullptr;
    4111           0 : }
    4112             : 
    4113             : void
    4114           0 : PluginInstanceChild::ClearAllSurfaces()
    4115             : {
    4116           0 :     if (mBackSurface) {
    4117             :         // Get last surface back, and drop it
    4118           0 :         SurfaceDescriptor temp = null_t();
    4119           0 :         NPRect r = { 0, 0, 1, 1 };
    4120           0 :         SendShow(r, temp, &temp);
    4121             :     }
    4122             : 
    4123           0 :     if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface))
    4124           0 :         DeallocShmem(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
    4125           0 :     if (gfxSharedImageSurface::IsSharedImage(mBackSurface))
    4126           0 :         DeallocShmem(static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem());
    4127           0 :     mCurrentSurface = nullptr;
    4128           0 :     mBackSurface = nullptr;
    4129             : 
    4130             : #ifdef XP_WIN
    4131             :     if (mCurrentSurfaceActor) {
    4132             :         PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor);
    4133             :         mCurrentSurfaceActor = nullptr;
    4134             :     }
    4135             :     if (mBackSurfaceActor) {
    4136             :         PPluginSurfaceChild::Send__delete__(mBackSurfaceActor);
    4137             :         mBackSurfaceActor = nullptr;
    4138             :     }
    4139             : #endif
    4140             : 
    4141             : #ifdef MOZ_WIDGET_COCOA
    4142             :     if (mDoubleBufferCARenderer.HasBackSurface()) {
    4143             :         // Get last surface back, and drop it
    4144             :         SurfaceDescriptor temp = null_t();
    4145             :         NPRect r = { 0, 0, 1, 1 };
    4146             :         SendShow(r, temp, &temp);
    4147             :     }
    4148             : 
    4149             :     if (mCGLayer) {
    4150             :         mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
    4151             :         mCGLayer = nullptr;
    4152             :     }
    4153             : 
    4154             :     mDoubleBufferCARenderer.ClearFrontSurface();
    4155             :     mDoubleBufferCARenderer.ClearBackSurface();
    4156             : #endif
    4157           0 : }
    4158             : 
    4159             : static void
    4160           0 : InvalidateObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
    4161             : {
    4162           0 :     for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
    4163           0 :         DeletingObjectEntry* e = iter.Get();
    4164           0 :         NPObject* o = e->GetKey();
    4165           0 :         if (!e->mDeleted && o->_class && o->_class->invalidate) {
    4166           0 :             o->_class->invalidate(o);
    4167             :         }
    4168             :     }
    4169           0 : }
    4170             : 
    4171             : static void
    4172           0 : DeleteObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
    4173             : {
    4174           0 :     for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
    4175           0 :         DeletingObjectEntry* e = iter.Get();
    4176           0 :         NPObject* o = e->GetKey();
    4177           0 :         if (!e->mDeleted) {
    4178           0 :             e->mDeleted = true;
    4179             : 
    4180             : #ifdef NS_BUILD_REFCNT_LOGGING
    4181             :             {
    4182           0 :                 int32_t refcnt = o->referenceCount;
    4183           0 :                 while (refcnt) {
    4184           0 :                     --refcnt;
    4185           0 :                     NS_LOG_RELEASE(o, refcnt, "NPObject");
    4186             :                 }
    4187             :             }
    4188             : #endif
    4189             : 
    4190           0 :             PluginModuleChild::DeallocNPObject(o);
    4191             :         }
    4192             :     }
    4193           0 : }
    4194             : 
    4195             : void
    4196           0 : PluginInstanceChild::Destroy()
    4197             : {
    4198           0 :     if (mDestroyed) {
    4199           0 :         return;
    4200             :     }
    4201           0 :     if (mStackDepth != 0) {
    4202           0 :         MOZ_CRASH("Destroying plugin instance on the stack.");
    4203             :     }
    4204           0 :     mDestroyed = true;
    4205             : 
    4206             : #if defined(OS_WIN)
    4207             :     SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
    4208             : #endif
    4209             : 
    4210           0 :     InfallibleTArray<PBrowserStreamChild*> streams;
    4211           0 :     ManagedPBrowserStreamChild(streams);
    4212             : 
    4213             :     // First make sure none of these streams become deleted
    4214           0 :     for (uint32_t i = 0; i < streams.Length(); ) {
    4215           0 :         if (static_cast<BrowserStreamChild*>(streams[i])->InstanceDying())
    4216           0 :             ++i;
    4217             :         else
    4218           0 :             streams.RemoveElementAt(i);
    4219             :     }
    4220           0 :     for (uint32_t i = 0; i < streams.Length(); ++i)
    4221           0 :         static_cast<BrowserStreamChild*>(streams[i])->FinishDelivery();
    4222             : 
    4223           0 :     mTimers.Clear();
    4224             : 
    4225             :     // NPP_Destroy() should be a synchronization point for plugin threads
    4226             :     // calling NPN_AsyncCall: after this function returns, they are no longer
    4227             :     // allowed to make async calls on this instance.
    4228           0 :     static_cast<PluginModuleChild *>(Manager())->NPP_Destroy(this);
    4229           0 :     mData.ndata = 0;
    4230             : 
    4231           0 :     if (mCurrentInvalidateTask) {
    4232           0 :         mCurrentInvalidateTask->Cancel();
    4233           0 :         mCurrentInvalidateTask = nullptr;
    4234             :     }
    4235           0 :     if (mCurrentAsyncSetWindowTask) {
    4236           0 :         mCurrentAsyncSetWindowTask->Cancel();
    4237           0 :         mCurrentAsyncSetWindowTask = nullptr;
    4238             :     }
    4239             :     {
    4240           0 :         MutexAutoLock autoLock(mAsyncInvalidateMutex);
    4241           0 :         if (mAsyncInvalidateTask) {
    4242           0 :             mAsyncInvalidateTask->Cancel();
    4243           0 :             mAsyncInvalidateTask = nullptr;
    4244             :         }
    4245             :     }
    4246             : 
    4247           0 :     ClearAllSurfaces();
    4248           0 :     mDirectBitmaps.Clear();
    4249             : 
    4250           0 :     mDeletingHash = new nsTHashtable<DeletingObjectEntry>;
    4251           0 :     PluginScriptableObjectChild::NotifyOfInstanceShutdown(this);
    4252             : 
    4253           0 :     InvalidateObjects(*mDeletingHash);
    4254           0 :     DeleteObjects(*mDeletingHash);
    4255             : 
    4256             :     // Null out our cached actors as they should have been killed in the
    4257             :     // PluginInstanceDestroyed call above.
    4258           0 :     mCachedWindowActor = nullptr;
    4259           0 :     mCachedElementActor = nullptr;
    4260             : 
    4261             : #if defined(OS_WIN)
    4262             :     DestroyWinlessPopupSurrogate();
    4263             :     UnhookWinlessFlashThrottle();
    4264             :     DestroyPluginWindow();
    4265             : #endif
    4266             : 
    4267             :     // Pending async calls are discarded, not delivered. This matches the
    4268             :     // in-process behavior.
    4269           0 :     for (uint32_t i = 0; i < mPendingAsyncCalls.Length(); ++i)
    4270           0 :         mPendingAsyncCalls[i]->Cancel();
    4271             : 
    4272           0 :     mPendingAsyncCalls.Clear();
    4273             : }
    4274             : 
    4275             : mozilla::ipc::IPCResult
    4276           0 : PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
    4277             : {
    4278           0 :     PLUGIN_LOG_DEBUG_METHOD;
    4279           0 :     AssertPluginThread();
    4280           0 :     *aResult = NPERR_NO_ERROR;
    4281             : 
    4282           0 :     Destroy();
    4283             : 
    4284           0 :     return IPC_OK();
    4285             : }
    4286             : 
    4287             : void
    4288           0 : PluginInstanceChild::ActorDestroy(ActorDestroyReason why)
    4289             : {
    4290             : #ifdef XP_WIN
    4291             :     // ClearAllSurfaces() should not try to send anything after ActorDestroy.
    4292             :     mCurrentSurfaceActor = nullptr;
    4293             :     mBackSurfaceActor = nullptr;
    4294             : #endif
    4295             : 
    4296           0 :     Destroy();
    4297           0 : }

Generated by: LCOV version 1.13