1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/ipc/PluginInstanceChild.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4003 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: sw=4 ts=4 et : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "PluginBackgroundDestroyer.h" 1.11 +#include "PluginInstanceChild.h" 1.12 +#include "PluginModuleChild.h" 1.13 +#include "BrowserStreamChild.h" 1.14 +#include "PluginStreamChild.h" 1.15 +#include "StreamNotifyChild.h" 1.16 +#include "PluginProcessChild.h" 1.17 +#include "gfxASurface.h" 1.18 +#include "gfxContext.h" 1.19 +#include "nsNPAPIPluginInstance.h" 1.20 +#ifdef MOZ_X11 1.21 +#include "gfxXlibSurface.h" 1.22 +#endif 1.23 +#ifdef XP_WIN 1.24 +#include "mozilla/gfx/SharedDIBSurface.h" 1.25 +#include "nsCrashOnException.h" 1.26 +extern const wchar_t* kFlashFullscreenClass; 1.27 +using mozilla::gfx::SharedDIBSurface; 1.28 +#endif 1.29 +#include "gfxSharedImageSurface.h" 1.30 +#include "gfxUtils.h" 1.31 +#include "gfxAlphaRecovery.h" 1.32 + 1.33 +#include "mozilla/ArrayUtils.h" 1.34 +#include "mozilla/ipc/MessageChannel.h" 1.35 +#include "mozilla/AutoRestore.h" 1.36 +#include "ImageContainer.h" 1.37 + 1.38 +using namespace mozilla; 1.39 +using mozilla::ipc::ProcessChild; 1.40 +using namespace mozilla::plugins; 1.41 +using namespace mozilla::layers; 1.42 +using namespace mozilla::gfx; 1.43 +using namespace std; 1.44 + 1.45 +#ifdef MOZ_WIDGET_GTK 1.46 + 1.47 +#include <gtk/gtk.h> 1.48 +#if (MOZ_WIDGET_GTK == 3) 1.49 +#include <gtk/gtkx.h> 1.50 +#endif 1.51 +#include <gdk/gdkx.h> 1.52 +#include <gdk/gdk.h> 1.53 +#if (MOZ_WIDGET_GTK == 2) 1.54 +#include "gtk2xtbin.h" 1.55 +#endif 1.56 + 1.57 +#elif defined(MOZ_WIDGET_QT) 1.58 +#undef KeyPress 1.59 +#undef KeyRelease 1.60 +#elif defined(OS_WIN) 1.61 +#ifndef WM_MOUSEHWHEEL 1.62 +#define WM_MOUSEHWHEEL 0x020E 1.63 +#endif 1.64 + 1.65 +#include "nsWindowsDllInterceptor.h" 1.66 + 1.67 +typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu, 1.68 + UINT uFlags, 1.69 + int x, 1.70 + int y, 1.71 + int nReserved, 1.72 + HWND hWnd, 1.73 + CONST RECT *prcRect); 1.74 +static WindowsDllInterceptor sUser32Intercept; 1.75 +static HWND sWinlessPopupSurrogateHWND = nullptr; 1.76 +static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr; 1.77 + 1.78 +using mozilla::gfx::SharedDIB; 1.79 + 1.80 +#include <windows.h> 1.81 +#include <windowsx.h> 1.82 + 1.83 +// Flash WM_USER message delay time for PostDelayedTask. Borrowed 1.84 +// from Chromium's web plugin delegate src. See 'flash msg throttling 1.85 +// helpers' section for details. 1.86 +const int kFlashWMUSERMessageThrottleDelayMs = 5; 1.87 + 1.88 +static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty"); 1.89 + 1.90 +#elif defined(XP_MACOSX) 1.91 +#include <ApplicationServices/ApplicationServices.h> 1.92 +#include "nsCocoaFeatures.h" 1.93 +#include "PluginUtilsOSX.h" 1.94 +#endif // defined(XP_MACOSX) 1.95 + 1.96 +template<> 1.97 +struct RunnableMethodTraits<PluginInstanceChild> 1.98 +{ 1.99 + static void RetainCallee(PluginInstanceChild* obj) { } 1.100 + static void ReleaseCallee(PluginInstanceChild* obj) { } 1.101 +}; 1.102 + 1.103 +PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) 1.104 + : mPluginIface(aPluginIface) 1.105 +#if defined(XP_MACOSX) 1.106 + , mContentsScaleFactor(1.0) 1.107 +#endif 1.108 + , mDrawingModel(kDefaultDrawingModel) 1.109 + , mCurrentAsyncSurface(0) 1.110 + , mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex") 1.111 + , mAsyncInvalidateTask(0) 1.112 + , mCachedWindowActor(nullptr) 1.113 + , mCachedElementActor(nullptr) 1.114 +#if (MOZ_WIDGET_GTK == 2) 1.115 + , mXEmbed(false) 1.116 +#endif // MOZ_WIDGET_GTK 1.117 +#if defined(OS_WIN) 1.118 + , mPluginWindowHWND(0) 1.119 + , mPluginWndProc(0) 1.120 + , mPluginParentHWND(0) 1.121 + , mCachedWinlessPluginHWND(0) 1.122 + , mWinlessPopupSurrogateHWND(0) 1.123 + , mWinlessThrottleOldWndProc(0) 1.124 + , mWinlessHiddenMsgHWND(0) 1.125 +#endif // OS_WIN 1.126 + , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex") 1.127 +#if defined(MOZ_WIDGET_COCOA) 1.128 +#if defined(__i386__) 1.129 + , mEventModel(NPEventModelCarbon) 1.130 +#endif 1.131 + , mShColorSpace(nullptr) 1.132 + , mShContext(nullptr) 1.133 + , mCGLayer(nullptr) 1.134 + , mCurrentEvent(nullptr) 1.135 +#endif 1.136 + , mLayersRendering(false) 1.137 +#ifdef XP_WIN 1.138 + , mCurrentSurfaceActor(nullptr) 1.139 + , mBackSurfaceActor(nullptr) 1.140 +#endif 1.141 + , mAccumulatedInvalidRect(0,0,0,0) 1.142 + , mIsTransparent(false) 1.143 + , mSurfaceType(gfxSurfaceType::Max) 1.144 + , mCurrentInvalidateTask(nullptr) 1.145 + , mCurrentAsyncSetWindowTask(nullptr) 1.146 + , mPendingPluginCall(false) 1.147 + , mDoAlphaExtraction(false) 1.148 + , mHasPainted(false) 1.149 + , mSurfaceDifferenceRect(0,0,0,0) 1.150 +{ 1.151 + memset(&mWindow, 0, sizeof(mWindow)); 1.152 + mWindow.type = NPWindowTypeWindow; 1.153 + mData.ndata = (void*) this; 1.154 + mData.pdata = nullptr; 1.155 +#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) 1.156 + mWindow.ws_info = &mWsInfo; 1.157 + memset(&mWsInfo, 0, sizeof(mWsInfo)); 1.158 +#if (MOZ_WIDGET_GTK == 2) 1.159 + mWsInfo.display = nullptr; 1.160 + mXtClient.top_widget = nullptr; 1.161 +#else 1.162 + mWsInfo.display = DefaultXDisplay(); 1.163 +#endif 1.164 +#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX 1.165 +#if defined(OS_WIN) 1.166 + memset(&mAlphaExtract, 0, sizeof(mAlphaExtract)); 1.167 +#endif // OS_WIN 1.168 +#if defined(OS_WIN) 1.169 + InitPopupMenuHook(); 1.170 +#endif // OS_WIN 1.171 +} 1.172 + 1.173 +PluginInstanceChild::~PluginInstanceChild() 1.174 +{ 1.175 +#if defined(OS_WIN) 1.176 + NS_ASSERTION(!mPluginWindowHWND, "Destroying PluginInstanceChild without NPP_Destroy?"); 1.177 +#endif 1.178 +#if defined(MOZ_WIDGET_COCOA) 1.179 + if (mShColorSpace) { 1.180 + ::CGColorSpaceRelease(mShColorSpace); 1.181 + } 1.182 + if (mShContext) { 1.183 + ::CGContextRelease(mShContext); 1.184 + } 1.185 + if (mCGLayer) { 1.186 + PluginUtilsOSX::ReleaseCGLayer(mCGLayer); 1.187 + } 1.188 + if (mDrawingModel == NPDrawingModelCoreAnimation) { 1.189 + UnscheduleTimer(mCARefreshTimer); 1.190 + } 1.191 +#endif 1.192 +} 1.193 + 1.194 +int 1.195 +PluginInstanceChild::GetQuirks() 1.196 +{ 1.197 + return PluginModuleChild::current()->GetQuirks(); 1.198 +} 1.199 + 1.200 +NPError 1.201 +PluginInstanceChild::InternalGetNPObjectForValue(NPNVariable aValue, 1.202 + NPObject** aObject) 1.203 +{ 1.204 + PluginScriptableObjectChild* actor = nullptr; 1.205 + NPError result = NPERR_NO_ERROR; 1.206 + 1.207 + switch (aValue) { 1.208 + case NPNVWindowNPObject: 1.209 + if (!(actor = mCachedWindowActor)) { 1.210 + PPluginScriptableObjectChild* actorProtocol; 1.211 + CallNPN_GetValue_NPNVWindowNPObject(&actorProtocol, &result); 1.212 + if (result == NPERR_NO_ERROR) { 1.213 + actor = mCachedWindowActor = 1.214 + static_cast<PluginScriptableObjectChild*>(actorProtocol); 1.215 + NS_ASSERTION(actor, "Null actor!"); 1.216 + PluginModuleChild::sBrowserFuncs.retainobject( 1.217 + actor->GetObject(false)); 1.218 + } 1.219 + } 1.220 + break; 1.221 + 1.222 + case NPNVPluginElementNPObject: 1.223 + if (!(actor = mCachedElementActor)) { 1.224 + PPluginScriptableObjectChild* actorProtocol; 1.225 + CallNPN_GetValue_NPNVPluginElementNPObject(&actorProtocol, 1.226 + &result); 1.227 + if (result == NPERR_NO_ERROR) { 1.228 + actor = mCachedElementActor = 1.229 + static_cast<PluginScriptableObjectChild*>(actorProtocol); 1.230 + NS_ASSERTION(actor, "Null actor!"); 1.231 + PluginModuleChild::sBrowserFuncs.retainobject( 1.232 + actor->GetObject(false)); 1.233 + } 1.234 + } 1.235 + break; 1.236 + 1.237 + default: 1.238 + NS_NOTREACHED("Don't know what to do with this value type!"); 1.239 + } 1.240 + 1.241 +#ifdef DEBUG 1.242 + { 1.243 + NPError currentResult; 1.244 + PPluginScriptableObjectChild* currentActor = nullptr; 1.245 + 1.246 + switch (aValue) { 1.247 + case NPNVWindowNPObject: 1.248 + CallNPN_GetValue_NPNVWindowNPObject(¤tActor, 1.249 + ¤tResult); 1.250 + break; 1.251 + case NPNVPluginElementNPObject: 1.252 + CallNPN_GetValue_NPNVPluginElementNPObject(¤tActor, 1.253 + ¤tResult); 1.254 + break; 1.255 + default: 1.256 + MOZ_ASSERT(false); 1.257 + } 1.258 + 1.259 + // Make sure that the current actor returned by the parent matches our 1.260 + // cached actor! 1.261 + NS_ASSERTION(!currentActor || 1.262 + static_cast<PluginScriptableObjectChild*>(currentActor) == 1.263 + actor, "Cached actor is out of date!"); 1.264 + } 1.265 +#endif 1.266 + 1.267 + if (result != NPERR_NO_ERROR) { 1.268 + return result; 1.269 + } 1.270 + 1.271 + NPObject* object = actor->GetObject(false); 1.272 + NS_ASSERTION(object, "Null object?!"); 1.273 + 1.274 + *aObject = PluginModuleChild::sBrowserFuncs.retainobject(object); 1.275 + return NPERR_NO_ERROR; 1.276 + 1.277 +} 1.278 + 1.279 +NPError 1.280 +PluginInstanceChild::NPN_GetValue(NPNVariable aVar, 1.281 + void* aValue) 1.282 +{ 1.283 + PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION, (int) aVar)); 1.284 + AssertPluginThread(); 1.285 + 1.286 + switch(aVar) { 1.287 + 1.288 +#if defined(MOZ_X11) 1.289 + case NPNVToolkit: 1.290 + *((NPNToolkitType*)aValue) = NPNVGtk2; 1.291 + return NPERR_NO_ERROR; 1.292 + 1.293 + case NPNVxDisplay: 1.294 + if (!mWsInfo.display) { 1.295 + // We are called before Initialize() so we have to call it now. 1.296 + Initialize(); 1.297 + NS_ASSERTION(mWsInfo.display, "We should have a valid display!"); 1.298 + } 1.299 + *(void **)aValue = mWsInfo.display; 1.300 + return NPERR_NO_ERROR; 1.301 + 1.302 +#elif defined(OS_WIN) 1.303 + case NPNVToolkit: 1.304 + return NPERR_GENERIC_ERROR; 1.305 +#endif 1.306 + case NPNVprivateModeBool: { 1.307 + bool v = false; 1.308 + NPError result; 1.309 + if (!CallNPN_GetValue_NPNVprivateModeBool(&v, &result)) { 1.310 + return NPERR_GENERIC_ERROR; 1.311 + } 1.312 + *static_cast<NPBool*>(aValue) = v; 1.313 + return result; 1.314 + } 1.315 + 1.316 + case NPNVdocumentOrigin: { 1.317 + nsCString v; 1.318 + NPError result; 1.319 + if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) { 1.320 + return NPERR_GENERIC_ERROR; 1.321 + } 1.322 + if (result == NPERR_NO_ERROR) { 1.323 + *static_cast<char**>(aValue) = ToNewCString(v); 1.324 + } 1.325 + return result; 1.326 + } 1.327 + 1.328 + case NPNVWindowNPObject: // Intentional fall-through 1.329 + case NPNVPluginElementNPObject: { 1.330 + NPObject* object; 1.331 + NPError result = InternalGetNPObjectForValue(aVar, &object); 1.332 + if (result == NPERR_NO_ERROR) { 1.333 + *((NPObject**)aValue) = object; 1.334 + } 1.335 + return result; 1.336 + } 1.337 + 1.338 + case NPNVnetscapeWindow: { 1.339 +#ifdef XP_WIN 1.340 + if (mWindow.type == NPWindowTypeDrawable) { 1.341 + if (mCachedWinlessPluginHWND) { 1.342 + *static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND; 1.343 + return NPERR_NO_ERROR; 1.344 + } 1.345 + NPError result; 1.346 + if (!CallNPN_GetValue_NPNVnetscapeWindow(&mCachedWinlessPluginHWND, &result)) { 1.347 + return NPERR_GENERIC_ERROR; 1.348 + } 1.349 + *static_cast<HWND*>(aValue) = mCachedWinlessPluginHWND; 1.350 + return result; 1.351 + } 1.352 + else { 1.353 + *static_cast<HWND*>(aValue) = mPluginWindowHWND; 1.354 + return NPERR_NO_ERROR; 1.355 + } 1.356 +#elif defined(MOZ_X11) 1.357 + NPError result; 1.358 + CallNPN_GetValue_NPNVnetscapeWindow(static_cast<XID*>(aValue), &result); 1.359 + return result; 1.360 +#else 1.361 + return NPERR_GENERIC_ERROR; 1.362 +#endif 1.363 + } 1.364 + 1.365 + case NPNVsupportsAsyncBitmapSurfaceBool: { 1.366 +#ifdef XP_WIN 1.367 + *((NPBool*)aValue) = PluginModuleChild::current()->AsyncDrawingAllowed(); 1.368 +#else 1.369 + // We do not support non-windows yet. 1.370 + *((NPBool*)aValue) = false; 1.371 +#endif 1.372 + return NPERR_NO_ERROR; 1.373 + } 1.374 + 1.375 +#ifdef XP_WIN 1.376 + case NPNVsupportsAsyncWindowsDXGISurfaceBool: { 1.377 + bool val; 1.378 + CallNPN_GetValue_DrawingModelSupport(NPNVsupportsAsyncWindowsDXGISurfaceBool, &val); 1.379 + *((NPBool*)aValue) = val; 1.380 + return NPERR_NO_ERROR; 1.381 + } 1.382 +#endif 1.383 + 1.384 +#ifdef XP_MACOSX 1.385 + case NPNVsupportsCoreGraphicsBool: { 1.386 + *((NPBool*)aValue) = true; 1.387 + return NPERR_NO_ERROR; 1.388 + } 1.389 + 1.390 + case NPNVsupportsCoreAnimationBool: { 1.391 + *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins(); 1.392 + return NPERR_NO_ERROR; 1.393 + } 1.394 + 1.395 + case NPNVsupportsInvalidatingCoreAnimationBool: { 1.396 + *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins(); 1.397 + return NPERR_NO_ERROR; 1.398 + } 1.399 + 1.400 + case NPNVsupportsCompositingCoreAnimationPluginsBool: { 1.401 + *((NPBool*)aValue) = true; 1.402 + return NPERR_NO_ERROR; 1.403 + } 1.404 + 1.405 + case NPNVsupportsCocoaBool: { 1.406 + *((NPBool*)aValue) = true; 1.407 + return NPERR_NO_ERROR; 1.408 + } 1.409 + 1.410 +#ifndef NP_NO_CARBON 1.411 + case NPNVsupportsCarbonBool: { 1.412 + *((NPBool*)aValue) = false; 1.413 + return NPERR_NO_ERROR; 1.414 + } 1.415 +#endif 1.416 + 1.417 + case NPNVsupportsUpdatedCocoaTextInputBool: { 1.418 + *static_cast<NPBool*>(aValue) = true; 1.419 + return NPERR_NO_ERROR; 1.420 + } 1.421 + 1.422 +#ifndef NP_NO_QUICKDRAW 1.423 + case NPNVsupportsQuickDrawBool: { 1.424 + *((NPBool*)aValue) = false; 1.425 + return NPERR_NO_ERROR; 1.426 + } 1.427 +#endif /* NP_NO_QUICKDRAW */ 1.428 + 1.429 + case NPNVcontentsScaleFactor: { 1.430 + *static_cast<double*>(aValue) = mContentsScaleFactor; 1.431 + return NPERR_NO_ERROR; 1.432 + } 1.433 +#endif /* XP_MACOSX */ 1.434 + 1.435 +#ifdef DEBUG 1.436 + case NPNVjavascriptEnabledBool: 1.437 + case NPNVasdEnabledBool: 1.438 + case NPNVisOfflineBool: 1.439 + case NPNVSupportsXEmbedBool: 1.440 + case NPNVSupportsWindowless: 1.441 + NS_NOTREACHED("NPNVariable should be handled in PluginModuleChild."); 1.442 +#endif 1.443 + 1.444 + default: 1.445 + PR_LOG(GetPluginLog(), PR_LOG_WARNING, 1.446 + ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)", 1.447 + (int) aVar, NPNVariableToString(aVar))); 1.448 + return NPERR_GENERIC_ERROR; 1.449 + } 1.450 + 1.451 +} 1.452 + 1.453 +#ifdef MOZ_WIDGET_COCOA 1.454 +#define DEFAULT_REFRESH_MS 20 // CoreAnimation: 50 FPS 1.455 + 1.456 +void 1.457 +CAUpdate(NPP npp, uint32_t timerID) { 1.458 + static_cast<PluginInstanceChild*>(npp->ndata)->Invalidate(); 1.459 +} 1.460 + 1.461 +void 1.462 +PluginInstanceChild::Invalidate() 1.463 +{ 1.464 + NPRect windowRect = {0, 0, uint16_t(mWindow.height), 1.465 + uint16_t(mWindow.width)}; 1.466 + 1.467 + InvalidateRect(&windowRect); 1.468 +} 1.469 +#endif 1.470 + 1.471 +NPError 1.472 +PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue) 1.473 +{ 1.474 + PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s (aVar=%i, aValue=%p)", 1.475 + FULLFUNCTION, (int) aVar, aValue)); 1.476 + 1.477 + AssertPluginThread(); 1.478 + 1.479 + switch (aVar) { 1.480 + case NPPVpluginWindowBool: { 1.481 + NPError rv; 1.482 + bool windowed = (NPBool) (intptr_t) aValue; 1.483 + 1.484 + if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv)) 1.485 + return NPERR_GENERIC_ERROR; 1.486 + 1.487 + NPWindowType newWindowType = windowed ? NPWindowTypeWindow : NPWindowTypeDrawable; 1.488 +#if (MOZ_WIDGET_GTK == 2) 1.489 + if (mWindow.type != newWindowType && mWsInfo.display) { 1.490 + // plugin type has been changed but we already have a valid display 1.491 + // so update it for the recent plugin mode 1.492 + if (mXEmbed || !windowed) { 1.493 + // Use default GTK display for XEmbed and windowless plugins 1.494 + mWsInfo.display = DefaultXDisplay(); 1.495 + } 1.496 + else { 1.497 + mWsInfo.display = xt_client_get_display(); 1.498 + } 1.499 + } 1.500 +#endif 1.501 + mWindow.type = newWindowType; 1.502 + return rv; 1.503 + } 1.504 + 1.505 + case NPPVpluginTransparentBool: { 1.506 + NPError rv; 1.507 + mIsTransparent = (!!aValue); 1.508 + 1.509 + if (!CallNPN_SetValue_NPPVpluginTransparent(mIsTransparent, &rv)) 1.510 + return NPERR_GENERIC_ERROR; 1.511 + 1.512 + return rv; 1.513 + } 1.514 + 1.515 + case NPPVpluginUsesDOMForCursorBool: { 1.516 + NPError rv = NPERR_GENERIC_ERROR; 1.517 + if (!CallNPN_SetValue_NPPVpluginUsesDOMForCursor((NPBool)(intptr_t)aValue, &rv)) { 1.518 + return NPERR_GENERIC_ERROR; 1.519 + } 1.520 + return rv; 1.521 + } 1.522 + 1.523 + case NPPVpluginDrawingModel: { 1.524 + NPError rv; 1.525 + int drawingModel = (int16_t) (intptr_t) aValue; 1.526 + 1.527 + if (!PluginModuleChild::current()->AsyncDrawingAllowed() && 1.528 + IsDrawingModelAsync(drawingModel)) { 1.529 + return NPERR_GENERIC_ERROR; 1.530 + } 1.531 + 1.532 + CrossProcessMutexHandle handle; 1.533 + OptionalShmem optionalShmem; 1.534 + if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &optionalShmem, &handle, &rv)) 1.535 + return NPERR_GENERIC_ERROR; 1.536 + 1.537 + if (IsDrawingModelAsync(drawingModel)) { 1.538 + if (optionalShmem.type() != OptionalShmem::TShmem) { 1.539 + return NPERR_GENERIC_ERROR; 1.540 + } 1.541 + mRemoteImageDataShmem = optionalShmem.get_Shmem(); 1.542 + mRemoteImageData = mRemoteImageDataShmem.get<RemoteImageData>(); 1.543 + mRemoteImageDataMutex = new CrossProcessMutex(handle); 1.544 + } 1.545 + mDrawingModel = drawingModel; 1.546 + 1.547 +#ifdef XP_MACOSX 1.548 + if (drawingModel == NPDrawingModelCoreAnimation) { 1.549 + mCARefreshTimer = ScheduleTimer(DEFAULT_REFRESH_MS, true, CAUpdate); 1.550 + } 1.551 +#endif 1.552 + 1.553 + PLUGIN_LOG_DEBUG((" Plugin requested drawing model id #%i\n", 1.554 + mDrawingModel)); 1.555 + 1.556 + return rv; 1.557 + } 1.558 + 1.559 +#ifdef XP_MACOSX 1.560 + case NPPVpluginEventModel: { 1.561 + NPError rv; 1.562 + int eventModel = (int16_t) (intptr_t) aValue; 1.563 + 1.564 + if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv)) 1.565 + return NPERR_GENERIC_ERROR; 1.566 +#if defined(__i386__) 1.567 + mEventModel = static_cast<NPEventModel>(eventModel); 1.568 +#endif 1.569 + 1.570 + PLUGIN_LOG_DEBUG((" Plugin requested event model id # %i\n", 1.571 + eventModel)); 1.572 + 1.573 + return rv; 1.574 + } 1.575 +#endif 1.576 + 1.577 + default: 1.578 + PR_LOG(GetPluginLog(), PR_LOG_WARNING, 1.579 + ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)", 1.580 + (int) aVar, NPPVariableToString(aVar))); 1.581 + return NPERR_GENERIC_ERROR; 1.582 + } 1.583 +} 1.584 + 1.585 +bool 1.586 +PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams( 1.587 + bool* wantsAllStreams, NPError* rv) 1.588 +{ 1.589 + AssertPluginThread(); 1.590 + 1.591 + uint32_t value = 0; 1.592 + if (!mPluginIface->getvalue) { 1.593 + *rv = NPERR_GENERIC_ERROR; 1.594 + } 1.595 + else { 1.596 + *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWantsAllNetworkStreams, 1.597 + &value); 1.598 + } 1.599 + *wantsAllStreams = value; 1.600 + return true; 1.601 +} 1.602 + 1.603 +bool 1.604 +PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed( 1.605 + bool* needs, NPError* rv) 1.606 +{ 1.607 + AssertPluginThread(); 1.608 + 1.609 +#ifdef MOZ_X11 1.610 + // The documentation on the types for many variables in NP(N|P)_GetValue 1.611 + // is vague. Often boolean values are NPBool (1 byte), but 1.612 + // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins 1.613 + // treats NPPVpluginNeedsXEmbed as PRBool (int), and 1.614 + // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|. 1.615 + // thus we can't use NPBool for needsXEmbed, or the three bytes above 1.616 + // it on the stack would get clobbered. so protect with the larger bool. 1.617 + int needsXEmbed = 0; 1.618 + if (!mPluginIface->getvalue) { 1.619 + *rv = NPERR_GENERIC_ERROR; 1.620 + } 1.621 + else { 1.622 + *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginNeedsXEmbed, 1.623 + &needsXEmbed); 1.624 + } 1.625 + *needs = needsXEmbed; 1.626 + return true; 1.627 + 1.628 +#else 1.629 + 1.630 + NS_RUNTIMEABORT("shouldn't be called on non-X11 platforms"); 1.631 + return false; // not reached 1.632 + 1.633 +#endif 1.634 +} 1.635 + 1.636 +bool 1.637 +PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject( 1.638 + PPluginScriptableObjectChild** aValue, 1.639 + NPError* aResult) 1.640 +{ 1.641 + AssertPluginThread(); 1.642 + 1.643 + NPObject* object = nullptr; 1.644 + NPError result = NPERR_GENERIC_ERROR; 1.645 + if (mPluginIface->getvalue) { 1.646 + result = mPluginIface->getvalue(GetNPP(), NPPVpluginScriptableNPObject, 1.647 + &object); 1.648 + } 1.649 + if (result == NPERR_NO_ERROR && object) { 1.650 + PluginScriptableObjectChild* actor = GetActorForNPObject(object); 1.651 + 1.652 + // If we get an actor then it has retained. Otherwise we don't need it 1.653 + // any longer. 1.654 + PluginModuleChild::sBrowserFuncs.releaseobject(object); 1.655 + if (actor) { 1.656 + *aValue = actor; 1.657 + *aResult = NPERR_NO_ERROR; 1.658 + return true; 1.659 + } 1.660 + 1.661 + NS_ERROR("Failed to get actor!"); 1.662 + result = NPERR_GENERIC_ERROR; 1.663 + } 1.664 + else { 1.665 + result = NPERR_GENERIC_ERROR; 1.666 + } 1.667 + 1.668 + *aValue = nullptr; 1.669 + *aResult = result; 1.670 + return true; 1.671 +} 1.672 + 1.673 +bool 1.674 +PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId( 1.675 + nsCString* aPlugId, 1.676 + NPError* aResult) 1.677 +{ 1.678 + AssertPluginThread(); 1.679 + 1.680 +#if MOZ_ACCESSIBILITY_ATK 1.681 + 1.682 + char* plugId = nullptr; 1.683 + NPError result = NPERR_GENERIC_ERROR; 1.684 + if (mPluginIface->getvalue) { 1.685 + result = mPluginIface->getvalue(GetNPP(), 1.686 + NPPVpluginNativeAccessibleAtkPlugId, 1.687 + &plugId); 1.688 + } 1.689 + 1.690 + *aPlugId = nsCString(plugId); 1.691 + *aResult = result; 1.692 + return true; 1.693 + 1.694 +#else 1.695 + 1.696 + NS_RUNTIMEABORT("shouldn't be called on non-ATK platforms"); 1.697 + return false; 1.698 + 1.699 +#endif 1.700 +} 1.701 + 1.702 +bool 1.703 +PluginInstanceChild::AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value, 1.704 + NPError* result) 1.705 +{ 1.706 + if (!mPluginIface->setvalue) { 1.707 + *result = NPERR_GENERIC_ERROR; 1.708 + return true; 1.709 + } 1.710 + 1.711 + NPBool v = value; 1.712 + *result = mPluginIface->setvalue(GetNPP(), NPNVprivateModeBool, &v); 1.713 + return true; 1.714 +} 1.715 + 1.716 +bool 1.717 +PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event, 1.718 + int16_t* handled) 1.719 +{ 1.720 + PLUGIN_LOG_DEBUG_FUNCTION; 1.721 + AssertPluginThread(); 1.722 + 1.723 +#if defined(MOZ_X11) && defined(DEBUG) 1.724 + if (GraphicsExpose == event.event.type) 1.725 + PLUGIN_LOG_DEBUG((" received drawable 0x%lx\n", 1.726 + event.event.xgraphicsexpose.drawable)); 1.727 +#endif 1.728 + 1.729 +#ifdef XP_MACOSX 1.730 + // Mac OS X does not define an NPEvent structure. It defines more specific types. 1.731 + NPCocoaEvent evcopy = event.event; 1.732 + // event.contentsScaleFactor <= 0 is a signal we shouldn't use it, 1.733 + // for example when AnswerNPP_HandleEvent() is called from elsewhere 1.734 + // in the child process (not via rpc code from the parent process). 1.735 + if (event.contentsScaleFactor > 0) { 1.736 + mContentsScaleFactor = event.contentsScaleFactor; 1.737 + } 1.738 + 1.739 + // Make sure we reset mCurrentEvent in case of an exception 1.740 + AutoRestore<const NPCocoaEvent*> savePreviousEvent(mCurrentEvent); 1.741 + 1.742 + // Track the current event for NPN_PopUpContextMenu. 1.743 + mCurrentEvent = &event.event; 1.744 +#else 1.745 + // Make a copy since we may modify values. 1.746 + NPEvent evcopy = event.event; 1.747 +#endif 1.748 + 1.749 +#ifdef OS_WIN 1.750 + // FIXME/bug 567645: temporarily drop the "dummy event" on the floor 1.751 + if (WM_NULL == evcopy.event) 1.752 + return true; 1.753 + 1.754 + // Painting for win32. SharedSurfacePaint handles everything. 1.755 + if (mWindow.type == NPWindowTypeDrawable) { 1.756 + if (evcopy.event == WM_PAINT) { 1.757 + *handled = SharedSurfacePaint(evcopy); 1.758 + return true; 1.759 + } 1.760 + else if (DoublePassRenderingEvent() == evcopy.event) { 1.761 + // We'll render to mSharedSurfaceDib first, then render to a cached bitmap 1.762 + // we store locally. The two passes are for alpha extraction, so the second 1.763 + // pass must be to a flat white surface in order for things to work. 1.764 + mAlphaExtract.doublePass = RENDER_BACK_ONE; 1.765 + *handled = true; 1.766 + return true; 1.767 + } 1.768 + } 1.769 + *handled = WinlessHandleEvent(evcopy); 1.770 + return true; 1.771 +#endif 1.772 + 1.773 + // XXX A previous call to mPluginIface->event might block, e.g. right click 1.774 + // for context menu. Still, we might get here again, calling into the plugin 1.775 + // a second time while it's in the previous call. 1.776 + if (!mPluginIface->event) 1.777 + *handled = false; 1.778 + else 1.779 + *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy)); 1.780 + 1.781 +#ifdef XP_MACOSX 1.782 + // Release any reference counted objects created in the child process. 1.783 + if (evcopy.type == NPCocoaEventKeyDown || 1.784 + evcopy.type == NPCocoaEventKeyUp) { 1.785 + ::CFRelease((CFStringRef)evcopy.data.key.characters); 1.786 + ::CFRelease((CFStringRef)evcopy.data.key.charactersIgnoringModifiers); 1.787 + } 1.788 + else if (evcopy.type == NPCocoaEventTextInput) { 1.789 + ::CFRelease((CFStringRef)evcopy.data.text.text); 1.790 + } 1.791 +#endif 1.792 + 1.793 +#ifdef MOZ_X11 1.794 + if (GraphicsExpose == event.event.type) { 1.795 + // Make sure the X server completes the drawing before the parent 1.796 + // draws on top and destroys the Drawable. 1.797 + // 1.798 + // XSync() waits for the X server to complete. Really this child 1.799 + // process does not need to wait; the parent is the process that needs 1.800 + // to wait. A possibly-slightly-better alternative would be to send 1.801 + // an X event to the parent that the parent would wait for. 1.802 + XSync(mWsInfo.display, False); 1.803 + } 1.804 +#endif 1.805 + 1.806 + return true; 1.807 +} 1.808 + 1.809 +#ifdef XP_MACOSX 1.810 + 1.811 +bool 1.812 +PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, 1.813 + Shmem& mem, 1.814 + int16_t* handled, 1.815 + Shmem* rtnmem) 1.816 +{ 1.817 + PLUGIN_LOG_DEBUG_FUNCTION; 1.818 + AssertPluginThread(); 1.819 + 1.820 + PaintTracker pt; 1.821 + 1.822 + NPCocoaEvent evcopy = event.event; 1.823 + mContentsScaleFactor = event.contentsScaleFactor; 1.824 + 1.825 + if (evcopy.type == NPCocoaEventDrawRect) { 1.826 + int scaleFactor = ceil(mContentsScaleFactor); 1.827 + if (!mShColorSpace) { 1.828 + mShColorSpace = CreateSystemColorSpace(); 1.829 + if (!mShColorSpace) { 1.830 + PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); 1.831 + *handled = false; 1.832 + *rtnmem = mem; 1.833 + return true; 1.834 + } 1.835 + } 1.836 + if (!mShContext) { 1.837 + void* cgContextByte = mem.get<char>(); 1.838 + mShContext = ::CGBitmapContextCreate(cgContextByte, 1.839 + mWindow.width * scaleFactor, 1.840 + mWindow.height * scaleFactor, 8, 1.841 + mWindow.width * 4 * scaleFactor, mShColorSpace, 1.842 + kCGImageAlphaPremultipliedFirst | 1.843 + kCGBitmapByteOrder32Host); 1.844 + 1.845 + if (!mShContext) { 1.846 + PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); 1.847 + *handled = false; 1.848 + *rtnmem = mem; 1.849 + return true; 1.850 + } 1.851 + } 1.852 + CGRect clearRect = ::CGRectMake(0, 0, mWindow.width, mWindow.height); 1.853 + ::CGContextClearRect(mShContext, clearRect); 1.854 + evcopy.data.draw.context = mShContext; 1.855 + } else { 1.856 + PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem.")); 1.857 + *handled = false; 1.858 + *rtnmem = mem; 1.859 + return true; 1.860 + } 1.861 + 1.862 + if (!mPluginIface->event) { 1.863 + *handled = false; 1.864 + } else { 1.865 + ::CGContextSaveGState(evcopy.data.draw.context); 1.866 + *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy)); 1.867 + ::CGContextRestoreGState(evcopy.data.draw.context); 1.868 + } 1.869 + 1.870 + *rtnmem = mem; 1.871 + return true; 1.872 +} 1.873 + 1.874 +#else 1.875 +bool 1.876 +PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, 1.877 + Shmem& mem, 1.878 + int16_t* handled, 1.879 + Shmem* rtnmem) 1.880 +{ 1.881 + NS_RUNTIMEABORT("not reached."); 1.882 + *rtnmem = mem; 1.883 + return true; 1.884 +} 1.885 +#endif 1.886 + 1.887 +#ifdef XP_MACOSX 1.888 + 1.889 +void CallCGDraw(CGContextRef ref, void* aPluginInstance, nsIntRect aUpdateRect) { 1.890 + PluginInstanceChild* pluginInstance = (PluginInstanceChild*)aPluginInstance; 1.891 + 1.892 + pluginInstance->CGDraw(ref, aUpdateRect); 1.893 +} 1.894 + 1.895 +bool 1.896 +PluginInstanceChild::CGDraw(CGContextRef ref, nsIntRect aUpdateRect) { 1.897 + 1.898 + NPCocoaEvent drawEvent; 1.899 + drawEvent.type = NPCocoaEventDrawRect; 1.900 + drawEvent.version = 0; 1.901 + drawEvent.data.draw.x = aUpdateRect.x; 1.902 + drawEvent.data.draw.y = aUpdateRect.y; 1.903 + drawEvent.data.draw.width = aUpdateRect.width; 1.904 + drawEvent.data.draw.height = aUpdateRect.height; 1.905 + drawEvent.data.draw.context = ref; 1.906 + 1.907 + NPRemoteEvent remoteDrawEvent = {drawEvent}; 1.908 + // Signal to AnswerNPP_HandleEvent() not to use this value 1.909 + remoteDrawEvent.contentsScaleFactor = -1.0; 1.910 + 1.911 + int16_t handled; 1.912 + AnswerNPP_HandleEvent(remoteDrawEvent, &handled); 1.913 + return handled == true; 1.914 +} 1.915 + 1.916 +bool 1.917 +PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event, 1.918 + const uint32_t &surfaceid, 1.919 + int16_t* handled) 1.920 +{ 1.921 + PLUGIN_LOG_DEBUG_FUNCTION; 1.922 + AssertPluginThread(); 1.923 + 1.924 + PaintTracker pt; 1.925 + 1.926 + NPCocoaEvent evcopy = event.event; 1.927 + mContentsScaleFactor = event.contentsScaleFactor; 1.928 + RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid, 1.929 + mContentsScaleFactor); 1.930 + if (!surf) { 1.931 + NS_ERROR("Invalid IOSurface."); 1.932 + *handled = false; 1.933 + return false; 1.934 + } 1.935 + 1.936 + if (!mCARenderer) { 1.937 + mCARenderer = new nsCARenderer(); 1.938 + } 1.939 + 1.940 + if (evcopy.type == NPCocoaEventDrawRect) { 1.941 + mCARenderer->AttachIOSurface(surf); 1.942 + if (!mCARenderer->isInit()) { 1.943 + void *caLayer = nullptr; 1.944 + NPError result = mPluginIface->getvalue(GetNPP(), 1.945 + NPPVpluginCoreAnimationLayer, 1.946 + &caLayer); 1.947 + 1.948 + if (result != NPERR_NO_ERROR || !caLayer) { 1.949 + PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not " 1.950 + "provide CALayer.")); 1.951 + *handled = false; 1.952 + return false; 1.953 + } 1.954 + 1.955 + mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height, 1.956 + mContentsScaleFactor, 1.957 + GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ? 1.958 + ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER); 1.959 + 1.960 + // Flash needs to have the window set again after this step 1.961 + if (mPluginIface->setwindow) 1.962 + (void) mPluginIface->setwindow(&mData, &mWindow); 1.963 + } 1.964 + } else { 1.965 + PLUGIN_LOG_DEBUG(("Invalid event type for " 1.966 + "AnswerNNP_HandleEvent_IOSurface.")); 1.967 + *handled = false; 1.968 + return false; 1.969 + } 1.970 + 1.971 + mCARenderer->Render(mWindow.width, mWindow.height, 1.972 + mContentsScaleFactor, nullptr); 1.973 + 1.974 + return true; 1.975 + 1.976 +} 1.977 + 1.978 +#else 1.979 +bool 1.980 +PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event, 1.981 + const uint32_t &surfaceid, 1.982 + int16_t* handled) 1.983 +{ 1.984 + NS_RUNTIMEABORT("NPP_HandleEvent_IOSurface is a OSX-only message"); 1.985 + return false; 1.986 +} 1.987 +#endif 1.988 + 1.989 +bool 1.990 +PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event) 1.991 +{ 1.992 + NS_ASSERTION(!mLayersRendering && !mPendingPluginCall, 1.993 + "Shouldn't be receiving WindowPosChanged with layer rendering"); 1.994 + 1.995 +#ifdef OS_WIN 1.996 + int16_t dontcare; 1.997 + return AnswerNPP_HandleEvent(event, &dontcare); 1.998 +#else 1.999 + NS_RUNTIMEABORT("WindowPosChanged is a windows-only message"); 1.1000 + return false; 1.1001 +#endif 1.1002 +} 1.1003 + 1.1004 +bool 1.1005 +PluginInstanceChild::RecvContentsScaleFactorChanged(const double& aContentsScaleFactor) 1.1006 +{ 1.1007 +#ifdef XP_MACOSX 1.1008 + mContentsScaleFactor = aContentsScaleFactor; 1.1009 + if (mShContext) { 1.1010 + // Release the shared context so that it is reallocated 1.1011 + // with the new size. 1.1012 + ::CGContextRelease(mShContext); 1.1013 + mShContext = nullptr; 1.1014 + } 1.1015 + return true; 1.1016 +#else 1.1017 + NS_RUNTIMEABORT("ContentsScaleFactorChanged is an OSX-only message"); 1.1018 + return false; 1.1019 +#endif 1.1020 +} 1.1021 + 1.1022 +#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) 1.1023 +// Create a new window from NPWindow 1.1024 +bool PluginInstanceChild::CreateWindow(const NPRemoteWindow& aWindow) 1.1025 +{ 1.1026 + PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)", 1.1027 + FULLFUNCTION, 1.1028 + aWindow.window, 1.1029 + aWindow.x, aWindow.y, 1.1030 + aWindow.width, aWindow.height)); 1.1031 + 1.1032 +#if (MOZ_WIDGET_GTK == 2) 1.1033 + if (mXEmbed) { 1.1034 + mWindow.window = reinterpret_cast<void*>(aWindow.window); 1.1035 + } 1.1036 + else { 1.1037 + Window browserSocket = (Window)(aWindow.window); 1.1038 + xt_client_init(&mXtClient, mWsInfo.visual, mWsInfo.colormap, mWsInfo.depth); 1.1039 + xt_client_create(&mXtClient, browserSocket, mWindow.width, mWindow.height); 1.1040 + mWindow.window = (void *)XtWindow(mXtClient.child_widget); 1.1041 + } 1.1042 +#else 1.1043 + mWindow.window = reinterpret_cast<void*>(aWindow.window); 1.1044 +#endif 1.1045 + 1.1046 + return true; 1.1047 +} 1.1048 + 1.1049 +// Destroy window 1.1050 +void PluginInstanceChild::DeleteWindow() 1.1051 +{ 1.1052 + PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)", 1.1053 + FULLFUNCTION, 1.1054 + mWindow.window, 1.1055 + mWindow.x, mWindow.y, 1.1056 + mWindow.width, mWindow.height)); 1.1057 + 1.1058 + if (!mWindow.window) 1.1059 + return; 1.1060 + 1.1061 +#if (MOZ_WIDGET_GTK == 2) 1.1062 + if (mXtClient.top_widget) { 1.1063 + xt_client_unrealize(&mXtClient); 1.1064 + xt_client_destroy(&mXtClient); 1.1065 + mXtClient.top_widget = nullptr; 1.1066 + } 1.1067 +#endif 1.1068 + 1.1069 + // We don't have to keep the plug-in window ID any longer. 1.1070 + mWindow.window = nullptr; 1.1071 +} 1.1072 +#endif 1.1073 + 1.1074 +bool 1.1075 +PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) 1.1076 +{ 1.1077 + PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)", 1.1078 + FULLFUNCTION, 1.1079 + aWindow.window, 1.1080 + aWindow.x, aWindow.y, 1.1081 + aWindow.width, aWindow.height)); 1.1082 + NS_ASSERTION(!mLayersRendering && !mPendingPluginCall, 1.1083 + "Shouldn't be receiving NPP_SetWindow with layer rendering"); 1.1084 + AssertPluginThread(); 1.1085 + 1.1086 +#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) 1.1087 + NS_ASSERTION(mWsInfo.display, "We should have a valid display!"); 1.1088 + 1.1089 + // The minimum info is sent over IPC to allow this 1.1090 + // code to determine the rest. 1.1091 + 1.1092 + mWindow.x = aWindow.x; 1.1093 + mWindow.y = aWindow.y; 1.1094 + mWindow.width = aWindow.width; 1.1095 + mWindow.height = aWindow.height; 1.1096 + mWindow.clipRect = aWindow.clipRect; 1.1097 + mWindow.type = aWindow.type; 1.1098 + 1.1099 + mWsInfo.colormap = aWindow.colormap; 1.1100 + int depth; 1.1101 + FindVisualAndDepth(mWsInfo.display, aWindow.visualID, 1.1102 + &mWsInfo.visual, &depth); 1.1103 + mWsInfo.depth = depth; 1.1104 + 1.1105 + if (!mWindow.window && mWindow.type == NPWindowTypeWindow) { 1.1106 + CreateWindow(aWindow); 1.1107 + } 1.1108 + 1.1109 +#if (MOZ_WIDGET_GTK == 2) 1.1110 + if (mXEmbed && gtk_check_version(2,18,7) != nullptr) { // older 1.1111 + if (aWindow.type == NPWindowTypeWindow) { 1.1112 + GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window)); 1.1113 + if (socket_window) { 1.1114 + // A GdkWindow for the socket already exists. Need to 1.1115 + // workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061 1.1116 + // See wrap_gtk_plug_embedded in PluginModuleChild.cpp. 1.1117 + g_object_set_data(G_OBJECT(socket_window), 1.1118 + "moz-existed-before-set-window", 1.1119 + GUINT_TO_POINTER(1)); 1.1120 + } 1.1121 + } 1.1122 + 1.1123 + if (aWindow.visualID != None 1.1124 + && gtk_check_version(2, 12, 10) != nullptr) { // older 1.1125 + // Workaround for a bug in Gtk+ (prior to 2.12.10) where deleting 1.1126 + // a foreign GdkColormap will also free the XColormap. 1.1127 + // http://git.gnome.org/browse/gtk+/log/gdk/x11/gdkcolor-x11.c?id=GTK_2_12_10 1.1128 + GdkVisual *gdkvisual = gdkx_visual_get(aWindow.visualID); 1.1129 + GdkColormap *gdkcolor = 1.1130 + gdk_x11_colormap_foreign_new(gdkvisual, aWindow.colormap); 1.1131 + 1.1132 + if (g_object_get_data(G_OBJECT(gdkcolor), "moz-have-extra-ref")) { 1.1133 + // We already have a ref to keep the object alive. 1.1134 + g_object_unref(gdkcolor); 1.1135 + } else { 1.1136 + // leak and mark as already leaked 1.1137 + g_object_set_data(G_OBJECT(gdkcolor), 1.1138 + "moz-have-extra-ref", GUINT_TO_POINTER(1)); 1.1139 + } 1.1140 + } 1.1141 + } 1.1142 +#endif 1.1143 + 1.1144 + PLUGIN_LOG_DEBUG( 1.1145 + ("[InstanceChild][%p] Answer_SetWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>", 1.1146 + this, mWindow.x, mWindow.y, mWindow.width, mWindow.height, 1.1147 + mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom)); 1.1148 + 1.1149 + if (mPluginIface->setwindow) 1.1150 + (void) mPluginIface->setwindow(&mData, &mWindow); 1.1151 + 1.1152 +#elif defined(OS_WIN) 1.1153 + switch (aWindow.type) { 1.1154 + case NPWindowTypeWindow: 1.1155 + { 1.1156 + if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) && 1.1157 + aWindow.width == 0 && 1.1158 + aWindow.height == 0) { 1.1159 + // Skip SetWindow call for hidden QuickTime plugins 1.1160 + return true; 1.1161 + } 1.1162 + 1.1163 + if (!CreatePluginWindow()) 1.1164 + return false; 1.1165 + 1.1166 + ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window)); 1.1167 + SizePluginWindow(aWindow.width, aWindow.height); 1.1168 + 1.1169 + mWindow.window = (void*)mPluginWindowHWND; 1.1170 + mWindow.x = aWindow.x; 1.1171 + mWindow.y = aWindow.y; 1.1172 + mWindow.width = aWindow.width; 1.1173 + mWindow.height = aWindow.height; 1.1174 + mWindow.type = aWindow.type; 1.1175 + 1.1176 + if (mPluginIface->setwindow) { 1.1177 + SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1); 1.1178 + (void) mPluginIface->setwindow(&mData, &mWindow); 1.1179 + WNDPROC wndProc = reinterpret_cast<WNDPROC>( 1.1180 + GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC)); 1.1181 + if (wndProc != PluginWindowProc) { 1.1182 + mPluginWndProc = reinterpret_cast<WNDPROC>( 1.1183 + SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC, 1.1184 + reinterpret_cast<LONG_PTR>(PluginWindowProc))); 1.1185 + NS_ASSERTION(mPluginWndProc != PluginWindowProc, "WTF?"); 1.1186 + } 1.1187 + RemoveProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty); 1.1188 + HookSetWindowLongPtr(); 1.1189 + } 1.1190 + } 1.1191 + break; 1.1192 + 1.1193 + case NPWindowTypeDrawable: 1.1194 + mWindow.type = aWindow.type; 1.1195 + if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) 1.1196 + CreateWinlessPopupSurrogate(); 1.1197 + if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) 1.1198 + SetupFlashMsgThrottle(); 1.1199 + return SharedSurfaceSetWindow(aWindow); 1.1200 + break; 1.1201 + 1.1202 + default: 1.1203 + NS_NOTREACHED("Bad plugin window type."); 1.1204 + return false; 1.1205 + break; 1.1206 + } 1.1207 + 1.1208 +#elif defined(XP_MACOSX) 1.1209 + 1.1210 + mWindow.x = aWindow.x; 1.1211 + mWindow.y = aWindow.y; 1.1212 + mWindow.width = aWindow.width; 1.1213 + mWindow.height = aWindow.height; 1.1214 + mWindow.clipRect = aWindow.clipRect; 1.1215 + mWindow.type = aWindow.type; 1.1216 + mContentsScaleFactor = aWindow.contentsScaleFactor; 1.1217 + 1.1218 + if (mShContext) { 1.1219 + // Release the shared context so that it is reallocated 1.1220 + // with the new size. 1.1221 + ::CGContextRelease(mShContext); 1.1222 + mShContext = nullptr; 1.1223 + } 1.1224 + 1.1225 + if (mPluginIface->setwindow) 1.1226 + (void) mPluginIface->setwindow(&mData, &mWindow); 1.1227 + 1.1228 +#elif defined(ANDROID) 1.1229 + // TODO: Need Android impl 1.1230 +#elif defined(MOZ_WIDGET_QT) 1.1231 + // TODO: Need QT-nonX impl 1.1232 +#else 1.1233 +# error Implement me for your OS 1.1234 +#endif 1.1235 + 1.1236 + return true; 1.1237 +} 1.1238 + 1.1239 +bool 1.1240 +PluginInstanceChild::Initialize() 1.1241 +{ 1.1242 +#if (MOZ_WIDGET_GTK == 2) 1.1243 + NPError rv; 1.1244 + 1.1245 + if (mWsInfo.display) { 1.1246 + // Already initialized 1.1247 + return false; 1.1248 + } 1.1249 + 1.1250 + // Request for windowless plugins is set in newp(), before this call. 1.1251 + if (mWindow.type == NPWindowTypeWindow) { 1.1252 + AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(&mXEmbed, &rv); 1.1253 + 1.1254 + // Set up Xt loop for windowed plugins without XEmbed support 1.1255 + if (!mXEmbed) { 1.1256 + xt_client_xloop_create(); 1.1257 + } 1.1258 + } 1.1259 + 1.1260 + // Use default GTK display for XEmbed and windowless plugins 1.1261 + if (mXEmbed || mWindow.type != NPWindowTypeWindow) { 1.1262 + mWsInfo.display = DefaultXDisplay(); 1.1263 + } 1.1264 + else { 1.1265 + mWsInfo.display = xt_client_get_display(); 1.1266 + } 1.1267 +#endif 1.1268 + 1.1269 + return true; 1.1270 +} 1.1271 + 1.1272 +#if defined(OS_WIN) 1.1273 + 1.1274 +static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow"); 1.1275 +static const TCHAR kPluginInstanceChildProperty[] = TEXT("PluginInstanceChildProperty"); 1.1276 +static const TCHAR kFlashThrottleProperty[] = TEXT("MozillaFlashThrottleProperty"); 1.1277 + 1.1278 +// static 1.1279 +bool 1.1280 +PluginInstanceChild::RegisterWindowClass() 1.1281 +{ 1.1282 + static bool alreadyRegistered = false; 1.1283 + if (alreadyRegistered) 1.1284 + return true; 1.1285 + 1.1286 + alreadyRegistered = true; 1.1287 + 1.1288 + WNDCLASSEX wcex; 1.1289 + wcex.cbSize = sizeof(WNDCLASSEX); 1.1290 + wcex.style = CS_DBLCLKS; 1.1291 + wcex.lpfnWndProc = DummyWindowProc; 1.1292 + wcex.cbClsExtra = 0; 1.1293 + wcex.cbWndExtra = 0; 1.1294 + wcex.hInstance = GetModuleHandle(nullptr); 1.1295 + wcex.hIcon = 0; 1.1296 + wcex.hCursor = 0; 1.1297 + wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1); 1.1298 + wcex.lpszMenuName = 0; 1.1299 + wcex.lpszClassName = kWindowClassName; 1.1300 + wcex.hIconSm = 0; 1.1301 + 1.1302 + return RegisterClassEx(&wcex) ? true : false; 1.1303 +} 1.1304 + 1.1305 +bool 1.1306 +PluginInstanceChild::CreatePluginWindow() 1.1307 +{ 1.1308 + // already initialized 1.1309 + if (mPluginWindowHWND) 1.1310 + return true; 1.1311 + 1.1312 + if (!RegisterWindowClass()) 1.1313 + return false; 1.1314 + 1.1315 + mPluginWindowHWND = 1.1316 + CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING | 1.1317 + WS_EX_NOPARENTNOTIFY | // XXXbent Get rid of this! 1.1318 + WS_EX_RIGHTSCROLLBAR, 1.1319 + kWindowClassName, 0, 1.1320 + WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 1.1321 + 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0); 1.1322 + if (!mPluginWindowHWND) 1.1323 + return false; 1.1324 + if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this)) 1.1325 + return false; 1.1326 + 1.1327 + // Apparently some plugins require an ASCII WndProc. 1.1328 + SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC, 1.1329 + reinterpret_cast<LONG_PTR>(DefWindowProcA)); 1.1330 + 1.1331 + return true; 1.1332 +} 1.1333 + 1.1334 +void 1.1335 +PluginInstanceChild::DestroyPluginWindow() 1.1336 +{ 1.1337 + if (mPluginWindowHWND) { 1.1338 + // Unsubclass the window. 1.1339 + WNDPROC wndProc = reinterpret_cast<WNDPROC>( 1.1340 + GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC)); 1.1341 + // Removed prior to SetWindowLongPtr, see HookSetWindowLongPtr. 1.1342 + RemoveProp(mPluginWindowHWND, kPluginInstanceChildProperty); 1.1343 + if (wndProc == PluginWindowProc) { 1.1344 + NS_ASSERTION(mPluginWndProc, "Should have old proc here!"); 1.1345 + SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC, 1.1346 + reinterpret_cast<LONG_PTR>(mPluginWndProc)); 1.1347 + mPluginWndProc = 0; 1.1348 + } 1.1349 + DestroyWindow(mPluginWindowHWND); 1.1350 + mPluginWindowHWND = 0; 1.1351 + } 1.1352 +} 1.1353 + 1.1354 +void 1.1355 +PluginInstanceChild::ReparentPluginWindow(HWND hWndParent) 1.1356 +{ 1.1357 + if (hWndParent != mPluginParentHWND && IsWindow(hWndParent)) { 1.1358 + // Fix the child window's style to be a child window. 1.1359 + LONG_PTR style = GetWindowLongPtr(mPluginWindowHWND, GWL_STYLE); 1.1360 + style |= WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 1.1361 + style &= ~WS_POPUP; 1.1362 + SetWindowLongPtr(mPluginWindowHWND, GWL_STYLE, style); 1.1363 + 1.1364 + // Do the reparenting. 1.1365 + SetParent(mPluginWindowHWND, hWndParent); 1.1366 + 1.1367 + // Make sure we're visible. 1.1368 + ShowWindow(mPluginWindowHWND, SW_SHOWNA); 1.1369 + } 1.1370 + mPluginParentHWND = hWndParent; 1.1371 +} 1.1372 + 1.1373 +void 1.1374 +PluginInstanceChild::SizePluginWindow(int width, 1.1375 + int height) 1.1376 +{ 1.1377 + if (mPluginWindowHWND) { 1.1378 + mPluginSize.x = width; 1.1379 + mPluginSize.y = height; 1.1380 + SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height, 1.1381 + SWP_NOZORDER | SWP_NOREPOSITION); 1.1382 + } 1.1383 +} 1.1384 + 1.1385 +// See chromium's webplugin_delegate_impl.cc for explanation of this function. 1.1386 +// static 1.1387 +LRESULT CALLBACK 1.1388 +PluginInstanceChild::DummyWindowProc(HWND hWnd, 1.1389 + UINT message, 1.1390 + WPARAM wParam, 1.1391 + LPARAM lParam) 1.1392 +{ 1.1393 + return CallWindowProc(DefWindowProc, hWnd, message, wParam, lParam); 1.1394 +} 1.1395 + 1.1396 +// static 1.1397 +LRESULT CALLBACK 1.1398 +PluginInstanceChild::PluginWindowProc(HWND hWnd, 1.1399 + UINT message, 1.1400 + WPARAM wParam, 1.1401 + LPARAM lParam) 1.1402 +{ 1.1403 + return mozilla::CallWindowProcCrashProtected(PluginWindowProcInternal, hWnd, message, wParam, lParam); 1.1404 +} 1.1405 + 1.1406 +// static 1.1407 +LRESULT CALLBACK 1.1408 +PluginInstanceChild::PluginWindowProcInternal(HWND hWnd, 1.1409 + UINT message, 1.1410 + WPARAM wParam, 1.1411 + LPARAM lParam) 1.1412 +{ 1.1413 + NS_ASSERTION(!mozilla::ipc::MessageChannel::IsPumpingMessages(), 1.1414 + "Failed to prevent a nonqueued message from running!"); 1.1415 + PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>( 1.1416 + GetProp(hWnd, kPluginInstanceChildProperty)); 1.1417 + if (!self) { 1.1418 + NS_NOTREACHED("Badness!"); 1.1419 + return 0; 1.1420 + } 1.1421 + 1.1422 + NS_ASSERTION(self->mPluginWindowHWND == hWnd, "Wrong window!"); 1.1423 + NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Self-referential windowproc. Infinite recursion will happen soon."); 1.1424 + 1.1425 + // Adobe's shockwave positions the plugin window relative to the browser 1.1426 + // frame when it initializes. With oopp disabled, this wouldn't have an 1.1427 + // effect. With oopp, GeckoPluginWindow is a child of the parent plugin 1.1428 + // window, so the move offsets the child within the parent. Generally 1.1429 + // we don't want plugins moving or sizing our window, so we prevent these 1.1430 + // changes here. 1.1431 + if (message == WM_WINDOWPOSCHANGING) { 1.1432 + WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(lParam); 1.1433 + if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE))) { 1.1434 + pos->x = pos->y = 0; 1.1435 + pos->cx = self->mPluginSize.x; 1.1436 + pos->cy = self->mPluginSize.y; 1.1437 + LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam, 1.1438 + lParam); 1.1439 + pos->x = pos->y = 0; 1.1440 + pos->cx = self->mPluginSize.x; 1.1441 + pos->cy = self->mPluginSize.y; 1.1442 + return res; 1.1443 + } 1.1444 + } 1.1445 + 1.1446 + // The plugin received keyboard focus, let the parent know so the dom is up to date. 1.1447 + if (message == WM_MOUSEACTIVATE) 1.1448 + self->CallPluginFocusChange(true); 1.1449 + 1.1450 + // Prevent lockups due to plugins making rpc calls when the parent 1.1451 + // is making a synchronous SendMessage call to the child window. Add 1.1452 + // more messages as needed. 1.1453 + if ((InSendMessageEx(nullptr)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) { 1.1454 + switch(message) { 1.1455 + case WM_KILLFOCUS: 1.1456 + ReplyMessage(0); 1.1457 + break; 1.1458 + } 1.1459 + } 1.1460 + 1.1461 + if (message == WM_KILLFOCUS) 1.1462 + self->CallPluginFocusChange(false); 1.1463 + 1.1464 + if (message == WM_USER+1 && 1.1465 + (self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) { 1.1466 + self->FlashThrottleMessage(hWnd, message, wParam, lParam, true); 1.1467 + return 0; 1.1468 + } 1.1469 + 1.1470 + NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, 1.1471 + "Self-referential windowproc happened inside our hook proc. " 1.1472 + "Infinite recursion will happen soon."); 1.1473 + 1.1474 + LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam, 1.1475 + lParam); 1.1476 + 1.1477 + // Make sure capture is released by the child on mouse events. Fixes a 1.1478 + // problem with flash full screen mode mouse input. Appears to be 1.1479 + // caused by a bug in flash, since we are not setting the capture 1.1480 + // on the window. 1.1481 + if (message == WM_LBUTTONDOWN && 1.1482 + self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) { 1.1483 + wchar_t szClass[26]; 1.1484 + HWND hwnd = GetForegroundWindow(); 1.1485 + if (hwnd && GetClassNameW(hwnd, szClass, 1.1486 + sizeof(szClass)/sizeof(char16_t)) && 1.1487 + !wcscmp(szClass, kFlashFullscreenClass)) { 1.1488 + ReleaseCapture(); 1.1489 + SetFocus(hwnd); 1.1490 + } 1.1491 + } 1.1492 + 1.1493 + if (message == WM_CLOSE) 1.1494 + self->DestroyPluginWindow(); 1.1495 + 1.1496 + if (message == WM_NCDESTROY) 1.1497 + RemoveProp(hWnd, kPluginInstanceChildProperty); 1.1498 + 1.1499 + return res; 1.1500 +} 1.1501 + 1.1502 +/* set window long ptr hook for flash */ 1.1503 + 1.1504 +/* 1.1505 + * Flash will reset the subclass of our widget at various times. 1.1506 + * (Notably when entering and exiting full screen mode.) This 1.1507 + * occurs independent of the main plugin window event procedure. 1.1508 + * We trap these subclass calls to prevent our subclass hook from 1.1509 + * getting dropped. 1.1510 + * Note, ascii versions can be nixed once flash versions < 10.1 1.1511 + * are considered obsolete. 1.1512 + */ 1.1513 + 1.1514 +#ifdef _WIN64 1.1515 +typedef LONG_PTR 1.1516 + (WINAPI *User32SetWindowLongPtrA)(HWND hWnd, 1.1517 + int nIndex, 1.1518 + LONG_PTR dwNewLong); 1.1519 +typedef LONG_PTR 1.1520 + (WINAPI *User32SetWindowLongPtrW)(HWND hWnd, 1.1521 + int nIndex, 1.1522 + LONG_PTR dwNewLong); 1.1523 +static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr; 1.1524 +static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr; 1.1525 +#else 1.1526 +typedef LONG 1.1527 +(WINAPI *User32SetWindowLongA)(HWND hWnd, 1.1528 + int nIndex, 1.1529 + LONG dwNewLong); 1.1530 +typedef LONG 1.1531 +(WINAPI *User32SetWindowLongW)(HWND hWnd, 1.1532 + int nIndex, 1.1533 + LONG dwNewLong); 1.1534 +static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr; 1.1535 +static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr; 1.1536 +#endif 1.1537 + 1.1538 +extern LRESULT CALLBACK 1.1539 +NeuteredWindowProc(HWND hwnd, 1.1540 + UINT uMsg, 1.1541 + WPARAM wParam, 1.1542 + LPARAM lParam); 1.1543 + 1.1544 +const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc"; 1.1545 + 1.1546 +// static 1.1547 +bool 1.1548 +PluginInstanceChild::SetWindowLongHookCheck(HWND hWnd, 1.1549 + int nIndex, 1.1550 + LONG_PTR newLong) 1.1551 +{ 1.1552 + // Let this go through if it's not a subclass 1.1553 + if (nIndex != GWLP_WNDPROC || 1.1554 + // if it's not a subclassed plugin window 1.1555 + !GetProp(hWnd, kPluginInstanceChildProperty) || 1.1556 + // if we're not disabled 1.1557 + GetProp(hWnd, kPluginIgnoreSubclassProperty) || 1.1558 + // if the subclass is set to a known procedure 1.1559 + newLong == reinterpret_cast<LONG_PTR>(PluginWindowProc) || 1.1560 + newLong == reinterpret_cast<LONG_PTR>(NeuteredWindowProc) || 1.1561 + newLong == reinterpret_cast<LONG_PTR>(DefWindowProcA) || 1.1562 + newLong == reinterpret_cast<LONG_PTR>(DefWindowProcW) || 1.1563 + // if the subclass is a WindowsMessageLoop subclass restore 1.1564 + GetProp(hWnd, kOldWndProcProp)) 1.1565 + return true; 1.1566 + // prevent the subclass 1.1567 + return false; 1.1568 +} 1.1569 + 1.1570 +#ifdef _WIN64 1.1571 +LONG_PTR WINAPI 1.1572 +PluginInstanceChild::SetWindowLongPtrAHook(HWND hWnd, 1.1573 + int nIndex, 1.1574 + LONG_PTR newLong) 1.1575 +#else 1.1576 +LONG WINAPI 1.1577 +PluginInstanceChild::SetWindowLongAHook(HWND hWnd, 1.1578 + int nIndex, 1.1579 + LONG newLong) 1.1580 +#endif 1.1581 +{ 1.1582 + if (SetWindowLongHookCheck(hWnd, nIndex, newLong)) 1.1583 + return sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong); 1.1584 + 1.1585 + // Set flash's new subclass to get the result. 1.1586 + LONG_PTR proc = sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong); 1.1587 + 1.1588 + // We already checked this in SetWindowLongHookCheck 1.1589 + PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>( 1.1590 + GetProp(hWnd, kPluginInstanceChildProperty)); 1.1591 + 1.1592 + // Hook our subclass back up, just like we do on setwindow. 1.1593 + WNDPROC currentProc = 1.1594 + reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC)); 1.1595 + if (currentProc != PluginWindowProc) { 1.1596 + self->mPluginWndProc = 1.1597 + reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex, 1.1598 + reinterpret_cast<LONG_PTR>(PluginWindowProc))); 1.1599 + NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!"); 1.1600 + } 1.1601 + return proc; 1.1602 +} 1.1603 + 1.1604 +#ifdef _WIN64 1.1605 +LONG_PTR WINAPI 1.1606 +PluginInstanceChild::SetWindowLongPtrWHook(HWND hWnd, 1.1607 + int nIndex, 1.1608 + LONG_PTR newLong) 1.1609 +#else 1.1610 +LONG WINAPI 1.1611 +PluginInstanceChild::SetWindowLongWHook(HWND hWnd, 1.1612 + int nIndex, 1.1613 + LONG newLong) 1.1614 +#endif 1.1615 +{ 1.1616 + if (SetWindowLongHookCheck(hWnd, nIndex, newLong)) 1.1617 + return sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong); 1.1618 + 1.1619 + // Set flash's new subclass to get the result. 1.1620 + LONG_PTR proc = sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong); 1.1621 + 1.1622 + // We already checked this in SetWindowLongHookCheck 1.1623 + PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>( 1.1624 + GetProp(hWnd, kPluginInstanceChildProperty)); 1.1625 + 1.1626 + // Hook our subclass back up, just like we do on setwindow. 1.1627 + WNDPROC currentProc = 1.1628 + reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC)); 1.1629 + if (currentProc != PluginWindowProc) { 1.1630 + self->mPluginWndProc = 1.1631 + reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex, 1.1632 + reinterpret_cast<LONG_PTR>(PluginWindowProc))); 1.1633 + NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!"); 1.1634 + } 1.1635 + return proc; 1.1636 +} 1.1637 + 1.1638 +void 1.1639 +PluginInstanceChild::HookSetWindowLongPtr() 1.1640 +{ 1.1641 + if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_SETLONGPTR)) 1.1642 + return; 1.1643 + 1.1644 + sUser32Intercept.Init("user32.dll"); 1.1645 +#ifdef _WIN64 1.1646 + if (!sUser32SetWindowLongAHookStub) 1.1647 + sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook), 1.1648 + (void**) &sUser32SetWindowLongAHookStub); 1.1649 + if (!sUser32SetWindowLongWHookStub) 1.1650 + sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook), 1.1651 + (void**) &sUser32SetWindowLongWHookStub); 1.1652 +#else 1.1653 + if (!sUser32SetWindowLongAHookStub) 1.1654 + sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook), 1.1655 + (void**) &sUser32SetWindowLongAHookStub); 1.1656 + if (!sUser32SetWindowLongWHookStub) 1.1657 + sUser32Intercept.AddHook("SetWindowLongW", reinterpret_cast<intptr_t>(SetWindowLongWHook), 1.1658 + (void**) &sUser32SetWindowLongWHookStub); 1.1659 +#endif 1.1660 +} 1.1661 + 1.1662 +/* windowless track popup menu helpers */ 1.1663 + 1.1664 +BOOL 1.1665 +WINAPI 1.1666 +PluginInstanceChild::TrackPopupHookProc(HMENU hMenu, 1.1667 + UINT uFlags, 1.1668 + int x, 1.1669 + int y, 1.1670 + int nReserved, 1.1671 + HWND hWnd, 1.1672 + CONST RECT *prcRect) 1.1673 +{ 1.1674 + if (!sUser32TrackPopupMenuStub) { 1.1675 + NS_ERROR("TrackPopupMenu stub isn't set! Badness!"); 1.1676 + return 0; 1.1677 + } 1.1678 + 1.1679 + // Only change the parent when we know this is a context on the plugin 1.1680 + // surface within the browser. Prevents resetting the parent on child ui 1.1681 + // displayed by plugins that have working parent-child relationships. 1.1682 + wchar_t szClass[21]; 1.1683 + bool haveClass = GetClassNameW(hWnd, szClass, ArrayLength(szClass)); 1.1684 + if (!haveClass || 1.1685 + (wcscmp(szClass, L"MozillaWindowClass") && 1.1686 + wcscmp(szClass, L"SWFlash_Placeholder"))) { 1.1687 + // Unrecognized parent 1.1688 + return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved, 1.1689 + hWnd, prcRect); 1.1690 + } 1.1691 + 1.1692 + // Called on an unexpected event, warn. 1.1693 + if (!sWinlessPopupSurrogateHWND) { 1.1694 + NS_WARNING( 1.1695 + "Untraced TrackPopupHookProc call! Menu might not work right!"); 1.1696 + return sUser32TrackPopupMenuStub(hMenu, uFlags, x, y, nReserved, 1.1697 + hWnd, prcRect); 1.1698 + } 1.1699 + 1.1700 + HWND surrogateHwnd = sWinlessPopupSurrogateHWND; 1.1701 + sWinlessPopupSurrogateHWND = nullptr; 1.1702 + 1.1703 + // Popups that don't use TPM_RETURNCMD expect a final command message 1.1704 + // when an item is selected and the context closes. Since we replace 1.1705 + // the parent, we need to forward this back to the real parent so it 1.1706 + // can act on the menu item selected. 1.1707 + bool isRetCmdCall = (uFlags & TPM_RETURNCMD); 1.1708 + 1.1709 + DWORD res = sUser32TrackPopupMenuStub(hMenu, uFlags|TPM_RETURNCMD, x, y, 1.1710 + nReserved, surrogateHwnd, prcRect); 1.1711 + 1.1712 + if (!isRetCmdCall && res) { 1.1713 + SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(res, 0), 0); 1.1714 + } 1.1715 + 1.1716 + return res; 1.1717 +} 1.1718 + 1.1719 +void 1.1720 +PluginInstanceChild::InitPopupMenuHook() 1.1721 +{ 1.1722 + if (!(GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) || 1.1723 + sUser32TrackPopupMenuStub) 1.1724 + return; 1.1725 + 1.1726 + // Note, once WindowsDllInterceptor is initialized for a module, 1.1727 + // it remains initialized for that particular module for it's 1.1728 + // lifetime. Additional instances are needed if other modules need 1.1729 + // to be hooked. 1.1730 + if (!sUser32TrackPopupMenuStub) { 1.1731 + sUser32Intercept.Init("user32.dll"); 1.1732 + sUser32Intercept.AddHook("TrackPopupMenu", reinterpret_cast<intptr_t>(TrackPopupHookProc), 1.1733 + (void**) &sUser32TrackPopupMenuStub); 1.1734 + } 1.1735 +} 1.1736 + 1.1737 +void 1.1738 +PluginInstanceChild::CreateWinlessPopupSurrogate() 1.1739 +{ 1.1740 + // already initialized 1.1741 + if (mWinlessPopupSurrogateHWND) 1.1742 + return; 1.1743 + 1.1744 + HWND hwnd = nullptr; 1.1745 + NPError result; 1.1746 + if (!CallNPN_GetValue_NPNVnetscapeWindow(&hwnd, &result)) { 1.1747 + NS_ERROR("CallNPN_GetValue_NPNVnetscapeWindow failed."); 1.1748 + return; 1.1749 + } 1.1750 + 1.1751 + mWinlessPopupSurrogateHWND = 1.1752 + CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_CHILD, 1.1753 + 0, 0, 0, 0, hwnd, 0, GetModuleHandle(nullptr), 0); 1.1754 + if (!mWinlessPopupSurrogateHWND) { 1.1755 + NS_ERROR("CreateWindowEx failed for winless placeholder!"); 1.1756 + return; 1.1757 + } 1.1758 + return; 1.1759 +} 1.1760 + 1.1761 +void 1.1762 +PluginInstanceChild::DestroyWinlessPopupSurrogate() 1.1763 +{ 1.1764 + if (mWinlessPopupSurrogateHWND) 1.1765 + DestroyWindow(mWinlessPopupSurrogateHWND); 1.1766 + mWinlessPopupSurrogateHWND = nullptr; 1.1767 +} 1.1768 + 1.1769 +int16_t 1.1770 +PluginInstanceChild::WinlessHandleEvent(NPEvent& event) 1.1771 +{ 1.1772 + if (!mPluginIface->event) 1.1773 + return false; 1.1774 + 1.1775 + // Events that might generate nested event dispatch loops need 1.1776 + // special handling during delivery. 1.1777 + int16_t handled; 1.1778 + 1.1779 + HWND focusHwnd = nullptr; 1.1780 + 1.1781 + // TrackPopupMenu will fail if the parent window is not associated with 1.1782 + // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate 1.1783 + // parent created in the child process. 1.1784 + if ((GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default? 1.1785 + (event.event == WM_RBUTTONDOWN || // flash 1.1786 + event.event == WM_RBUTTONUP)) { // silverlight 1.1787 + sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND; 1.1788 + 1.1789 + // A little trick scrounged from chromium's code - set the focus 1.1790 + // to our surrogate parent so keyboard nav events go to the menu. 1.1791 + focusHwnd = SetFocus(mWinlessPopupSurrogateHWND); 1.1792 + } 1.1793 + 1.1794 + MessageLoop* loop = MessageLoop::current(); 1.1795 + AutoRestore<bool> modalLoop(loop->os_modal_loop()); 1.1796 + 1.1797 + handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event)); 1.1798 + 1.1799 + sWinlessPopupSurrogateHWND = nullptr; 1.1800 + 1.1801 + if (IsWindow(focusHwnd)) { 1.1802 + SetFocus(focusHwnd); 1.1803 + } 1.1804 + 1.1805 + return handled; 1.1806 +} 1.1807 + 1.1808 +/* windowless drawing helpers */ 1.1809 + 1.1810 +bool 1.1811 +PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow& aWindow) 1.1812 +{ 1.1813 + // If the surfaceHandle is empty, parent is telling us we can reuse our cached 1.1814 + // memory surface and hdc. Otherwise, we need to reset, usually due to a 1.1815 + // expanding plugin port size. 1.1816 + if (!aWindow.surfaceHandle) { 1.1817 + if (!mSharedSurfaceDib.IsValid()) { 1.1818 + return false; 1.1819 + } 1.1820 + } 1.1821 + else { 1.1822 + // Attach to the new shared surface parent handed us. 1.1823 + if (NS_FAILED(mSharedSurfaceDib.Attach((SharedDIB::Handle)aWindow.surfaceHandle, 1.1824 + aWindow.width, aWindow.height, false))) 1.1825 + return false; 1.1826 + // Free any alpha extraction resources if needed. This will be reset 1.1827 + // the next time it's used. 1.1828 + AlphaExtractCacheRelease(); 1.1829 + } 1.1830 + 1.1831 + // NPRemoteWindow's origin is the origin of our shared dib. 1.1832 + mWindow.x = aWindow.x; 1.1833 + mWindow.y = aWindow.y; 1.1834 + mWindow.width = aWindow.width; 1.1835 + mWindow.height = aWindow.height; 1.1836 + mWindow.type = aWindow.type; 1.1837 + 1.1838 + mWindow.window = reinterpret_cast<void*>(mSharedSurfaceDib.GetHDC()); 1.1839 + ::SetViewportOrgEx(mSharedSurfaceDib.GetHDC(), 1.1840 + -aWindow.x, -aWindow.y, nullptr); 1.1841 + 1.1842 + if (mPluginIface->setwindow) 1.1843 + mPluginIface->setwindow(&mData, &mWindow); 1.1844 + 1.1845 + return true; 1.1846 +} 1.1847 + 1.1848 +void 1.1849 +PluginInstanceChild::SharedSurfaceRelease() 1.1850 +{ 1.1851 + mSharedSurfaceDib.Close(); 1.1852 + AlphaExtractCacheRelease(); 1.1853 +} 1.1854 + 1.1855 +/* double pass cache buffer - (rarely) used in cases where alpha extraction 1.1856 + * occurs for windowless plugins. */ 1.1857 + 1.1858 +bool 1.1859 +PluginInstanceChild::AlphaExtractCacheSetup() 1.1860 +{ 1.1861 + AlphaExtractCacheRelease(); 1.1862 + 1.1863 + mAlphaExtract.hdc = ::CreateCompatibleDC(nullptr); 1.1864 + 1.1865 + if (!mAlphaExtract.hdc) 1.1866 + return false; 1.1867 + 1.1868 + BITMAPINFOHEADER bmih; 1.1869 + memset((void*)&bmih, 0, sizeof(BITMAPINFOHEADER)); 1.1870 + bmih.biSize = sizeof(BITMAPINFOHEADER); 1.1871 + bmih.biWidth = mWindow.width; 1.1872 + bmih.biHeight = mWindow.height; 1.1873 + bmih.biPlanes = 1; 1.1874 + bmih.biBitCount = 32; 1.1875 + bmih.biCompression = BI_RGB; 1.1876 + 1.1877 + void* ppvBits = nullptr; 1.1878 + mAlphaExtract.bmp = ::CreateDIBSection(mAlphaExtract.hdc, 1.1879 + (BITMAPINFO*)&bmih, 1.1880 + DIB_RGB_COLORS, 1.1881 + (void**)&ppvBits, 1.1882 + nullptr, 1.1883 + (unsigned long)sizeof(BITMAPINFOHEADER)); 1.1884 + if (!mAlphaExtract.bmp) 1.1885 + return false; 1.1886 + 1.1887 + DeleteObject(::SelectObject(mAlphaExtract.hdc, mAlphaExtract.bmp)); 1.1888 + return true; 1.1889 +} 1.1890 + 1.1891 +void 1.1892 +PluginInstanceChild::AlphaExtractCacheRelease() 1.1893 +{ 1.1894 + if (mAlphaExtract.bmp) 1.1895 + ::DeleteObject(mAlphaExtract.bmp); 1.1896 + 1.1897 + if (mAlphaExtract.hdc) 1.1898 + ::DeleteObject(mAlphaExtract.hdc); 1.1899 + 1.1900 + mAlphaExtract.bmp = nullptr; 1.1901 + mAlphaExtract.hdc = nullptr; 1.1902 +} 1.1903 + 1.1904 +void 1.1905 +PluginInstanceChild::UpdatePaintClipRect(RECT* aRect) 1.1906 +{ 1.1907 + if (aRect) { 1.1908 + // Update the clip rect on our internal hdc 1.1909 + HRGN clip = ::CreateRectRgnIndirect(aRect); 1.1910 + ::SelectClipRgn(mSharedSurfaceDib.GetHDC(), clip); 1.1911 + ::DeleteObject(clip); 1.1912 + } 1.1913 +} 1.1914 + 1.1915 +int16_t 1.1916 +PluginInstanceChild::SharedSurfacePaint(NPEvent& evcopy) 1.1917 +{ 1.1918 + if (!mPluginIface->event) 1.1919 + return false; 1.1920 + 1.1921 + RECT* pRect = reinterpret_cast<RECT*>(evcopy.lParam); 1.1922 + 1.1923 + switch(mAlphaExtract.doublePass) { 1.1924 + case RENDER_NATIVE: 1.1925 + // pass the internal hdc to the plugin 1.1926 + UpdatePaintClipRect(pRect); 1.1927 + evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC()); 1.1928 + return mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy)); 1.1929 + break; 1.1930 + case RENDER_BACK_ONE: 1.1931 + // Handle a double pass render used in alpha extraction for transparent 1.1932 + // plugins. (See nsObjectFrame and gfxWindowsNativeDrawing for details.) 1.1933 + // We render twice, once to the shared dib, and once to a cache which 1.1934 + // we copy back on a second paint. These paints can't be spread across 1.1935 + // multiple rpc messages as delays cause animation frame changes. 1.1936 + if (!mAlphaExtract.bmp && !AlphaExtractCacheSetup()) { 1.1937 + mAlphaExtract.doublePass = RENDER_NATIVE; 1.1938 + return false; 1.1939 + } 1.1940 + 1.1941 + // See gfxWindowsNativeDrawing, color order doesn't have to match. 1.1942 + UpdatePaintClipRect(pRect); 1.1943 + ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); 1.1944 + evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC()); 1.1945 + if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) { 1.1946 + mAlphaExtract.doublePass = RENDER_NATIVE; 1.1947 + return false; 1.1948 + } 1.1949 + 1.1950 + // Copy to cache. We render to shared dib so we don't have to call 1.1951 + // setwindow between calls (flash issue). 1.1952 + ::BitBlt(mAlphaExtract.hdc, 1.1953 + pRect->left, 1.1954 + pRect->top, 1.1955 + pRect->right - pRect->left, 1.1956 + pRect->bottom - pRect->top, 1.1957 + mSharedSurfaceDib.GetHDC(), 1.1958 + pRect->left, 1.1959 + pRect->top, 1.1960 + SRCCOPY); 1.1961 + 1.1962 + ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); 1.1963 + if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) { 1.1964 + mAlphaExtract.doublePass = RENDER_NATIVE; 1.1965 + return false; 1.1966 + } 1.1967 + mAlphaExtract.doublePass = RENDER_BACK_TWO; 1.1968 + return true; 1.1969 + break; 1.1970 + case RENDER_BACK_TWO: 1.1971 + // copy our cached surface back 1.1972 + UpdatePaintClipRect(pRect); 1.1973 + ::BitBlt(mSharedSurfaceDib.GetHDC(), 1.1974 + pRect->left, 1.1975 + pRect->top, 1.1976 + pRect->right - pRect->left, 1.1977 + pRect->bottom - pRect->top, 1.1978 + mAlphaExtract.hdc, 1.1979 + pRect->left, 1.1980 + pRect->top, 1.1981 + SRCCOPY); 1.1982 + mAlphaExtract.doublePass = RENDER_NATIVE; 1.1983 + return true; 1.1984 + break; 1.1985 + } 1.1986 + return false; 1.1987 +} 1.1988 + 1.1989 +/* flash msg throttling helpers */ 1.1990 + 1.1991 +// Flash has the unfortunate habit of flooding dispatch loops with custom 1.1992 +// windowing events they use for timing. We throttle these by dropping the 1.1993 +// delivery priority below any other event, including pending ipc io 1.1994 +// notifications. We do this for both windowed and windowless controls. 1.1995 +// Note flash's windowless msg window can last longer than our instance, 1.1996 +// so we try to unhook when the window is destroyed and in NPP_Destroy. 1.1997 + 1.1998 +void 1.1999 +PluginInstanceChild::UnhookWinlessFlashThrottle() 1.2000 +{ 1.2001 + // We may have already unhooked 1.2002 + if (!mWinlessThrottleOldWndProc) 1.2003 + return; 1.2004 + 1.2005 + WNDPROC tmpProc = mWinlessThrottleOldWndProc; 1.2006 + mWinlessThrottleOldWndProc = nullptr; 1.2007 + 1.2008 + NS_ASSERTION(mWinlessHiddenMsgHWND, 1.2009 + "Missing mWinlessHiddenMsgHWND w/subclass set??"); 1.2010 + 1.2011 + // reset the subclass 1.2012 + SetWindowLongPtr(mWinlessHiddenMsgHWND, GWLP_WNDPROC, 1.2013 + reinterpret_cast<LONG_PTR>(tmpProc)); 1.2014 + 1.2015 + // Remove our instance prop 1.2016 + RemoveProp(mWinlessHiddenMsgHWND, kFlashThrottleProperty); 1.2017 + mWinlessHiddenMsgHWND = nullptr; 1.2018 +} 1.2019 + 1.2020 +// static 1.2021 +LRESULT CALLBACK 1.2022 +PluginInstanceChild::WinlessHiddenFlashWndProc(HWND hWnd, 1.2023 + UINT message, 1.2024 + WPARAM wParam, 1.2025 + LPARAM lParam) 1.2026 +{ 1.2027 + PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>( 1.2028 + GetProp(hWnd, kFlashThrottleProperty)); 1.2029 + if (!self) { 1.2030 + NS_NOTREACHED("Badness!"); 1.2031 + return 0; 1.2032 + } 1.2033 + 1.2034 + NS_ASSERTION(self->mWinlessThrottleOldWndProc, 1.2035 + "Missing subclass procedure!!"); 1.2036 + 1.2037 + // Throttle 1.2038 + if (message == WM_USER+1) { 1.2039 + self->FlashThrottleMessage(hWnd, message, wParam, lParam, false); 1.2040 + return 0; 1.2041 + } 1.2042 + 1.2043 + // Unhook 1.2044 + if (message == WM_CLOSE || message == WM_NCDESTROY) { 1.2045 + WNDPROC tmpProc = self->mWinlessThrottleOldWndProc; 1.2046 + self->UnhookWinlessFlashThrottle(); 1.2047 + LRESULT res = CallWindowProc(tmpProc, hWnd, message, wParam, lParam); 1.2048 + return res; 1.2049 + } 1.2050 + 1.2051 + return CallWindowProc(self->mWinlessThrottleOldWndProc, 1.2052 + hWnd, message, wParam, lParam); 1.2053 +} 1.2054 + 1.2055 +// Enumerate all thread windows looking for flash's hidden message window. 1.2056 +// Once we find it, sub class it so we can throttle user msgs. 1.2057 +// static 1.2058 +BOOL CALLBACK 1.2059 +PluginInstanceChild::EnumThreadWindowsCallback(HWND hWnd, 1.2060 + LPARAM aParam) 1.2061 +{ 1.2062 + PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(aParam); 1.2063 + if (!self) { 1.2064 + NS_NOTREACHED("Enum befuddled!"); 1.2065 + return FALSE; 1.2066 + } 1.2067 + 1.2068 + wchar_t className[64]; 1.2069 + if (!GetClassNameW(hWnd, className, sizeof(className)/sizeof(char16_t))) 1.2070 + return TRUE; 1.2071 + 1.2072 + if (!wcscmp(className, L"SWFlash_PlaceholderX")) { 1.2073 + WNDPROC oldWndProc = 1.2074 + reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_WNDPROC)); 1.2075 + // Only set this if we haven't already. 1.2076 + if (oldWndProc != WinlessHiddenFlashWndProc) { 1.2077 + if (self->mWinlessThrottleOldWndProc) { 1.2078 + NS_WARNING("mWinlessThrottleWndProc already set???"); 1.2079 + return FALSE; 1.2080 + } 1.2081 + // Subsclass and store self as a property 1.2082 + self->mWinlessHiddenMsgHWND = hWnd; 1.2083 + self->mWinlessThrottleOldWndProc = 1.2084 + reinterpret_cast<WNDPROC>(SetWindowLongPtr(hWnd, GWLP_WNDPROC, 1.2085 + reinterpret_cast<LONG_PTR>(WinlessHiddenFlashWndProc))); 1.2086 + SetProp(hWnd, kFlashThrottleProperty, self); 1.2087 + NS_ASSERTION(self->mWinlessThrottleOldWndProc, 1.2088 + "SetWindowLongPtr failed?!"); 1.2089 + } 1.2090 + // Return no matter what once we find the right window. 1.2091 + return FALSE; 1.2092 + } 1.2093 + 1.2094 + return TRUE; 1.2095 +} 1.2096 + 1.2097 + 1.2098 +void 1.2099 +PluginInstanceChild::SetupFlashMsgThrottle() 1.2100 +{ 1.2101 + if (mWindow.type == NPWindowTypeDrawable) { 1.2102 + // Search for the flash hidden message window and subclass it. Only 1.2103 + // search for flash windows belonging to our ui thread! 1.2104 + if (mWinlessThrottleOldWndProc) 1.2105 + return; 1.2106 + EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsCallback, 1.2107 + reinterpret_cast<LPARAM>(this)); 1.2108 + } 1.2109 + else { 1.2110 + // Already setup through quirks and the subclass. 1.2111 + return; 1.2112 + } 1.2113 +} 1.2114 + 1.2115 +WNDPROC 1.2116 +PluginInstanceChild::FlashThrottleAsyncMsg::GetProc() 1.2117 +{ 1.2118 + if (mInstance) { 1.2119 + return mWindowed ? mInstance->mPluginWndProc : 1.2120 + mInstance->mWinlessThrottleOldWndProc; 1.2121 + } 1.2122 + return nullptr; 1.2123 +} 1.2124 + 1.2125 +void 1.2126 +PluginInstanceChild::FlashThrottleAsyncMsg::Run() 1.2127 +{ 1.2128 + RemoveFromAsyncList(); 1.2129 + 1.2130 + // GetProc() checks mInstance, and pulls the procedure from 1.2131 + // PluginInstanceChild. We don't transport sub-class procedure 1.2132 + // ptrs around in FlashThrottleAsyncMsg msgs. 1.2133 + if (!GetProc()) 1.2134 + return; 1.2135 + 1.2136 + // deliver the event to flash 1.2137 + CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam()); 1.2138 +} 1.2139 + 1.2140 +void 1.2141 +PluginInstanceChild::FlashThrottleMessage(HWND aWnd, 1.2142 + UINT aMsg, 1.2143 + WPARAM aWParam, 1.2144 + LPARAM aLParam, 1.2145 + bool isWindowed) 1.2146 +{ 1.2147 + // We reuse ChildAsyncCall so we get the cancelation work 1.2148 + // that's done in Destroy. 1.2149 + FlashThrottleAsyncMsg* task = new FlashThrottleAsyncMsg(this, 1.2150 + aWnd, aMsg, aWParam, aLParam, isWindowed); 1.2151 + if (!task) 1.2152 + return; 1.2153 + 1.2154 + { 1.2155 + MutexAutoLock lock(mAsyncCallMutex); 1.2156 + mPendingAsyncCalls.AppendElement(task); 1.2157 + } 1.2158 + MessageLoop::current()->PostDelayedTask(FROM_HERE, 1.2159 + task, kFlashWMUSERMessageThrottleDelayMs); 1.2160 +} 1.2161 + 1.2162 +#endif // OS_WIN 1.2163 + 1.2164 +bool 1.2165 +PluginInstanceChild::AnswerSetPluginFocus() 1.2166 +{ 1.2167 + PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION)); 1.2168 + 1.2169 +#if defined(OS_WIN) 1.2170 + // Parent is letting us know the dom set focus to the plugin. Note, 1.2171 + // focus can change during transit in certain edge cases, for example 1.2172 + // when a button click brings up a full screen window. Since we send 1.2173 + // this in response to a WM_SETFOCUS event on our parent, the parent 1.2174 + // should have focus when we receive this. If not, ignore the call. 1.2175 + if (::GetFocus() == mPluginWindowHWND || 1.2176 + ((GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) && 1.2177 + (::GetFocus() != mPluginParentHWND))) 1.2178 + return true; 1.2179 + ::SetFocus(mPluginWindowHWND); 1.2180 + return true; 1.2181 +#else 1.2182 + NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!"); 1.2183 + return false; 1.2184 +#endif 1.2185 +} 1.2186 + 1.2187 +bool 1.2188 +PluginInstanceChild::AnswerUpdateWindow() 1.2189 +{ 1.2190 + PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION)); 1.2191 + 1.2192 +#if defined(OS_WIN) 1.2193 + if (mPluginWindowHWND) { 1.2194 + RECT rect; 1.2195 + if (GetUpdateRect(GetParent(mPluginWindowHWND), &rect, FALSE)) { 1.2196 + ::InvalidateRect(mPluginWindowHWND, &rect, FALSE); 1.2197 + } 1.2198 + UpdateWindow(mPluginWindowHWND); 1.2199 + } 1.2200 + return true; 1.2201 +#else 1.2202 + NS_NOTREACHED("PluginInstanceChild::AnswerUpdateWindow not implemented!"); 1.2203 + return false; 1.2204 +#endif 1.2205 +} 1.2206 + 1.2207 +bool 1.2208 +PluginInstanceChild::RecvNPP_DidComposite() 1.2209 +{ 1.2210 + if (mPluginIface->didComposite) { 1.2211 + mPluginIface->didComposite(GetNPP()); 1.2212 + } 1.2213 + return true; 1.2214 +} 1.2215 + 1.2216 +PPluginScriptableObjectChild* 1.2217 +PluginInstanceChild::AllocPPluginScriptableObjectChild() 1.2218 +{ 1.2219 + AssertPluginThread(); 1.2220 + return new PluginScriptableObjectChild(Proxy); 1.2221 +} 1.2222 + 1.2223 +bool 1.2224 +PluginInstanceChild::DeallocPPluginScriptableObjectChild( 1.2225 + PPluginScriptableObjectChild* aObject) 1.2226 +{ 1.2227 + AssertPluginThread(); 1.2228 + delete aObject; 1.2229 + return true; 1.2230 +} 1.2231 + 1.2232 +bool 1.2233 +PluginInstanceChild::RecvPPluginScriptableObjectConstructor( 1.2234 + PPluginScriptableObjectChild* aActor) 1.2235 +{ 1.2236 + AssertPluginThread(); 1.2237 + 1.2238 + // This is only called in response to the parent process requesting the 1.2239 + // creation of an actor. This actor will represent an NPObject that is 1.2240 + // created by the browser and returned to the plugin. 1.2241 + PluginScriptableObjectChild* actor = 1.2242 + static_cast<PluginScriptableObjectChild*>(aActor); 1.2243 + NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!"); 1.2244 + 1.2245 + actor->InitializeProxy(); 1.2246 + NS_ASSERTION(actor->GetObject(false), "Actor should have an object!"); 1.2247 + 1.2248 + return true; 1.2249 +} 1.2250 + 1.2251 +bool 1.2252 +PluginInstanceChild::AnswerPBrowserStreamConstructor( 1.2253 + PBrowserStreamChild* aActor, 1.2254 + const nsCString& url, 1.2255 + const uint32_t& length, 1.2256 + const uint32_t& lastmodified, 1.2257 + PStreamNotifyChild* notifyData, 1.2258 + const nsCString& headers, 1.2259 + const nsCString& mimeType, 1.2260 + const bool& seekable, 1.2261 + NPError* rv, 1.2262 + uint16_t* stype) 1.2263 +{ 1.2264 + AssertPluginThread(); 1.2265 + *rv = static_cast<BrowserStreamChild*>(aActor) 1.2266 + ->StreamConstructed(mimeType, seekable, stype); 1.2267 + return true; 1.2268 +} 1.2269 + 1.2270 +PBrowserStreamChild* 1.2271 +PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url, 1.2272 + const uint32_t& length, 1.2273 + const uint32_t& lastmodified, 1.2274 + PStreamNotifyChild* notifyData, 1.2275 + const nsCString& headers, 1.2276 + const nsCString& mimeType, 1.2277 + const bool& seekable, 1.2278 + NPError* rv, 1.2279 + uint16_t *stype) 1.2280 +{ 1.2281 + AssertPluginThread(); 1.2282 + return new BrowserStreamChild(this, url, length, lastmodified, 1.2283 + static_cast<StreamNotifyChild*>(notifyData), 1.2284 + headers, mimeType, seekable, rv, stype); 1.2285 +} 1.2286 + 1.2287 +bool 1.2288 +PluginInstanceChild::DeallocPBrowserStreamChild(PBrowserStreamChild* stream) 1.2289 +{ 1.2290 + AssertPluginThread(); 1.2291 + delete stream; 1.2292 + return true; 1.2293 +} 1.2294 + 1.2295 +PPluginStreamChild* 1.2296 +PluginInstanceChild::AllocPPluginStreamChild(const nsCString& mimeType, 1.2297 + const nsCString& target, 1.2298 + NPError* result) 1.2299 +{ 1.2300 + NS_RUNTIMEABORT("not callable"); 1.2301 + return nullptr; 1.2302 +} 1.2303 + 1.2304 +bool 1.2305 +PluginInstanceChild::DeallocPPluginStreamChild(PPluginStreamChild* stream) 1.2306 +{ 1.2307 + AssertPluginThread(); 1.2308 + delete stream; 1.2309 + return true; 1.2310 +} 1.2311 + 1.2312 +PStreamNotifyChild* 1.2313 +PluginInstanceChild::AllocPStreamNotifyChild(const nsCString& url, 1.2314 + const nsCString& target, 1.2315 + const bool& post, 1.2316 + const nsCString& buffer, 1.2317 + const bool& file, 1.2318 + NPError* result) 1.2319 +{ 1.2320 + AssertPluginThread(); 1.2321 + NS_RUNTIMEABORT("not reached"); 1.2322 + return nullptr; 1.2323 +} 1.2324 + 1.2325 +void 1.2326 +StreamNotifyChild::ActorDestroy(ActorDestroyReason why) 1.2327 +{ 1.2328 + if (AncestorDeletion == why && mBrowserStream) { 1.2329 + NS_ERROR("Pending NPP_URLNotify not called when closing an instance."); 1.2330 + 1.2331 + // reclaim responsibility for deleting ourself 1.2332 + mBrowserStream->mStreamNotify = nullptr; 1.2333 + mBrowserStream = nullptr; 1.2334 + } 1.2335 +} 1.2336 + 1.2337 + 1.2338 +void 1.2339 +StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs) 1.2340 +{ 1.2341 + NS_ASSERTION(bs, "Shouldn't be null"); 1.2342 + NS_ASSERTION(!mBrowserStream, "Two streams for one streamnotify?"); 1.2343 + 1.2344 + mBrowserStream = bs; 1.2345 +} 1.2346 + 1.2347 +bool 1.2348 +StreamNotifyChild::Recv__delete__(const NPReason& reason) 1.2349 +{ 1.2350 + AssertPluginThread(); 1.2351 + 1.2352 + if (mBrowserStream) 1.2353 + mBrowserStream->NotifyPending(); 1.2354 + else 1.2355 + NPP_URLNotify(reason); 1.2356 + 1.2357 + return true; 1.2358 +} 1.2359 + 1.2360 +bool 1.2361 +StreamNotifyChild::RecvRedirectNotify(const nsCString& url, const int32_t& status) 1.2362 +{ 1.2363 + // NPP_URLRedirectNotify requires a non-null closure. Since core logic 1.2364 + // assumes that all out-of-process notify streams have non-null closure 1.2365 + // data it will assume that the plugin was notified at this point and 1.2366 + // expect a response otherwise the redirect will hang indefinitely. 1.2367 + if (!mClosure) { 1.2368 + SendRedirectNotifyResponse(false); 1.2369 + } 1.2370 + 1.2371 + PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager()); 1.2372 + if (instance->mPluginIface->urlredirectnotify) 1.2373 + instance->mPluginIface->urlredirectnotify(instance->GetNPP(), url.get(), status, mClosure); 1.2374 + 1.2375 + return true; 1.2376 +} 1.2377 + 1.2378 +void 1.2379 +StreamNotifyChild::NPP_URLNotify(NPReason reason) 1.2380 +{ 1.2381 + PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager()); 1.2382 + 1.2383 + if (mClosure) 1.2384 + instance->mPluginIface->urlnotify(instance->GetNPP(), mURL.get(), 1.2385 + reason, mClosure); 1.2386 +} 1.2387 + 1.2388 +bool 1.2389 +PluginInstanceChild::DeallocPStreamNotifyChild(PStreamNotifyChild* notifyData) 1.2390 +{ 1.2391 + AssertPluginThread(); 1.2392 + 1.2393 + if (!static_cast<StreamNotifyChild*>(notifyData)->mBrowserStream) 1.2394 + delete notifyData; 1.2395 + return true; 1.2396 +} 1.2397 + 1.2398 +PluginScriptableObjectChild* 1.2399 +PluginInstanceChild::GetActorForNPObject(NPObject* aObject) 1.2400 +{ 1.2401 + AssertPluginThread(); 1.2402 + NS_ASSERTION(aObject, "Null pointer!"); 1.2403 + 1.2404 + if (aObject->_class == PluginScriptableObjectChild::GetClass()) { 1.2405 + // One of ours! It's a browser-provided object. 1.2406 + ChildNPObject* object = static_cast<ChildNPObject*>(aObject); 1.2407 + NS_ASSERTION(object->parent, "Null actor!"); 1.2408 + return object->parent; 1.2409 + } 1.2410 + 1.2411 + PluginScriptableObjectChild* actor = 1.2412 + PluginModuleChild::current()->GetActorForNPObject(aObject); 1.2413 + if (actor) { 1.2414 + // Plugin-provided object that we've previously wrapped. 1.2415 + return actor; 1.2416 + } 1.2417 + 1.2418 + actor = new PluginScriptableObjectChild(LocalObject); 1.2419 + if (!SendPPluginScriptableObjectConstructor(actor)) { 1.2420 + NS_ERROR("Failed to send constructor message!"); 1.2421 + return nullptr; 1.2422 + } 1.2423 + 1.2424 + actor->InitializeLocal(aObject); 1.2425 + return actor; 1.2426 +} 1.2427 + 1.2428 +NPError 1.2429 +PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow, 1.2430 + NPStream** aStream) 1.2431 +{ 1.2432 + AssertPluginThread(); 1.2433 + 1.2434 + PluginStreamChild* ps = new PluginStreamChild(); 1.2435 + 1.2436 + NPError result; 1.2437 + CallPPluginStreamConstructor(ps, nsDependentCString(aMIMEType), 1.2438 + NullableString(aWindow), &result); 1.2439 + if (NPERR_NO_ERROR != result) { 1.2440 + *aStream = nullptr; 1.2441 + PPluginStreamChild::Call__delete__(ps, NPERR_GENERIC_ERROR, true); 1.2442 + return result; 1.2443 + } 1.2444 + 1.2445 + *aStream = &ps->mStream; 1.2446 + return NPERR_NO_ERROR; 1.2447 +} 1.2448 + 1.2449 +void 1.2450 +PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData, NPBool allow) 1.2451 +{ 1.2452 + if (!notifyData) { 1.2453 + return; 1.2454 + } 1.2455 + 1.2456 + InfallibleTArray<PStreamNotifyChild*> notifyStreams; 1.2457 + ManagedPStreamNotifyChild(notifyStreams); 1.2458 + uint32_t notifyStreamCount = notifyStreams.Length(); 1.2459 + for (uint32_t i = 0; i < notifyStreamCount; i++) { 1.2460 + StreamNotifyChild* sn = static_cast<StreamNotifyChild*>(notifyStreams[i]); 1.2461 + if (sn->mClosure == notifyData) { 1.2462 + sn->SendRedirectNotifyResponse(static_cast<bool>(allow)); 1.2463 + return; 1.2464 + } 1.2465 + } 1.2466 + NS_ASSERTION(false, "Couldn't find stream for redirect response!"); 1.2467 +} 1.2468 + 1.2469 +NPError 1.2470 +PluginInstanceChild::DeallocateAsyncBitmapSurface(NPAsyncSurface *aSurface) 1.2471 +{ 1.2472 + AsyncBitmapData* data; 1.2473 + 1.2474 + if (!mAsyncBitmaps.Get(aSurface, &data)) { 1.2475 + return NPERR_INVALID_PARAM; 1.2476 + } 1.2477 + 1.2478 + DeallocShmem(data->mShmem); 1.2479 + aSurface->bitmap.data = nullptr; 1.2480 + 1.2481 + mAsyncBitmaps.Remove(aSurface); 1.2482 + return NPERR_NO_ERROR; 1.2483 +} 1.2484 + 1.2485 +bool 1.2486 +PluginInstanceChild::IsAsyncDrawing() 1.2487 +{ 1.2488 + return IsDrawingModelAsync(mDrawingModel); 1.2489 +} 1.2490 + 1.2491 +NPError 1.2492 +PluginInstanceChild::NPN_InitAsyncSurface(NPSize *size, NPImageFormat format, 1.2493 + void *initData, NPAsyncSurface *surface) 1.2494 +{ 1.2495 + AssertPluginThread(); 1.2496 + 1.2497 + surface->bitmap.data = nullptr; 1.2498 + 1.2499 + if (!IsAsyncDrawing()) { 1.2500 + return NPERR_GENERIC_ERROR; 1.2501 + } 1.2502 + 1.2503 + switch (mDrawingModel) { 1.2504 + case NPDrawingModelAsyncBitmapSurface: { 1.2505 + if (mAsyncBitmaps.Get(surface, nullptr)) { 1.2506 + return NPERR_INVALID_PARAM; 1.2507 + } 1.2508 + 1.2509 + if (size->width < 0 || size->height < 0) { 1.2510 + return NPERR_INVALID_PARAM; 1.2511 + } 1.2512 + 1.2513 + 1.2514 + bool result; 1.2515 + NPRemoteAsyncSurface remote; 1.2516 + 1.2517 + if (!CallNPN_InitAsyncSurface(gfxIntSize(size->width, size->height), format, &remote, &result) || !result) { 1.2518 + return NPERR_OUT_OF_MEMORY_ERROR; 1.2519 + } 1.2520 + 1.2521 + NS_ABORT_IF_FALSE(remote.data().get_Shmem().IsWritable(), 1.2522 + "Failed to create writable shared memory."); 1.2523 + 1.2524 + AsyncBitmapData *data = new AsyncBitmapData; 1.2525 + mAsyncBitmaps.Put(surface, data); 1.2526 + 1.2527 + data->mRemotePtr = (void*)remote.hostPtr(); 1.2528 + data->mShmem = remote.data().get_Shmem(); 1.2529 + 1.2530 + surface->bitmap.data = data->mShmem.get<unsigned char>(); 1.2531 + surface->bitmap.stride = remote.stride(); 1.2532 + surface->format = remote.format(); 1.2533 + surface->size.width = remote.size().width; 1.2534 + surface->size.height = remote.size().height; 1.2535 + 1.2536 + return NPERR_NO_ERROR; 1.2537 + } 1.2538 +#ifdef XP_WIN 1.2539 + case NPDrawingModelAsyncWindowsDXGISurface: { 1.2540 + if (size->width < 0 || size->height < 0) { 1.2541 + return NPERR_INVALID_PARAM; 1.2542 + } 1.2543 + bool result; 1.2544 + NPRemoteAsyncSurface remote; 1.2545 + 1.2546 + if (!CallNPN_InitAsyncSurface(gfxIntSize(size->width, size->height), format, &remote, &result) || !result) { 1.2547 + return NPERR_OUT_OF_MEMORY_ERROR; 1.2548 + } 1.2549 + 1.2550 + surface->format = remote.format(); 1.2551 + surface->size.width = remote.size().width; 1.2552 + surface->size.height = remote.size().height; 1.2553 + surface->sharedHandle = remote.data().get_DXGISharedSurfaceHandle(); 1.2554 + 1.2555 + return NPERR_NO_ERROR; 1.2556 + } 1.2557 +#endif 1.2558 + } 1.2559 + 1.2560 + return NPERR_GENERIC_ERROR; 1.2561 +} 1.2562 + 1.2563 +NPError 1.2564 +PluginInstanceChild::NPN_FinalizeAsyncSurface(NPAsyncSurface *surface) 1.2565 +{ 1.2566 + AssertPluginThread(); 1.2567 + 1.2568 + if (!IsAsyncDrawing()) { 1.2569 + return NPERR_GENERIC_ERROR; 1.2570 + } 1.2571 + 1.2572 + switch (mDrawingModel) { 1.2573 + case NPDrawingModelAsyncBitmapSurface: { 1.2574 + AsyncBitmapData *bitmapData; 1.2575 + 1.2576 + if (!mAsyncBitmaps.Get(surface, &bitmapData)) { 1.2577 + return NPERR_GENERIC_ERROR; 1.2578 + } 1.2579 + 1.2580 + { 1.2581 + CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex); 1.2582 + RemoteImageData *data = mRemoteImageData; 1.2583 + if (data->mBitmap.mData == bitmapData->mRemotePtr) { 1.2584 + data->mBitmap.mData = nullptr; 1.2585 + data->mSize = IntSize(0, 0); 1.2586 + data->mWasUpdated = true; 1.2587 + } 1.2588 + } 1.2589 + 1.2590 + return DeallocateAsyncBitmapSurface(surface); 1.2591 + } 1.2592 +#ifdef XP_WIN 1.2593 + case NPDrawingModelAsyncWindowsDXGISurface: { 1.2594 + 1.2595 + { 1.2596 + CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex); 1.2597 + RemoteImageData *data = mRemoteImageData; 1.2598 + if (data->mTextureHandle == surface->sharedHandle) { 1.2599 + data->mTextureHandle = nullptr; 1.2600 + data->mSize = IntSize(0, 0); 1.2601 + data->mWasUpdated = true; 1.2602 + } 1.2603 + } 1.2604 + 1.2605 + SendReleaseDXGISharedSurface(surface->sharedHandle); 1.2606 + return NPERR_NO_ERROR; 1.2607 + } 1.2608 +#endif 1.2609 + } 1.2610 + 1.2611 + return NPERR_GENERIC_ERROR; 1.2612 +} 1.2613 + 1.2614 +void 1.2615 +PluginInstanceChild::NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) 1.2616 +{ 1.2617 + if (!IsAsyncDrawing()) { 1.2618 + return; 1.2619 + } 1.2620 + 1.2621 + RemoteImageData *data = mRemoteImageData; 1.2622 + 1.2623 + if (!surface) { 1.2624 + CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex); 1.2625 + data->mBitmap.mData = nullptr; 1.2626 + data->mSize = IntSize(0, 0); 1.2627 + data->mWasUpdated = true; 1.2628 + } else { 1.2629 + switch (mDrawingModel) { 1.2630 + case NPDrawingModelAsyncBitmapSurface: 1.2631 + { 1.2632 + AsyncBitmapData *bitmapData; 1.2633 + 1.2634 + if (!mAsyncBitmaps.Get(surface, &bitmapData)) { 1.2635 + return; 1.2636 + } 1.2637 + 1.2638 + CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex); 1.2639 + data->mBitmap.mData = (unsigned char*)bitmapData->mRemotePtr; 1.2640 + data->mSize = IntSize(surface->size.width, surface->size.height); 1.2641 + data->mFormat = surface->format == NPImageFormatBGRX32 ? 1.2642 + RemoteImageData::BGRX32 : RemoteImageData::BGRA32; 1.2643 + data->mBitmap.mStride = surface->bitmap.stride; 1.2644 + data->mWasUpdated = true; 1.2645 + break; 1.2646 + } 1.2647 +#ifdef XP_WIN 1.2648 + case NPDrawingModelAsyncWindowsDXGISurface: 1.2649 + { 1.2650 + CrossProcessMutexAutoLock autoLock(*mRemoteImageDataMutex); 1.2651 + data->mType = RemoteImageData::DXGI_TEXTURE_HANDLE; 1.2652 + data->mSize = IntSize(surface->size.width, surface->size.height); 1.2653 + data->mFormat = surface->format == NPImageFormatBGRX32 ? 1.2654 + RemoteImageData::BGRX32 : RemoteImageData::BGRA32; 1.2655 + data->mTextureHandle = surface->sharedHandle; 1.2656 + 1.2657 + data->mWasUpdated = true; 1.2658 + break; 1.2659 + } 1.2660 +#endif 1.2661 + } 1.2662 + } 1.2663 + 1.2664 + { 1.2665 + MutexAutoLock autoLock(mAsyncInvalidateMutex); 1.2666 + if (!mAsyncInvalidateTask) { 1.2667 + mAsyncInvalidateTask = 1.2668 + NewRunnableMethod<PluginInstanceChild, void (PluginInstanceChild::*)()> 1.2669 + (this, &PluginInstanceChild::DoAsyncRedraw); 1.2670 + ProcessChild::message_loop()->PostTask(FROM_HERE, mAsyncInvalidateTask); 1.2671 + } 1.2672 + } 1.2673 +} 1.2674 + 1.2675 +void 1.2676 +PluginInstanceChild::DoAsyncRedraw() 1.2677 +{ 1.2678 + { 1.2679 + MutexAutoLock autoLock(mAsyncInvalidateMutex); 1.2680 + mAsyncInvalidateTask = nullptr; 1.2681 + } 1.2682 + 1.2683 + SendRedrawPlugin(); 1.2684 +} 1.2685 + 1.2686 +bool 1.2687 +PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType, 1.2688 + const NPRemoteWindow& aWindow) 1.2689 +{ 1.2690 + AssertPluginThread(); 1.2691 + 1.2692 + NS_ASSERTION(!aWindow.window, "Remote window should be null."); 1.2693 + 1.2694 + if (mCurrentAsyncSetWindowTask) { 1.2695 + mCurrentAsyncSetWindowTask->Cancel(); 1.2696 + mCurrentAsyncSetWindowTask = nullptr; 1.2697 + } 1.2698 + 1.2699 + // We shouldn't process this now because it may be received within a nested 1.2700 + // RPC call, and both Flash and Java don't expect to receive setwindow calls 1.2701 + // at arbitrary times. 1.2702 + mCurrentAsyncSetWindowTask = 1.2703 + NewRunnableMethod<PluginInstanceChild, 1.2704 + void (PluginInstanceChild::*)(const gfxSurfaceType&, const NPRemoteWindow&, bool), 1.2705 + gfxSurfaceType, NPRemoteWindow, bool> 1.2706 + (this, &PluginInstanceChild::DoAsyncSetWindow, 1.2707 + aSurfaceType, aWindow, true); 1.2708 + MessageLoop::current()->PostTask(FROM_HERE, mCurrentAsyncSetWindowTask); 1.2709 + 1.2710 + return true; 1.2711 +} 1.2712 + 1.2713 +void 1.2714 +PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType, 1.2715 + const NPRemoteWindow& aWindow, 1.2716 + bool aIsAsync) 1.2717 +{ 1.2718 + PLUGIN_LOG_DEBUG( 1.2719 + ("[InstanceChild][%p] AsyncSetWindow to <x=%d,y=%d, w=%d,h=%d>", 1.2720 + this, aWindow.x, aWindow.y, aWindow.width, aWindow.height)); 1.2721 + 1.2722 + AssertPluginThread(); 1.2723 + NS_ASSERTION(!aWindow.window, "Remote window should be null."); 1.2724 + NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!"); 1.2725 + 1.2726 + if (aIsAsync) { 1.2727 + if (!mCurrentAsyncSetWindowTask) { 1.2728 + return; 1.2729 + } 1.2730 + mCurrentAsyncSetWindowTask = nullptr; 1.2731 + } 1.2732 + 1.2733 + mWindow.window = nullptr; 1.2734 + if (mWindow.width != aWindow.width || mWindow.height != aWindow.height || 1.2735 + mWindow.clipRect.top != aWindow.clipRect.top || 1.2736 + mWindow.clipRect.left != aWindow.clipRect.left || 1.2737 + mWindow.clipRect.bottom != aWindow.clipRect.bottom || 1.2738 + mWindow.clipRect.right != aWindow.clipRect.right) 1.2739 + mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height); 1.2740 + 1.2741 + mWindow.x = aWindow.x; 1.2742 + mWindow.y = aWindow.y; 1.2743 + mWindow.width = aWindow.width; 1.2744 + mWindow.height = aWindow.height; 1.2745 + mWindow.clipRect = aWindow.clipRect; 1.2746 + mWindow.type = aWindow.type; 1.2747 +#ifdef XP_MACOSX 1.2748 + mContentsScaleFactor = aWindow.contentsScaleFactor; 1.2749 +#endif 1.2750 + 1.2751 + if (GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT) 1.2752 + mIsTransparent = true; 1.2753 + 1.2754 + mLayersRendering = true; 1.2755 + mSurfaceType = aSurfaceType; 1.2756 + UpdateWindowAttributes(true); 1.2757 + 1.2758 +#ifdef XP_WIN 1.2759 + if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) 1.2760 + CreateWinlessPopupSurrogate(); 1.2761 + if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) 1.2762 + SetupFlashMsgThrottle(); 1.2763 +#endif 1.2764 + 1.2765 + if (!mAccumulatedInvalidRect.IsEmpty()) { 1.2766 + AsyncShowPluginFrame(); 1.2767 + } 1.2768 +} 1.2769 + 1.2770 +static inline gfxRect 1.2771 +GfxFromNsRect(const nsIntRect& aRect) 1.2772 +{ 1.2773 + return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height); 1.2774 +} 1.2775 + 1.2776 +bool 1.2777 +PluginInstanceChild::CreateOptSurface(void) 1.2778 +{ 1.2779 + NS_ABORT_IF_FALSE(mSurfaceType != gfxSurfaceType::Max, 1.2780 + "Need a valid surface type here"); 1.2781 + NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync."); 1.2782 + 1.2783 + nsRefPtr<gfxASurface> retsurf; 1.2784 + // Use an opaque surface unless we're transparent and *don't* have 1.2785 + // a background to source from. 1.2786 + gfxImageFormat format = 1.2787 + (mIsTransparent && !mBackground) ? gfxImageFormat::ARGB32 : 1.2788 + gfxImageFormat::RGB24; 1.2789 + 1.2790 +#ifdef MOZ_X11 1.2791 + Display* dpy = mWsInfo.display; 1.2792 + Screen* screen = DefaultScreenOfDisplay(dpy); 1.2793 + if (format == gfxImageFormat::RGB24 && 1.2794 + DefaultDepth(dpy, DefaultScreen(dpy)) == 16) { 1.2795 + format = gfxImageFormat::RGB16_565; 1.2796 + } 1.2797 + 1.2798 + if (mSurfaceType == gfxSurfaceType::Xlib) { 1.2799 + if (!mIsTransparent || mBackground) { 1.2800 + Visual* defaultVisual = DefaultVisualOfScreen(screen); 1.2801 + mCurrentSurface = 1.2802 + gfxXlibSurface::Create(screen, defaultVisual, 1.2803 + gfxIntSize(mWindow.width, 1.2804 + mWindow.height)); 1.2805 + return mCurrentSurface != nullptr; 1.2806 + } 1.2807 + 1.2808 + XRenderPictFormat* xfmt = XRenderFindStandardFormat(dpy, PictStandardARGB32); 1.2809 + if (!xfmt) { 1.2810 + NS_ERROR("Need X falback surface, but FindRenderFormat failed"); 1.2811 + return false; 1.2812 + } 1.2813 + mCurrentSurface = 1.2814 + gfxXlibSurface::Create(screen, xfmt, 1.2815 + gfxIntSize(mWindow.width, 1.2816 + mWindow.height)); 1.2817 + return mCurrentSurface != nullptr; 1.2818 + } 1.2819 +#endif 1.2820 + 1.2821 +#ifdef XP_WIN 1.2822 + if (mSurfaceType == gfxSurfaceType::Win32 || 1.2823 + mSurfaceType == gfxSurfaceType::D2D) { 1.2824 + bool willHaveTransparentPixels = mIsTransparent && !mBackground; 1.2825 + 1.2826 + SharedDIBSurface* s = new SharedDIBSurface(); 1.2827 + if (!s->Create(reinterpret_cast<HDC>(mWindow.window), 1.2828 + mWindow.width, mWindow.height, 1.2829 + willHaveTransparentPixels)) 1.2830 + return false; 1.2831 + 1.2832 + mCurrentSurface = s; 1.2833 + return true; 1.2834 + } 1.2835 + 1.2836 + NS_RUNTIMEABORT("Shared-memory drawing not expected on Windows."); 1.2837 +#endif 1.2838 + 1.2839 + // Make common shmem implementation working for any platform 1.2840 + mCurrentSurface = 1.2841 + gfxSharedImageSurface::CreateUnsafe(this, gfxIntSize(mWindow.width, mWindow.height), format); 1.2842 + return !!mCurrentSurface; 1.2843 +} 1.2844 + 1.2845 +bool 1.2846 +PluginInstanceChild::MaybeCreatePlatformHelperSurface(void) 1.2847 +{ 1.2848 + if (!mCurrentSurface) { 1.2849 + NS_ERROR("Cannot create helper surface without mCurrentSurface"); 1.2850 + return false; 1.2851 + } 1.2852 + 1.2853 +#ifdef MOZ_X11 1.2854 + bool supportNonDefaultVisual = false; 1.2855 + Screen* screen = DefaultScreenOfDisplay(mWsInfo.display); 1.2856 + Visual* defaultVisual = DefaultVisualOfScreen(screen); 1.2857 + Visual* visual = nullptr; 1.2858 + Colormap colormap = 0; 1.2859 + mDoAlphaExtraction = false; 1.2860 + bool createHelperSurface = false; 1.2861 + 1.2862 + if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) { 1.2863 + static_cast<gfxXlibSurface*>(mCurrentSurface.get())-> 1.2864 + GetColormapAndVisual(&colormap, &visual); 1.2865 + // Create helper surface if layer surface visual not same as default 1.2866 + // and we don't support non-default visual rendering 1.2867 + if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) { 1.2868 + createHelperSurface = true; 1.2869 + visual = defaultVisual; 1.2870 + mDoAlphaExtraction = mIsTransparent; 1.2871 + } 1.2872 + } else if (mCurrentSurface->GetType() == gfxSurfaceType::Image) { 1.2873 + // For image layer surface we should always create helper surface 1.2874 + createHelperSurface = true; 1.2875 + // Check if we can create helper surface with non-default visual 1.2876 + visual = gfxXlibSurface::FindVisual(screen, 1.2877 + static_cast<gfxImageSurface*>(mCurrentSurface.get())->Format()); 1.2878 + if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) { 1.2879 + visual = defaultVisual; 1.2880 + mDoAlphaExtraction = mIsTransparent; 1.2881 + } 1.2882 + } 1.2883 + 1.2884 + if (createHelperSurface) { 1.2885 + if (!visual) { 1.2886 + NS_ERROR("Need X falback surface, but visual failed"); 1.2887 + return false; 1.2888 + } 1.2889 + mHelperSurface = 1.2890 + gfxXlibSurface::Create(screen, visual, 1.2891 + mCurrentSurface->GetSize()); 1.2892 + if (!mHelperSurface) { 1.2893 + NS_WARNING("Fail to create create helper surface"); 1.2894 + return false; 1.2895 + } 1.2896 + } 1.2897 +#elif defined(XP_WIN) 1.2898 + mDoAlphaExtraction = mIsTransparent && !mBackground; 1.2899 +#endif 1.2900 + 1.2901 + return true; 1.2902 +} 1.2903 + 1.2904 +bool 1.2905 +PluginInstanceChild::EnsureCurrentBuffer(void) 1.2906 +{ 1.2907 +#ifndef XP_MACOSX 1.2908 + nsIntRect toInvalidate(0, 0, 0, 0); 1.2909 + gfxIntSize winSize = gfxIntSize(mWindow.width, mWindow.height); 1.2910 + 1.2911 + if (mBackground && mBackground->GetSize() != winSize) { 1.2912 + // It would be nice to keep the old background here, but doing 1.2913 + // so can lead to cases in which we permanently keep the old 1.2914 + // background size. 1.2915 + mBackground = nullptr; 1.2916 + toInvalidate.UnionRect(toInvalidate, 1.2917 + nsIntRect(0, 0, winSize.width, winSize.height)); 1.2918 + } 1.2919 + 1.2920 + if (mCurrentSurface) { 1.2921 + gfxIntSize surfSize = mCurrentSurface->GetSize(); 1.2922 + if (winSize != surfSize || 1.2923 + (mBackground && !CanPaintOnBackground()) || 1.2924 + (mBackground && 1.2925 + gfxContentType::COLOR != mCurrentSurface->GetContentType()) || 1.2926 + (!mBackground && mIsTransparent && 1.2927 + gfxContentType::COLOR == mCurrentSurface->GetContentType())) { 1.2928 + // Don't try to use an old, invalid DC. 1.2929 + mWindow.window = nullptr; 1.2930 + ClearCurrentSurface(); 1.2931 + toInvalidate.UnionRect(toInvalidate, 1.2932 + nsIntRect(0, 0, winSize.width, winSize.height)); 1.2933 + } 1.2934 + } 1.2935 + 1.2936 + mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate); 1.2937 + 1.2938 + if (mCurrentSurface) { 1.2939 + return true; 1.2940 + } 1.2941 + 1.2942 + if (!CreateOptSurface()) { 1.2943 + NS_ERROR("Cannot create optimized surface"); 1.2944 + return false; 1.2945 + } 1.2946 + 1.2947 + if (!MaybeCreatePlatformHelperSurface()) { 1.2948 + NS_ERROR("Cannot create helper surface"); 1.2949 + return false; 1.2950 + } 1.2951 + 1.2952 + return true; 1.2953 +#else // XP_MACOSX 1.2954 + 1.2955 + if (!mDoubleBufferCARenderer.HasCALayer()) { 1.2956 + void *caLayer = nullptr; 1.2957 + if (mDrawingModel == NPDrawingModelCoreGraphics) { 1.2958 + if (!mCGLayer) { 1.2959 + bool avoidCGCrashes = !nsCocoaFeatures::OnMountainLionOrLater() && 1.2960 + (GetQuirks() & PluginModuleChild::QUIRK_FLASH_AVOID_CGMODE_CRASHES); 1.2961 + caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw, this, 1.2962 + avoidCGCrashes, 1.2963 + mContentsScaleFactor); 1.2964 + 1.2965 + if (!caLayer) { 1.2966 + PLUGIN_LOG_DEBUG(("GetCGLayer failed.")); 1.2967 + return false; 1.2968 + } 1.2969 + } 1.2970 + mCGLayer = caLayer; 1.2971 + } else { 1.2972 + NPError result = mPluginIface->getvalue(GetNPP(), 1.2973 + NPPVpluginCoreAnimationLayer, 1.2974 + &caLayer); 1.2975 + if (result != NPERR_NO_ERROR || !caLayer) { 1.2976 + PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not " 1.2977 + "provide CALayer.")); 1.2978 + return false; 1.2979 + } 1.2980 + } 1.2981 + mDoubleBufferCARenderer.SetCALayer(caLayer); 1.2982 + } 1.2983 + 1.2984 + if (mDoubleBufferCARenderer.HasFrontSurface() && 1.2985 + (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != mWindow.width || 1.2986 + mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height || 1.2987 + mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) { 1.2988 + mDoubleBufferCARenderer.ClearFrontSurface(); 1.2989 + } 1.2990 + 1.2991 + if (!mDoubleBufferCARenderer.HasFrontSurface()) { 1.2992 + bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface( 1.2993 + mWindow.width, mWindow.height, mContentsScaleFactor, 1.2994 + GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ? 1.2995 + ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER); 1.2996 + if (!allocSurface) { 1.2997 + PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface")); 1.2998 + return false; 1.2999 + } 1.3000 + 1.3001 + if (mPluginIface->setwindow) 1.3002 + (void) mPluginIface->setwindow(&mData, &mWindow); 1.3003 + 1.3004 + nsIntRect toInvalidate(0, 0, mWindow.width, mWindow.height); 1.3005 + mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate); 1.3006 + } 1.3007 + 1.3008 + return true; 1.3009 +#endif 1.3010 +} 1.3011 + 1.3012 +void 1.3013 +PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow) 1.3014 +{ 1.3015 + nsRefPtr<gfxASurface> curSurface = mHelperSurface ? mHelperSurface : mCurrentSurface; 1.3016 + bool needWindowUpdate = aForceSetWindow; 1.3017 +#ifdef MOZ_X11 1.3018 + Visual* visual = nullptr; 1.3019 + Colormap colormap = 0; 1.3020 + if (curSurface && curSurface->GetType() == gfxSurfaceType::Xlib) { 1.3021 + static_cast<gfxXlibSurface*>(curSurface.get())-> 1.3022 + GetColormapAndVisual(&colormap, &visual); 1.3023 + if (visual != mWsInfo.visual || colormap != mWsInfo.colormap) { 1.3024 + mWsInfo.visual = visual; 1.3025 + mWsInfo.colormap = colormap; 1.3026 + needWindowUpdate = true; 1.3027 + } 1.3028 + } 1.3029 +#endif // MOZ_X11 1.3030 +#ifdef XP_WIN 1.3031 + HDC dc = nullptr; 1.3032 + 1.3033 + if (curSurface) { 1.3034 + if (!SharedDIBSurface::IsSharedDIBSurface(curSurface)) 1.3035 + NS_RUNTIMEABORT("Expected SharedDIBSurface!"); 1.3036 + 1.3037 + SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get()); 1.3038 + dc = dibsurf->GetHDC(); 1.3039 + } 1.3040 + if (mWindow.window != dc) { 1.3041 + mWindow.window = dc; 1.3042 + needWindowUpdate = true; 1.3043 + } 1.3044 +#endif // XP_WIN 1.3045 + 1.3046 + if (!needWindowUpdate) { 1.3047 + return; 1.3048 + } 1.3049 + 1.3050 +#ifndef XP_MACOSX 1.3051 + // Adjusting the window isn't needed for OSX 1.3052 +#ifndef XP_WIN 1.3053 + // On Windows, we translate the device context, in order for the window 1.3054 + // origin to be correct. 1.3055 + mWindow.x = mWindow.y = 0; 1.3056 +#endif 1.3057 + 1.3058 + if (IsVisible()) { 1.3059 + // The clip rect is relative to drawable top-left. 1.3060 + nsIntRect clipRect; 1.3061 + 1.3062 + // Don't ask the plugin to draw outside the drawable. The clip rect 1.3063 + // is in plugin coordinates, not window coordinates. 1.3064 + // This also ensures that the unsigned clip rectangle offsets won't be -ve. 1.3065 + clipRect.SetRect(0, 0, mWindow.width, mWindow.height); 1.3066 + 1.3067 + mWindow.clipRect.left = 0; 1.3068 + mWindow.clipRect.top = 0; 1.3069 + mWindow.clipRect.right = clipRect.XMost(); 1.3070 + mWindow.clipRect.bottom = clipRect.YMost(); 1.3071 + } 1.3072 +#endif // XP_MACOSX 1.3073 + 1.3074 +#ifdef XP_WIN 1.3075 + // Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update 1.3076 + // their location... or at least Flash does: Silverlight uses the 1.3077 + // window.x/y passed to NPP_SetWindow 1.3078 + 1.3079 + if (mPluginIface->event) { 1.3080 + WINDOWPOS winpos = { 1.3081 + 0, 0, 1.3082 + mWindow.x, mWindow.y, 1.3083 + mWindow.width, mWindow.height, 1.3084 + 0 1.3085 + }; 1.3086 + NPEvent pluginEvent = { 1.3087 + WM_WINDOWPOSCHANGED, 0, 1.3088 + (LPARAM) &winpos 1.3089 + }; 1.3090 + mPluginIface->event(&mData, &pluginEvent); 1.3091 + } 1.3092 +#endif 1.3093 + 1.3094 + PLUGIN_LOG_DEBUG( 1.3095 + ("[InstanceChild][%p] UpdateWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>", 1.3096 + this, mWindow.x, mWindow.y, mWindow.width, mWindow.height, 1.3097 + mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom)); 1.3098 + 1.3099 + if (mPluginIface->setwindow) { 1.3100 + mPluginIface->setwindow(&mData, &mWindow); 1.3101 + } 1.3102 +} 1.3103 + 1.3104 +void 1.3105 +PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, 1.3106 + gfxASurface* aSurface) 1.3107 +{ 1.3108 + UpdateWindowAttributes(); 1.3109 + 1.3110 +#ifdef MOZ_X11 1.3111 + { 1.3112 + NS_ASSERTION(aSurface->GetType() == gfxSurfaceType::Xlib, 1.3113 + "Non supported platform surface type"); 1.3114 + 1.3115 + NPEvent pluginEvent; 1.3116 + XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose; 1.3117 + exposeEvent.type = GraphicsExpose; 1.3118 + exposeEvent.display = mWsInfo.display; 1.3119 + exposeEvent.drawable = static_cast<gfxXlibSurface*>(aSurface)->XDrawable(); 1.3120 + exposeEvent.x = aRect.x; 1.3121 + exposeEvent.y = aRect.y; 1.3122 + exposeEvent.width = aRect.width; 1.3123 + exposeEvent.height = aRect.height; 1.3124 + exposeEvent.count = 0; 1.3125 + // information not set: 1.3126 + exposeEvent.serial = 0; 1.3127 + exposeEvent.send_event = False; 1.3128 + exposeEvent.major_code = 0; 1.3129 + exposeEvent.minor_code = 0; 1.3130 + mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent)); 1.3131 + } 1.3132 +#elif defined(XP_WIN) 1.3133 + NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface), 1.3134 + "Expected (SharedDIB) image surface."); 1.3135 + 1.3136 + // This rect is in the window coordinate space. aRect is in the plugin 1.3137 + // coordinate space. 1.3138 + RECT rect = { 1.3139 + mWindow.x + aRect.x, 1.3140 + mWindow.y + aRect.y, 1.3141 + mWindow.x + aRect.XMost(), 1.3142 + mWindow.y + aRect.YMost() 1.3143 + }; 1.3144 + NPEvent paintEvent = { 1.3145 + WM_PAINT, 1.3146 + uintptr_t(mWindow.window), 1.3147 + uintptr_t(&rect) 1.3148 + }; 1.3149 + 1.3150 + ::SetViewportOrgEx((HDC) mWindow.window, -mWindow.x, -mWindow.y, nullptr); 1.3151 + ::SelectClipRgn((HDC) mWindow.window, nullptr); 1.3152 + ::IntersectClipRect((HDC) mWindow.window, rect.left, rect.top, rect.right, rect.bottom); 1.3153 + mPluginIface->event(&mData, reinterpret_cast<void*>(&paintEvent)); 1.3154 +#else 1.3155 + NS_RUNTIMEABORT("Surface type not implemented."); 1.3156 +#endif 1.3157 +} 1.3158 + 1.3159 +void 1.3160 +PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect, 1.3161 + gfxASurface* aSurface, 1.3162 + const gfxRGBA& aColor) 1.3163 +{ 1.3164 + // Render using temporary X surface, with copy to image surface 1.3165 + nsIntRect plPaintRect(aRect); 1.3166 + nsRefPtr<gfxASurface> renderSurface = aSurface; 1.3167 +#ifdef MOZ_X11 1.3168 + if (mIsTransparent && (GetQuirks() & PluginModuleChild::QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) { 1.3169 + // Work around a bug in Flash up to 10.1 d51 at least, where expose event 1.3170 + // top left coordinates within the plugin-rect and not at the drawable 1.3171 + // origin are misinterpreted. (We can move the top left coordinate 1.3172 + // provided it is within the clipRect.), see bug 574583 1.3173 + plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost()); 1.3174 + } 1.3175 + if (mHelperSurface) { 1.3176 + // On X11 we can paint to non Xlib surface only with HelperSurface 1.3177 + renderSurface = mHelperSurface; 1.3178 + } 1.3179 +#endif 1.3180 + 1.3181 + if (mIsTransparent && !CanPaintOnBackground()) { 1.3182 + // Clear surface content for transparent rendering 1.3183 + nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface); 1.3184 + ctx->SetDeviceColor(aColor); 1.3185 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3186 + ctx->Rectangle(GfxFromNsRect(plPaintRect)); 1.3187 + ctx->Fill(); 1.3188 + } 1.3189 + 1.3190 + PaintRectToPlatformSurface(plPaintRect, renderSurface); 1.3191 + 1.3192 + if (renderSurface != aSurface) { 1.3193 + // Copy helper surface content to target 1.3194 + nsRefPtr<gfxContext> ctx = new gfxContext(aSurface); 1.3195 + ctx->SetSource(renderSurface); 1.3196 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3197 + ctx->Rectangle(GfxFromNsRect(aRect)); 1.3198 + ctx->Fill(); 1.3199 + } 1.3200 +} 1.3201 + 1.3202 +void 1.3203 +PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect, 1.3204 + gfxASurface* aSurface) 1.3205 +{ 1.3206 + NS_ABORT_IF_FALSE(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA, 1.3207 + "Refusing to pointlessly recover alpha"); 1.3208 + 1.3209 + nsIntRect rect(aRect); 1.3210 + // If |aSurface| can be used to paint and can have alpha values 1.3211 + // recovered directly to it, do that to save a tmp surface and 1.3212 + // copy. 1.3213 + bool useSurfaceSubimageForBlack = false; 1.3214 + if (gfxSurfaceType::Image == aSurface->GetType()) { 1.3215 + gfxImageSurface* surfaceAsImage = 1.3216 + static_cast<gfxImageSurface*>(aSurface); 1.3217 + useSurfaceSubimageForBlack = 1.3218 + (surfaceAsImage->Format() == gfxImageFormat::ARGB32); 1.3219 + // If we're going to use a subimage, nudge the rect so that we 1.3220 + // can use optimal alpha recovery. If we're not using a 1.3221 + // subimage, the temporaries should automatically get 1.3222 + // fast-path alpha recovery so we don't need to do anything. 1.3223 + if (useSurfaceSubimageForBlack) { 1.3224 + rect = 1.3225 + gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect, 1.3226 + surfaceAsImage); 1.3227 + } 1.3228 + } 1.3229 + 1.3230 + nsRefPtr<gfxImageSurface> whiteImage; 1.3231 + nsRefPtr<gfxImageSurface> blackImage; 1.3232 + gfxRect targetRect(rect.x, rect.y, rect.width, rect.height); 1.3233 + gfxIntSize targetSize(rect.width, rect.height); 1.3234 + gfxPoint deviceOffset = -targetRect.TopLeft(); 1.3235 + 1.3236 + // We always use a temporary "white image" 1.3237 + whiteImage = new gfxImageSurface(targetSize, gfxImageFormat::RGB24); 1.3238 + if (whiteImage->CairoStatus()) { 1.3239 + return; 1.3240 + } 1.3241 + 1.3242 +#ifdef XP_WIN 1.3243 + // On windows, we need an HDC and so can't paint directly to 1.3244 + // vanilla image surfaces. Bifurcate this painting code so that 1.3245 + // we don't accidentally attempt that. 1.3246 + if (!SharedDIBSurface::IsSharedDIBSurface(aSurface)) 1.3247 + NS_RUNTIMEABORT("Expected SharedDIBSurface!"); 1.3248 + 1.3249 + // Paint the plugin directly onto the target, with a white 1.3250 + // background and copy the result 1.3251 + PaintRectToSurface(rect, aSurface, gfxRGBA(1.0, 1.0, 1.0)); 1.3252 + { 1.3253 + gfxRect copyRect(gfxPoint(0, 0), targetRect.Size()); 1.3254 + nsRefPtr<gfxContext> ctx = new gfxContext(whiteImage); 1.3255 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3256 + ctx->SetSource(aSurface, deviceOffset); 1.3257 + ctx->Rectangle(copyRect); 1.3258 + ctx->Fill(); 1.3259 + } 1.3260 + 1.3261 + // Paint the plugin directly onto the target, with a black 1.3262 + // background 1.3263 + PaintRectToSurface(rect, aSurface, gfxRGBA(0.0, 0.0, 0.0)); 1.3264 + 1.3265 + // Don't copy the result, just extract a subimage so that we can 1.3266 + // recover alpha directly into the target 1.3267 + gfxImageSurface *image = static_cast<gfxImageSurface*>(aSurface); 1.3268 + blackImage = image->GetSubimage(targetRect); 1.3269 + 1.3270 +#else 1.3271 + // Paint onto white background 1.3272 + whiteImage->SetDeviceOffset(deviceOffset); 1.3273 + PaintRectToSurface(rect, whiteImage, gfxRGBA(1.0, 1.0, 1.0)); 1.3274 + 1.3275 + if (useSurfaceSubimageForBlack) { 1.3276 + gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface); 1.3277 + blackImage = surface->GetSubimage(targetRect); 1.3278 + } else { 1.3279 + blackImage = new gfxImageSurface(targetSize, 1.3280 + gfxImageFormat::ARGB32); 1.3281 + } 1.3282 + 1.3283 + // Paint onto black background 1.3284 + blackImage->SetDeviceOffset(deviceOffset); 1.3285 + PaintRectToSurface(rect, blackImage, gfxRGBA(0.0, 0.0, 0.0)); 1.3286 +#endif 1.3287 + 1.3288 + NS_ABORT_IF_FALSE(whiteImage && blackImage, "Didn't paint enough!"); 1.3289 + 1.3290 + // Extract alpha from black and white image and store to black 1.3291 + // image 1.3292 + if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) { 1.3293 + return; 1.3294 + } 1.3295 + 1.3296 + // If we had to use a temporary black surface, copy the pixels 1.3297 + // with alpha back to the target 1.3298 + if (!useSurfaceSubimageForBlack) { 1.3299 + nsRefPtr<gfxContext> ctx = new gfxContext(aSurface); 1.3300 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3301 + ctx->SetSource(blackImage); 1.3302 + ctx->Rectangle(targetRect); 1.3303 + ctx->Fill(); 1.3304 + } 1.3305 +} 1.3306 + 1.3307 +bool 1.3308 +PluginInstanceChild::CanPaintOnBackground() 1.3309 +{ 1.3310 + return (mBackground && 1.3311 + mCurrentSurface && 1.3312 + mCurrentSurface->GetSize() == mBackground->GetSize()); 1.3313 +} 1.3314 + 1.3315 +bool 1.3316 +PluginInstanceChild::ShowPluginFrame() 1.3317 +{ 1.3318 + // mLayersRendering can be false if we somehow get here without 1.3319 + // receiving AsyncSetWindow() first. mPendingPluginCall is our 1.3320 + // re-entrancy guard; we can't paint while nested inside another 1.3321 + // paint. 1.3322 + if (!mLayersRendering || mPendingPluginCall) { 1.3323 + return false; 1.3324 + } 1.3325 + 1.3326 + AutoRestore<bool> pending(mPendingPluginCall); 1.3327 + mPendingPluginCall = true; 1.3328 + 1.3329 + bool temporarilyMakeVisible = !IsVisible() && !mHasPainted; 1.3330 + if (temporarilyMakeVisible && mWindow.width && mWindow.height) { 1.3331 + mWindow.clipRect.right = mWindow.width; 1.3332 + mWindow.clipRect.bottom = mWindow.height; 1.3333 + } else if (!IsVisible()) { 1.3334 + // If we're not visible, don't bother painting a <0,0,0,0> 1.3335 + // rect. If we're eventually made visible, the visibility 1.3336 + // change will invalidate our window. 1.3337 + ClearCurrentSurface(); 1.3338 + return true; 1.3339 + } 1.3340 + 1.3341 + if (!EnsureCurrentBuffer()) { 1.3342 + return false; 1.3343 + } 1.3344 + 1.3345 +#ifdef MOZ_WIDGET_COCOA 1.3346 + // We can't use the thebes code with CoreAnimation so we will 1.3347 + // take a different code path. 1.3348 + if (mDrawingModel == NPDrawingModelCoreAnimation || 1.3349 + mDrawingModel == NPDrawingModelInvalidatingCoreAnimation || 1.3350 + mDrawingModel == NPDrawingModelCoreGraphics) { 1.3351 + 1.3352 + if (!IsVisible()) { 1.3353 + return true; 1.3354 + } 1.3355 + 1.3356 + if (!mDoubleBufferCARenderer.HasFrontSurface()) { 1.3357 + NS_ERROR("CARenderer not initialized for rendering"); 1.3358 + return false; 1.3359 + } 1.3360 + 1.3361 + // Clear accRect here to be able to pass 1.3362 + // test_invalidate_during_plugin_paint test 1.3363 + nsIntRect rect = mAccumulatedInvalidRect; 1.3364 + mAccumulatedInvalidRect.SetEmpty(); 1.3365 + 1.3366 + // Fix up old invalidations that might have been made when our 1.3367 + // surface was a different size 1.3368 + rect.IntersectRect(rect, 1.3369 + nsIntRect(0, 0, 1.3370 + mDoubleBufferCARenderer.GetFrontSurfaceWidth(), 1.3371 + mDoubleBufferCARenderer.GetFrontSurfaceHeight())); 1.3372 + 1.3373 + if (mDrawingModel == NPDrawingModelCoreGraphics) { 1.3374 + mozilla::plugins::PluginUtilsOSX::Repaint(mCGLayer, rect); 1.3375 + } 1.3376 + 1.3377 + mDoubleBufferCARenderer.Render(); 1.3378 + 1.3379 + NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x, 1.3380 + (uint16_t)rect.YMost(), (uint16_t)rect.XMost() }; 1.3381 + SurfaceDescriptor currSurf; 1.3382 + currSurf = IOSurfaceDescriptor(mDoubleBufferCARenderer.GetFrontSurfaceID(), 1.3383 + mDoubleBufferCARenderer.GetContentsScaleFactor()); 1.3384 + 1.3385 + mHasPainted = true; 1.3386 + 1.3387 + SurfaceDescriptor returnSurf; 1.3388 + 1.3389 + if (!SendShow(r, currSurf, &returnSurf)) { 1.3390 + return false; 1.3391 + } 1.3392 + 1.3393 + SwapSurfaces(); 1.3394 + return true; 1.3395 + } else { 1.3396 + NS_ERROR("Unsupported drawing model for async layer rendering"); 1.3397 + return false; 1.3398 + } 1.3399 +#endif 1.3400 + 1.3401 + NS_ASSERTION(mWindow.width == uint32_t(mWindow.clipRect.right - mWindow.clipRect.left) && 1.3402 + mWindow.height == uint32_t(mWindow.clipRect.bottom - mWindow.clipRect.top), 1.3403 + "Clip rect should be same size as window when using layers"); 1.3404 + 1.3405 + // Clear accRect here to be able to pass 1.3406 + // test_invalidate_during_plugin_paint test 1.3407 + nsIntRect rect = mAccumulatedInvalidRect; 1.3408 + mAccumulatedInvalidRect.SetEmpty(); 1.3409 + 1.3410 + // Fix up old invalidations that might have been made when our 1.3411 + // surface was a different size 1.3412 + gfxIntSize surfaceSize = mCurrentSurface->GetSize(); 1.3413 + rect.IntersectRect(rect, 1.3414 + nsIntRect(0, 0, surfaceSize.width, surfaceSize.height)); 1.3415 + 1.3416 + if (!ReadbackDifferenceRect(rect)) { 1.3417 + // We couldn't read back the pixels that differ between the 1.3418 + // current surface and last, so we have to invalidate the 1.3419 + // entire window. 1.3420 + rect.SetRect(0, 0, mWindow.width, mWindow.height); 1.3421 + } 1.3422 + 1.3423 + bool haveTransparentPixels = 1.3424 + gfxContentType::COLOR_ALPHA == mCurrentSurface->GetContentType(); 1.3425 + PLUGIN_LOG_DEBUG( 1.3426 + ("[InstanceChild][%p] Painting%s <x=%d,y=%d, w=%d,h=%d> on surface <w=%d,h=%d>", 1.3427 + this, haveTransparentPixels ? " with alpha" : "", 1.3428 + rect.x, rect.y, rect.width, rect.height, 1.3429 + mCurrentSurface->GetSize().width, mCurrentSurface->GetSize().height)); 1.3430 + 1.3431 + if (CanPaintOnBackground()) { 1.3432 + PLUGIN_LOG_DEBUG((" (on background)")); 1.3433 + // Source the background pixels ... 1.3434 + { 1.3435 + nsRefPtr<gfxContext> ctx = 1.3436 + new gfxContext(mHelperSurface ? mHelperSurface : mCurrentSurface); 1.3437 + ctx->SetSource(mBackground); 1.3438 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3439 + ctx->Rectangle(gfxRect(rect.x, rect.y, rect.width, rect.height)); 1.3440 + ctx->Fill(); 1.3441 + } 1.3442 + // ... and hand off to the plugin 1.3443 + // BEWARE: mBackground may die during this call 1.3444 + PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0)); 1.3445 + } else if (!temporarilyMakeVisible && mDoAlphaExtraction) { 1.3446 + // We don't want to pay the expense of alpha extraction for 1.3447 + // phony paints. 1.3448 + PLUGIN_LOG_DEBUG((" (with alpha recovery)")); 1.3449 + PaintRectWithAlphaExtraction(rect, mCurrentSurface); 1.3450 + } else { 1.3451 + PLUGIN_LOG_DEBUG((" (onto opaque surface)")); 1.3452 + 1.3453 + // If we're on a platform that needs helper surfaces for 1.3454 + // plugins, and we're forcing a throwaway paint of a 1.3455 + // wmode=transparent plugin, then make sure to use the helper 1.3456 + // surface here. 1.3457 + nsRefPtr<gfxASurface> target = 1.3458 + (temporarilyMakeVisible && mHelperSurface) ? 1.3459 + mHelperSurface : mCurrentSurface; 1.3460 + 1.3461 + PaintRectToSurface(rect, target, gfxRGBA(0.0, 0.0, 0.0, 0.0)); 1.3462 + } 1.3463 + mHasPainted = true; 1.3464 + 1.3465 + if (temporarilyMakeVisible) { 1.3466 + mWindow.clipRect.right = mWindow.clipRect.bottom = 0; 1.3467 + 1.3468 + PLUGIN_LOG_DEBUG( 1.3469 + ("[InstanceChild][%p] Undoing temporary clipping w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>", 1.3470 + this, mWindow.x, mWindow.y, mWindow.width, mWindow.height, 1.3471 + mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom)); 1.3472 + 1.3473 + if (mPluginIface->setwindow) { 1.3474 + mPluginIface->setwindow(&mData, &mWindow); 1.3475 + } 1.3476 + 1.3477 + // Skip forwarding the results of the phony paint to the 1.3478 + // browser. We may have painted a transparent plugin using 1.3479 + // the opaque-plugin path, which can result in wrong pixels. 1.3480 + // We also don't want to pay the expense of forwarding the 1.3481 + // surface for plugins that might really be invisible. 1.3482 + mAccumulatedInvalidRect.SetRect(0, 0, mWindow.width, mWindow.height); 1.3483 + return true; 1.3484 + } 1.3485 + 1.3486 + NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x, 1.3487 + (uint16_t)rect.YMost(), (uint16_t)rect.XMost() }; 1.3488 + SurfaceDescriptor currSurf; 1.3489 +#ifdef MOZ_X11 1.3490 + if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) { 1.3491 + gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get()); 1.3492 + currSurf = SurfaceDescriptorX11(xsurf); 1.3493 + // Need to sync all pending x-paint requests 1.3494 + // before giving drawable to another process 1.3495 + XSync(mWsInfo.display, False); 1.3496 + } else 1.3497 +#endif 1.3498 +#ifdef XP_WIN 1.3499 + if (SharedDIBSurface::IsSharedDIBSurface(mCurrentSurface)) { 1.3500 + SharedDIBSurface* s = static_cast<SharedDIBSurface*>(mCurrentSurface.get()); 1.3501 + if (!mCurrentSurfaceActor) { 1.3502 + base::SharedMemoryHandle handle = nullptr; 1.3503 + s->ShareToProcess(PluginModuleChild::current()->OtherProcess(), &handle); 1.3504 + 1.3505 + mCurrentSurfaceActor = 1.3506 + SendPPluginSurfaceConstructor(handle, 1.3507 + mCurrentSurface->GetSize(), 1.3508 + haveTransparentPixels); 1.3509 + } 1.3510 + currSurf = mCurrentSurfaceActor; 1.3511 + s->Flush(); 1.3512 + } else 1.3513 +#endif 1.3514 + if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) { 1.3515 + currSurf = static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem(); 1.3516 + } else { 1.3517 + NS_RUNTIMEABORT("Surface type is not remotable"); 1.3518 + return false; 1.3519 + } 1.3520 + 1.3521 + // Unused, except to possibly return a shmem to us 1.3522 + SurfaceDescriptor returnSurf; 1.3523 + 1.3524 + if (!SendShow(r, currSurf, &returnSurf)) { 1.3525 + return false; 1.3526 + } 1.3527 + 1.3528 + SwapSurfaces(); 1.3529 + mSurfaceDifferenceRect = rect; 1.3530 + return true; 1.3531 +} 1.3532 + 1.3533 +bool 1.3534 +PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect) 1.3535 +{ 1.3536 + if (!mBackSurface) 1.3537 + return false; 1.3538 + 1.3539 + // We can read safely from XSurface,SharedDIBSurface and Unsafe SharedMemory, 1.3540 + // because PluginHost is not able to modify that surface 1.3541 +#if defined(MOZ_X11) 1.3542 + if (mBackSurface->GetType() != gfxSurfaceType::Xlib && 1.3543 + !gfxSharedImageSurface::IsSharedImage(mBackSurface)) 1.3544 + return false; 1.3545 +#elif defined(XP_WIN) 1.3546 + if (!SharedDIBSurface::IsSharedDIBSurface(mBackSurface)) 1.3547 + return false; 1.3548 +#else 1.3549 + return false; 1.3550 +#endif 1.3551 + 1.3552 + if (mCurrentSurface->GetContentType() != mBackSurface->GetContentType()) 1.3553 + return false; 1.3554 + 1.3555 + if (mSurfaceDifferenceRect.IsEmpty()) 1.3556 + return true; 1.3557 + 1.3558 + PLUGIN_LOG_DEBUG( 1.3559 + ("[InstanceChild][%p] Reading back part of <x=%d,y=%d, w=%d,h=%d>", 1.3560 + this, mSurfaceDifferenceRect.x, mSurfaceDifferenceRect.y, 1.3561 + mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height)); 1.3562 + 1.3563 + // Read back previous content 1.3564 + nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface); 1.3565 + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); 1.3566 + ctx->SetSource(mBackSurface); 1.3567 + // Subtract from mSurfaceDifferenceRect area which is overlapping with rect 1.3568 + nsIntRegion result; 1.3569 + result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect)); 1.3570 + nsIntRegionRectIterator iter(result); 1.3571 + const nsIntRect* r; 1.3572 + while ((r = iter.Next()) != nullptr) { 1.3573 + ctx->Rectangle(GfxFromNsRect(*r)); 1.3574 + } 1.3575 + ctx->Fill(); 1.3576 + 1.3577 + return true; 1.3578 +} 1.3579 + 1.3580 +void 1.3581 +PluginInstanceChild::InvalidateRectDelayed(void) 1.3582 +{ 1.3583 + if (!mCurrentInvalidateTask) { 1.3584 + return; 1.3585 + } 1.3586 + 1.3587 + mCurrentInvalidateTask = nullptr; 1.3588 + if (mAccumulatedInvalidRect.IsEmpty()) { 1.3589 + return; 1.3590 + } 1.3591 + 1.3592 + if (!ShowPluginFrame()) { 1.3593 + AsyncShowPluginFrame(); 1.3594 + } 1.3595 +} 1.3596 + 1.3597 +void 1.3598 +PluginInstanceChild::AsyncShowPluginFrame(void) 1.3599 +{ 1.3600 + if (mCurrentInvalidateTask) { 1.3601 + return; 1.3602 + } 1.3603 + 1.3604 + mCurrentInvalidateTask = 1.3605 + NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed); 1.3606 + MessageLoop::current()->PostTask(FROM_HERE, mCurrentInvalidateTask); 1.3607 +} 1.3608 + 1.3609 +void 1.3610 +PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect) 1.3611 +{ 1.3612 + NS_ASSERTION(aInvalidRect, "Null pointer!"); 1.3613 + 1.3614 +#ifdef OS_WIN 1.3615 + // Invalidate and draw locally for windowed plugins. 1.3616 + if (mWindow.type == NPWindowTypeWindow) { 1.3617 + NS_ASSERTION(IsWindow(mPluginWindowHWND), "Bad window?!"); 1.3618 + RECT rect = { aInvalidRect->left, aInvalidRect->top, 1.3619 + aInvalidRect->right, aInvalidRect->bottom }; 1.3620 + ::InvalidateRect(mPluginWindowHWND, &rect, FALSE); 1.3621 + return; 1.3622 + } 1.3623 +#endif 1.3624 + 1.3625 + if (mLayersRendering) { 1.3626 + nsIntRect r(aInvalidRect->left, aInvalidRect->top, 1.3627 + aInvalidRect->right - aInvalidRect->left, 1.3628 + aInvalidRect->bottom - aInvalidRect->top); 1.3629 + 1.3630 + mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect); 1.3631 + // If we are able to paint and invalidate sent, then reset 1.3632 + // accumulated rectangle 1.3633 + AsyncShowPluginFrame(); 1.3634 + return; 1.3635 + } 1.3636 + 1.3637 + // If we were going to use layers rendering but it's not set up 1.3638 + // yet, and the plugin happens to call this first, we'll forward 1.3639 + // the invalidation to the browser. It's unclear whether 1.3640 + // non-layers plugins need this rect forwarded when their window 1.3641 + // width or height is 0, which it would be for layers plugins 1.3642 + // before their first SetWindow(). 1.3643 + SendNPN_InvalidateRect(*aInvalidRect); 1.3644 +} 1.3645 + 1.3646 +bool 1.3647 +PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground, 1.3648 + const nsIntRect& aRect) 1.3649 +{ 1.3650 + NS_ABORT_IF_FALSE(mIsTransparent, "Only transparent plugins use backgrounds"); 1.3651 + 1.3652 + if (!mBackground) { 1.3653 + // XXX refactor me 1.3654 + switch (aBackground.type()) { 1.3655 +#ifdef MOZ_X11 1.3656 + case SurfaceDescriptor::TSurfaceDescriptorX11: { 1.3657 + mBackground = aBackground.get_SurfaceDescriptorX11().OpenForeign(); 1.3658 + break; 1.3659 + } 1.3660 +#endif 1.3661 + case SurfaceDescriptor::TShmem: { 1.3662 + mBackground = gfxSharedImageSurface::Open(aBackground.get_Shmem()); 1.3663 + break; 1.3664 + } 1.3665 + default: 1.3666 + NS_RUNTIMEABORT("Unexpected background surface descriptor"); 1.3667 + } 1.3668 + 1.3669 + if (!mBackground) { 1.3670 + return false; 1.3671 + } 1.3672 + 1.3673 + gfxIntSize bgSize = mBackground->GetSize(); 1.3674 + mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, 1.3675 + nsIntRect(0, 0, bgSize.width, bgSize.height)); 1.3676 + AsyncShowPluginFrame(); 1.3677 + return true; 1.3678 + } 1.3679 + 1.3680 + // XXX refactor me 1.3681 + mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect); 1.3682 + 1.3683 + // This must be asynchronous, because we may be nested within RPC messages 1.3684 + // which do not expect to receiving paint events. 1.3685 + AsyncShowPluginFrame(); 1.3686 + 1.3687 + return true; 1.3688 +} 1.3689 + 1.3690 +PPluginBackgroundDestroyerChild* 1.3691 +PluginInstanceChild::AllocPPluginBackgroundDestroyerChild() 1.3692 +{ 1.3693 + return new PluginBackgroundDestroyerChild(); 1.3694 +} 1.3695 + 1.3696 +bool 1.3697 +PluginInstanceChild::RecvPPluginBackgroundDestroyerConstructor( 1.3698 + PPluginBackgroundDestroyerChild* aActor) 1.3699 +{ 1.3700 + // Our background changed, so we have to invalidate the area 1.3701 + // painted with the old background. If the background was 1.3702 + // destroyed because we have a new background, then we expect to 1.3703 + // be notified of that "soon", before processing the asynchronous 1.3704 + // invalidation here. If we're *not* getting a new background, 1.3705 + // our current front surface is stale and we want to repaint 1.3706 + // "soon" so that we can hand the browser back a surface with 1.3707 + // alpha values. (We should be notified of that invalidation soon 1.3708 + // too, but we don't assume that here.) 1.3709 + if (mBackground) { 1.3710 + gfxIntSize bgsize = mBackground->GetSize(); 1.3711 + mAccumulatedInvalidRect.UnionRect( 1.3712 + nsIntRect(0, 0, bgsize.width, bgsize.height), mAccumulatedInvalidRect); 1.3713 + 1.3714 + // NB: we don't have to XSync here because only ShowPluginFrame() 1.3715 + // uses mBackground, and it always XSyncs after finishing. 1.3716 + mBackground = nullptr; 1.3717 + AsyncShowPluginFrame(); 1.3718 + } 1.3719 + 1.3720 + return PPluginBackgroundDestroyerChild::Send__delete__(aActor); 1.3721 +} 1.3722 + 1.3723 +bool 1.3724 +PluginInstanceChild::DeallocPPluginBackgroundDestroyerChild( 1.3725 + PPluginBackgroundDestroyerChild* aActor) 1.3726 +{ 1.3727 + delete aActor; 1.3728 + return true; 1.3729 +} 1.3730 + 1.3731 +uint32_t 1.3732 +PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat, 1.3733 + TimerFunc func) 1.3734 +{ 1.3735 + ChildTimer* t = new ChildTimer(this, interval, repeat, func); 1.3736 + if (0 == t->ID()) { 1.3737 + delete t; 1.3738 + return 0; 1.3739 + } 1.3740 + 1.3741 + mTimers.AppendElement(t); 1.3742 + return t->ID(); 1.3743 +} 1.3744 + 1.3745 +void 1.3746 +PluginInstanceChild::UnscheduleTimer(uint32_t id) 1.3747 +{ 1.3748 + if (0 == id) 1.3749 + return; 1.3750 + 1.3751 + mTimers.RemoveElement(id, ChildTimer::IDComparator()); 1.3752 +} 1.3753 + 1.3754 +void 1.3755 +PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData) 1.3756 +{ 1.3757 + ChildAsyncCall* task = new ChildAsyncCall(this, aFunc, aUserData); 1.3758 + 1.3759 + { 1.3760 + MutexAutoLock lock(mAsyncCallMutex); 1.3761 + mPendingAsyncCalls.AppendElement(task); 1.3762 + } 1.3763 + ProcessChild::message_loop()->PostTask(FROM_HERE, task); 1.3764 +} 1.3765 + 1.3766 +static PLDHashOperator 1.3767 +InvalidateObject(DeletingObjectEntry* e, void* userArg) 1.3768 +{ 1.3769 + NPObject* o = e->GetKey(); 1.3770 + if (!e->mDeleted && o->_class && o->_class->invalidate) 1.3771 + o->_class->invalidate(o); 1.3772 + 1.3773 + return PL_DHASH_NEXT; 1.3774 +} 1.3775 + 1.3776 +static PLDHashOperator 1.3777 +DeleteObject(DeletingObjectEntry* e, void* userArg) 1.3778 +{ 1.3779 + NPObject* o = e->GetKey(); 1.3780 + if (!e->mDeleted) { 1.3781 + e->mDeleted = true; 1.3782 + 1.3783 +#ifdef NS_BUILD_REFCNT_LOGGING 1.3784 + { 1.3785 + int32_t refcnt = o->referenceCount; 1.3786 + while (refcnt) { 1.3787 + --refcnt; 1.3788 + NS_LOG_RELEASE(o, refcnt, "NPObject"); 1.3789 + } 1.3790 + } 1.3791 +#endif 1.3792 + 1.3793 + PluginModuleChild::DeallocNPObject(o); 1.3794 + } 1.3795 + 1.3796 + return PL_DHASH_NEXT; 1.3797 +} 1.3798 + 1.3799 +void 1.3800 +PluginInstanceChild::SwapSurfaces() 1.3801 +{ 1.3802 + nsRefPtr<gfxASurface> tmpsurf = mCurrentSurface; 1.3803 +#ifdef XP_WIN 1.3804 + PPluginSurfaceChild* tmpactor = mCurrentSurfaceActor; 1.3805 +#endif 1.3806 + 1.3807 + mCurrentSurface = mBackSurface; 1.3808 +#ifdef XP_WIN 1.3809 + mCurrentSurfaceActor = mBackSurfaceActor; 1.3810 +#endif 1.3811 + 1.3812 + mBackSurface = tmpsurf; 1.3813 +#ifdef XP_WIN 1.3814 + mBackSurfaceActor = tmpactor; 1.3815 +#endif 1.3816 + 1.3817 +#ifdef MOZ_WIDGET_COCOA 1.3818 + mDoubleBufferCARenderer.SwapSurfaces(); 1.3819 + 1.3820 + // Outdated back surface... not usable anymore due to changed plugin size. 1.3821 + // Dropping obsolete surface 1.3822 + if (mDoubleBufferCARenderer.HasFrontSurface() && 1.3823 + mDoubleBufferCARenderer.HasBackSurface() && 1.3824 + (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != 1.3825 + mDoubleBufferCARenderer.GetBackSurfaceWidth() || 1.3826 + mDoubleBufferCARenderer.GetFrontSurfaceHeight() != 1.3827 + mDoubleBufferCARenderer.GetBackSurfaceHeight() || 1.3828 + mDoubleBufferCARenderer.GetFrontSurfaceContentsScaleFactor() != 1.3829 + mDoubleBufferCARenderer.GetBackSurfaceContentsScaleFactor())) { 1.3830 + 1.3831 + mDoubleBufferCARenderer.ClearFrontSurface(); 1.3832 + } 1.3833 +#else 1.3834 + if (mCurrentSurface && mBackSurface && 1.3835 + (mCurrentSurface->GetSize() != mBackSurface->GetSize() || 1.3836 + mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) { 1.3837 + ClearCurrentSurface(); 1.3838 + } 1.3839 +#endif 1.3840 +} 1.3841 + 1.3842 +void 1.3843 +PluginInstanceChild::ClearCurrentSurface() 1.3844 +{ 1.3845 + mCurrentSurface = nullptr; 1.3846 +#ifdef MOZ_WIDGET_COCOA 1.3847 + if (mDoubleBufferCARenderer.HasFrontSurface()) { 1.3848 + mDoubleBufferCARenderer.ClearFrontSurface(); 1.3849 + } 1.3850 +#endif 1.3851 +#ifdef XP_WIN 1.3852 + if (mCurrentSurfaceActor) { 1.3853 + PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor); 1.3854 + mCurrentSurfaceActor = nullptr; 1.3855 + } 1.3856 +#endif 1.3857 + mHelperSurface = nullptr; 1.3858 +} 1.3859 + 1.3860 +void 1.3861 +PluginInstanceChild::ClearAllSurfaces() 1.3862 +{ 1.3863 + if (mBackSurface) { 1.3864 + // Get last surface back, and drop it 1.3865 + SurfaceDescriptor temp = null_t(); 1.3866 + NPRect r = { 0, 0, 1, 1 }; 1.3867 + SendShow(r, temp, &temp); 1.3868 + } 1.3869 + 1.3870 + if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) 1.3871 + DeallocShmem(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem()); 1.3872 + if (gfxSharedImageSurface::IsSharedImage(mBackSurface)) 1.3873 + DeallocShmem(static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem()); 1.3874 + mCurrentSurface = nullptr; 1.3875 + mBackSurface = nullptr; 1.3876 + 1.3877 +#ifdef XP_WIN 1.3878 + if (mCurrentSurfaceActor) { 1.3879 + PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor); 1.3880 + mCurrentSurfaceActor = nullptr; 1.3881 + } 1.3882 + if (mBackSurfaceActor) { 1.3883 + PPluginSurfaceChild::Send__delete__(mBackSurfaceActor); 1.3884 + mBackSurfaceActor = nullptr; 1.3885 + } 1.3886 +#endif 1.3887 + 1.3888 +#ifdef MOZ_WIDGET_COCOA 1.3889 + if (mDoubleBufferCARenderer.HasBackSurface()) { 1.3890 + // Get last surface back, and drop it 1.3891 + SurfaceDescriptor temp = null_t(); 1.3892 + NPRect r = { 0, 0, 1, 1 }; 1.3893 + SendShow(r, temp, &temp); 1.3894 + } 1.3895 + 1.3896 + if (mCGLayer) { 1.3897 + mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer); 1.3898 + mCGLayer = nullptr; 1.3899 + } 1.3900 + 1.3901 + mDoubleBufferCARenderer.ClearFrontSurface(); 1.3902 + mDoubleBufferCARenderer.ClearBackSurface(); 1.3903 +#endif 1.3904 +} 1.3905 + 1.3906 +PLDHashOperator 1.3907 +PluginInstanceChild::DeleteSurface(NPAsyncSurface* surf, nsAutoPtr<AsyncBitmapData> &data, void* userArg) 1.3908 +{ 1.3909 + PluginInstanceChild *inst = static_cast<PluginInstanceChild*>(userArg); 1.3910 + 1.3911 + inst->DeallocShmem(data->mShmem); 1.3912 + 1.3913 + return PL_DHASH_REMOVE; 1.3914 +} 1.3915 + 1.3916 +bool 1.3917 +PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult) 1.3918 +{ 1.3919 + PLUGIN_LOG_DEBUG_METHOD; 1.3920 + AssertPluginThread(); 1.3921 + *aResult = NPERR_NO_ERROR; 1.3922 + 1.3923 +#if defined(OS_WIN) 1.3924 + SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1); 1.3925 +#endif 1.3926 + 1.3927 + InfallibleTArray<PBrowserStreamChild*> streams; 1.3928 + ManagedPBrowserStreamChild(streams); 1.3929 + 1.3930 + // First make sure none of these streams become deleted 1.3931 + for (uint32_t i = 0; i < streams.Length(); ) { 1.3932 + if (static_cast<BrowserStreamChild*>(streams[i])->InstanceDying()) 1.3933 + ++i; 1.3934 + else 1.3935 + streams.RemoveElementAt(i); 1.3936 + } 1.3937 + for (uint32_t i = 0; i < streams.Length(); ++i) 1.3938 + static_cast<BrowserStreamChild*>(streams[i])->FinishDelivery(); 1.3939 + 1.3940 + mTimers.Clear(); 1.3941 + 1.3942 + // NPP_Destroy() should be a synchronization point for plugin threads 1.3943 + // calling NPN_AsyncCall: after this function returns, they are no longer 1.3944 + // allowed to make async calls on this instance. 1.3945 + PluginModuleChild::current()->NPP_Destroy(this); 1.3946 + mData.ndata = 0; 1.3947 + 1.3948 + if (mCurrentInvalidateTask) { 1.3949 + mCurrentInvalidateTask->Cancel(); 1.3950 + mCurrentInvalidateTask = nullptr; 1.3951 + } 1.3952 + if (mCurrentAsyncSetWindowTask) { 1.3953 + mCurrentAsyncSetWindowTask->Cancel(); 1.3954 + mCurrentAsyncSetWindowTask = nullptr; 1.3955 + } 1.3956 + { 1.3957 + MutexAutoLock autoLock(mAsyncInvalidateMutex); 1.3958 + if (mAsyncInvalidateTask) { 1.3959 + mAsyncInvalidateTask->Cancel(); 1.3960 + mAsyncInvalidateTask = nullptr; 1.3961 + } 1.3962 + } 1.3963 + 1.3964 + ClearAllSurfaces(); 1.3965 + 1.3966 + mDeletingHash = new nsTHashtable<DeletingObjectEntry>; 1.3967 + PluginModuleChild::current()->FindNPObjectsForInstance(this); 1.3968 + 1.3969 + mDeletingHash->EnumerateEntries(InvalidateObject, nullptr); 1.3970 + mDeletingHash->EnumerateEntries(DeleteObject, nullptr); 1.3971 + 1.3972 + // Null out our cached actors as they should have been killed in the 1.3973 + // PluginInstanceDestroyed call above. 1.3974 + mCachedWindowActor = nullptr; 1.3975 + mCachedElementActor = nullptr; 1.3976 + 1.3977 +#if defined(OS_WIN) 1.3978 + SharedSurfaceRelease(); 1.3979 + DestroyWinlessPopupSurrogate(); 1.3980 + UnhookWinlessFlashThrottle(); 1.3981 + DestroyPluginWindow(); 1.3982 +#endif 1.3983 + 1.3984 + // Pending async calls are discarded, not delivered. This matches the 1.3985 + // in-process behavior. 1.3986 + for (uint32_t i = 0; i < mPendingAsyncCalls.Length(); ++i) 1.3987 + mPendingAsyncCalls[i]->Cancel(); 1.3988 + 1.3989 + mPendingAsyncCalls.Clear(); 1.3990 + 1.3991 + if (mAsyncBitmaps.Count()) { 1.3992 + NS_ERROR("Not all AsyncBitmaps were finalized by a plugin!"); 1.3993 + mAsyncBitmaps.Enumerate(DeleteSurface, this); 1.3994 + } 1.3995 + 1.3996 +#if (MOZ_WIDGET_GTK == 2) 1.3997 + if (mWindow.type == NPWindowTypeWindow && !mXEmbed) { 1.3998 + xt_client_xloop_destroy(); 1.3999 + } 1.4000 +#endif 1.4001 +#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) 1.4002 + DeleteWindow(); 1.4003 +#endif 1.4004 + 1.4005 + return true; 1.4006 +}