dom/plugins/ipc/PluginInstanceChild.cpp

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

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

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

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

mercurial