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