|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: sw=4 ts=4 et : |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "mozilla/DebugOnly.h" |
|
8 #include <stdint.h> // for intptr_t |
|
9 |
|
10 #include "PluginInstanceParent.h" |
|
11 #include "BrowserStreamParent.h" |
|
12 #include "PluginBackgroundDestroyer.h" |
|
13 #include "PluginModuleParent.h" |
|
14 #include "PluginStreamParent.h" |
|
15 #include "StreamNotifyParent.h" |
|
16 #include "npfunctions.h" |
|
17 #include "nsAutoPtr.h" |
|
18 #include "gfxASurface.h" |
|
19 #include "gfxContext.h" |
|
20 #include "gfxPlatform.h" |
|
21 #include "gfxSharedImageSurface.h" |
|
22 #include "nsNPAPIPluginInstance.h" |
|
23 #ifdef MOZ_X11 |
|
24 #include "gfxXlibSurface.h" |
|
25 #endif |
|
26 #include "gfxContext.h" |
|
27 #include "gfxColor.h" |
|
28 #include "gfxUtils.h" |
|
29 #include "mozilla/gfx/2D.h" |
|
30 #include "Layers.h" |
|
31 #include "SharedTextureImage.h" |
|
32 #include "GLContext.h" |
|
33 #include "GLContextProvider.h" |
|
34 |
|
35 #ifdef XP_MACOSX |
|
36 #include "MacIOSurfaceImage.h" |
|
37 #endif |
|
38 |
|
39 #if defined(OS_WIN) |
|
40 #include <windowsx.h> |
|
41 #include "gfxWindowsPlatform.h" |
|
42 #include "mozilla/plugins/PluginSurfaceParent.h" |
|
43 |
|
44 // Plugin focus event for widget. |
|
45 extern const wchar_t* kOOPPPluginFocusEventId; |
|
46 UINT gOOPPPluginFocusEvent = |
|
47 RegisterWindowMessage(kOOPPPluginFocusEventId); |
|
48 extern const wchar_t* kFlashFullscreenClass; |
|
49 #elif defined(MOZ_WIDGET_GTK) |
|
50 #include <gdk/gdk.h> |
|
51 #elif defined(XP_MACOSX) |
|
52 #include <ApplicationServices/ApplicationServices.h> |
|
53 #endif // defined(XP_MACOSX) |
|
54 |
|
55 using namespace mozilla::plugins; |
|
56 using namespace mozilla::layers; |
|
57 using namespace mozilla::gl; |
|
58 |
|
59 bool |
|
60 StreamNotifyParent::RecvRedirectNotifyResponse(const bool& allow) |
|
61 { |
|
62 PluginInstanceParent* instance = static_cast<PluginInstanceParent*>(Manager()); |
|
63 instance->mNPNIface->urlredirectresponse(instance->mNPP, this, static_cast<NPBool>(allow)); |
|
64 return true; |
|
65 } |
|
66 |
|
67 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, |
|
68 NPP npp, |
|
69 const nsCString& aMimeType, |
|
70 const NPNetscapeFuncs* npniface) |
|
71 : mParent(parent) |
|
72 , mNPP(npp) |
|
73 , mNPNIface(npniface) |
|
74 , mWindowType(NPWindowTypeWindow) |
|
75 , mDrawingModel(kDefaultDrawingModel) |
|
76 #if defined(OS_WIN) |
|
77 , mPluginHWND(nullptr) |
|
78 , mPluginWndProc(nullptr) |
|
79 , mNestedEventState(false) |
|
80 #endif // defined(XP_WIN) |
|
81 #if defined(XP_MACOSX) |
|
82 , mShWidth(0) |
|
83 , mShHeight(0) |
|
84 , mShColorSpace(nullptr) |
|
85 #endif |
|
86 { |
|
87 } |
|
88 |
|
89 PluginInstanceParent::~PluginInstanceParent() |
|
90 { |
|
91 if (mNPP) |
|
92 mNPP->pdata = nullptr; |
|
93 |
|
94 #if defined(OS_WIN) |
|
95 NS_ASSERTION(!(mPluginHWND || mPluginWndProc), |
|
96 "Subclass was not reset correctly before the dtor was reached!"); |
|
97 #endif |
|
98 #if defined(MOZ_WIDGET_COCOA) |
|
99 if (mShWidth != 0 && mShHeight != 0) { |
|
100 DeallocShmem(mShSurface); |
|
101 } |
|
102 if (mShColorSpace) |
|
103 ::CGColorSpaceRelease(mShColorSpace); |
|
104 #endif |
|
105 if (mRemoteImageDataShmem.IsWritable()) { |
|
106 if (mImageContainer) { |
|
107 mImageContainer->SetRemoteImageData(nullptr, nullptr); |
|
108 mImageContainer->SetCompositionNotifySink(nullptr); |
|
109 } |
|
110 DeallocShmem(mRemoteImageDataShmem); |
|
111 } |
|
112 } |
|
113 |
|
114 bool |
|
115 PluginInstanceParent::Init() |
|
116 { |
|
117 return true; |
|
118 } |
|
119 |
|
120 void |
|
121 PluginInstanceParent::ActorDestroy(ActorDestroyReason why) |
|
122 { |
|
123 #if defined(OS_WIN) |
|
124 if (why == AbnormalShutdown) { |
|
125 // If the plugin process crashes, this is the only |
|
126 // chance we get to destroy resources. |
|
127 SharedSurfaceRelease(); |
|
128 UnsubclassPluginWindow(); |
|
129 } |
|
130 #endif |
|
131 // After this method, the data backing the remote surface may no |
|
132 // longer be valid. The X surface may be destroyed, or the shared |
|
133 // memory backing this surface may no longer be valid. |
|
134 if (mFrontSurface) { |
|
135 mFrontSurface = nullptr; |
|
136 if (mImageContainer) { |
|
137 mImageContainer->SetCurrentImage(nullptr); |
|
138 } |
|
139 #ifdef MOZ_X11 |
|
140 FinishX(DefaultXDisplay()); |
|
141 #endif |
|
142 } |
|
143 } |
|
144 |
|
145 NPError |
|
146 PluginInstanceParent::Destroy() |
|
147 { |
|
148 NPError retval; |
|
149 if (!CallNPP_Destroy(&retval)) |
|
150 retval = NPERR_GENERIC_ERROR; |
|
151 |
|
152 #if defined(OS_WIN) |
|
153 SharedSurfaceRelease(); |
|
154 UnsubclassPluginWindow(); |
|
155 #endif |
|
156 |
|
157 return retval; |
|
158 } |
|
159 |
|
160 PBrowserStreamParent* |
|
161 PluginInstanceParent::AllocPBrowserStreamParent(const nsCString& url, |
|
162 const uint32_t& length, |
|
163 const uint32_t& lastmodified, |
|
164 PStreamNotifyParent* notifyData, |
|
165 const nsCString& headers, |
|
166 const nsCString& mimeType, |
|
167 const bool& seekable, |
|
168 NPError* rv, |
|
169 uint16_t *stype) |
|
170 { |
|
171 NS_RUNTIMEABORT("Not reachable"); |
|
172 return nullptr; |
|
173 } |
|
174 |
|
175 bool |
|
176 PluginInstanceParent::DeallocPBrowserStreamParent(PBrowserStreamParent* stream) |
|
177 { |
|
178 delete stream; |
|
179 return true; |
|
180 } |
|
181 |
|
182 PPluginStreamParent* |
|
183 PluginInstanceParent::AllocPPluginStreamParent(const nsCString& mimeType, |
|
184 const nsCString& target, |
|
185 NPError* result) |
|
186 { |
|
187 return new PluginStreamParent(this, mimeType, target, result); |
|
188 } |
|
189 |
|
190 bool |
|
191 PluginInstanceParent::DeallocPPluginStreamParent(PPluginStreamParent* stream) |
|
192 { |
|
193 delete stream; |
|
194 return true; |
|
195 } |
|
196 |
|
197 bool |
|
198 PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle* value, |
|
199 NPError* result) |
|
200 { |
|
201 #ifdef XP_WIN |
|
202 HWND id; |
|
203 #elif defined(MOZ_X11) |
|
204 XID id; |
|
205 #elif defined(XP_MACOSX) |
|
206 intptr_t id; |
|
207 #elif defined(ANDROID) |
|
208 // TODO: Need Android impl |
|
209 int id; |
|
210 #elif defined(MOZ_WIDGET_QT) |
|
211 // TODO: Need Qt non X impl |
|
212 int id; |
|
213 #else |
|
214 #warning Implement me |
|
215 #endif |
|
216 |
|
217 *result = mNPNIface->getvalue(mNPP, NPNVnetscapeWindow, &id); |
|
218 *value = id; |
|
219 return true; |
|
220 } |
|
221 |
|
222 bool |
|
223 PluginInstanceParent::InternalGetValueForNPObject( |
|
224 NPNVariable aVariable, |
|
225 PPluginScriptableObjectParent** aValue, |
|
226 NPError* aResult) |
|
227 { |
|
228 NPObject* npobject; |
|
229 NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject); |
|
230 if (result == NPERR_NO_ERROR) { |
|
231 NS_ASSERTION(npobject, "Shouldn't return null and NPERR_NO_ERROR!"); |
|
232 |
|
233 PluginScriptableObjectParent* actor = GetActorForNPObject(npobject); |
|
234 mNPNIface->releaseobject(npobject); |
|
235 if (actor) { |
|
236 *aValue = actor; |
|
237 *aResult = NPERR_NO_ERROR; |
|
238 return true; |
|
239 } |
|
240 |
|
241 NS_ERROR("Failed to get actor!"); |
|
242 result = NPERR_GENERIC_ERROR; |
|
243 } |
|
244 |
|
245 *aValue = nullptr; |
|
246 *aResult = result; |
|
247 return true; |
|
248 } |
|
249 |
|
250 bool |
|
251 PluginInstanceParent::IsAsyncDrawing() |
|
252 { |
|
253 return IsDrawingModelAsync(mDrawingModel); |
|
254 } |
|
255 |
|
256 bool |
|
257 PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject( |
|
258 PPluginScriptableObjectParent** aValue, |
|
259 NPError* aResult) |
|
260 { |
|
261 return InternalGetValueForNPObject(NPNVWindowNPObject, aValue, aResult); |
|
262 } |
|
263 |
|
264 bool |
|
265 PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject( |
|
266 PPluginScriptableObjectParent** aValue, |
|
267 NPError* aResult) |
|
268 { |
|
269 return InternalGetValueForNPObject(NPNVPluginElementNPObject, aValue, |
|
270 aResult); |
|
271 } |
|
272 |
|
273 bool |
|
274 PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, |
|
275 NPError* result) |
|
276 { |
|
277 NPBool v; |
|
278 *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v); |
|
279 *value = v; |
|
280 return true; |
|
281 } |
|
282 |
|
283 bool |
|
284 PluginInstanceParent::AnswerNPN_GetValue_DrawingModelSupport(const NPNVariable& model, bool* value) |
|
285 { |
|
286 *value = false; |
|
287 |
|
288 #ifdef XP_WIN |
|
289 switch (model) { |
|
290 case NPNVsupportsAsyncWindowsDXGISurfaceBool: { |
|
291 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D) { |
|
292 *value = true; |
|
293 } |
|
294 } |
|
295 } |
|
296 #endif |
|
297 |
|
298 return true; |
|
299 } |
|
300 |
|
301 bool |
|
302 PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, |
|
303 NPError* result) |
|
304 { |
|
305 void *v = nullptr; |
|
306 *result = mNPNIface->getvalue(mNPP, NPNVdocumentOrigin, &v); |
|
307 if (*result == NPERR_NO_ERROR && v) { |
|
308 value->Adopt(static_cast<char*>(v)); |
|
309 } |
|
310 return true; |
|
311 } |
|
312 |
|
313 bool |
|
314 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow( |
|
315 const bool& windowed, NPError* result) |
|
316 { |
|
317 // Yes, we are passing a boolean as a void*. We have to cast to intptr_t |
|
318 // first to avoid gcc warnings about casting to a pointer from a |
|
319 // non-pointer-sized integer. |
|
320 *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool, |
|
321 (void*)(intptr_t)windowed); |
|
322 return true; |
|
323 } |
|
324 |
|
325 bool |
|
326 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent( |
|
327 const bool& transparent, NPError* result) |
|
328 { |
|
329 *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool, |
|
330 (void*)(intptr_t)transparent); |
|
331 return true; |
|
332 } |
|
333 |
|
334 bool |
|
335 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor( |
|
336 const bool& useDOMForCursor, NPError* result) |
|
337 { |
|
338 *result = mNPNIface->setvalue(mNPP, NPPVpluginUsesDOMForCursorBool, |
|
339 (void*)(intptr_t)useDOMForCursor); |
|
340 return true; |
|
341 } |
|
342 |
|
343 class NotificationSink : public CompositionNotifySink |
|
344 { |
|
345 public: |
|
346 NotificationSink(PluginInstanceParent *aInstance) : mInstance(aInstance) |
|
347 { } |
|
348 |
|
349 virtual void DidComposite() { mInstance->DidComposite(); } |
|
350 private: |
|
351 PluginInstanceParent *mInstance; |
|
352 }; |
|
353 |
|
354 bool |
|
355 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel( |
|
356 const int& drawingModel, OptionalShmem *shmem, CrossProcessMutexHandle *mutex, NPError* result) |
|
357 { |
|
358 *shmem = null_t(); |
|
359 |
|
360 #ifdef XP_MACOSX |
|
361 if (drawingModel == NPDrawingModelCoreAnimation || |
|
362 drawingModel == NPDrawingModelInvalidatingCoreAnimation) { |
|
363 // We need to request CoreGraphics otherwise |
|
364 // the nsObjectFrame will try to draw a CALayer |
|
365 // that can not be shared across process. |
|
366 mDrawingModel = drawingModel; |
|
367 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, |
|
368 (void*)NPDrawingModelCoreGraphics); |
|
369 } else |
|
370 #endif |
|
371 if (drawingModel == NPDrawingModelAsyncBitmapSurface |
|
372 #ifdef XP_WIN |
|
373 || drawingModel == NPDrawingModelAsyncWindowsDXGISurface |
|
374 #endif |
|
375 ) { |
|
376 ImageContainer *container = GetImageContainer(); |
|
377 if (!container) { |
|
378 *result = NPERR_GENERIC_ERROR; |
|
379 return true; |
|
380 } |
|
381 |
|
382 #ifdef XP_WIN |
|
383 if (drawingModel == NPDrawingModelAsyncWindowsDXGISurface && |
|
384 gfxWindowsPlatform::GetPlatform()->GetRenderMode() != gfxWindowsPlatform::RENDER_DIRECT2D) { |
|
385 *result = NPERR_GENERIC_ERROR; |
|
386 return true; |
|
387 } |
|
388 #endif |
|
389 |
|
390 mDrawingModel = drawingModel; |
|
391 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, |
|
392 reinterpret_cast<void*>(static_cast<uintptr_t>(drawingModel))); |
|
393 |
|
394 |
|
395 if (*result != NPERR_NO_ERROR) { |
|
396 return true; |
|
397 } |
|
398 |
|
399 AllocUnsafeShmem(sizeof(RemoteImageData), SharedMemory::TYPE_BASIC, &mRemoteImageDataShmem); |
|
400 |
|
401 *shmem = mRemoteImageDataShmem; |
|
402 |
|
403 mRemoteImageDataMutex = new CrossProcessMutex("PluginInstanceParent.mRemoteImageDataMutex"); |
|
404 |
|
405 *mutex = mRemoteImageDataMutex->ShareToProcess(OtherProcess()); |
|
406 container->SetRemoteImageData(mRemoteImageDataShmem.get<RemoteImageData>(), mRemoteImageDataMutex); |
|
407 |
|
408 mNotifySink = new NotificationSink(this); |
|
409 |
|
410 container->SetCompositionNotifySink(mNotifySink); |
|
411 } else if ( |
|
412 #if defined(XP_WIN) |
|
413 drawingModel == NPDrawingModelSyncWin |
|
414 #elif defined(XP_MACOSX) |
|
415 drawingModel == NPDrawingModelOpenGL || |
|
416 drawingModel == NPDrawingModelCoreGraphics |
|
417 #elif defined(MOZ_X11) |
|
418 drawingModel == NPDrawingModelSyncX |
|
419 #else |
|
420 false |
|
421 #endif |
|
422 ) { |
|
423 *shmem = null_t(); |
|
424 |
|
425 mDrawingModel = drawingModel; |
|
426 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, |
|
427 (void*)(intptr_t)drawingModel); |
|
428 |
|
429 if (mRemoteImageDataShmem.IsWritable()) { |
|
430 if (mImageContainer) { |
|
431 mImageContainer->SetRemoteImageData(nullptr, nullptr); |
|
432 mImageContainer->SetCompositionNotifySink(nullptr); |
|
433 } |
|
434 DeallocShmem(mRemoteImageDataShmem); |
|
435 mRemoteImageDataMutex = nullptr; |
|
436 } |
|
437 } else { |
|
438 *result = NPERR_GENERIC_ERROR; |
|
439 } |
|
440 return true; |
|
441 } |
|
442 |
|
443 bool |
|
444 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel( |
|
445 const int& eventModel, NPError* result) |
|
446 { |
|
447 #ifdef XP_MACOSX |
|
448 *result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel, |
|
449 (void*)(intptr_t)eventModel); |
|
450 return true; |
|
451 #else |
|
452 *result = NPERR_GENERIC_ERROR; |
|
453 return true; |
|
454 #endif |
|
455 } |
|
456 |
|
457 bool |
|
458 PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url, |
|
459 const nsCString& target, |
|
460 NPError* result) |
|
461 { |
|
462 *result = mNPNIface->geturl(mNPP, |
|
463 NullableStringGet(url), |
|
464 NullableStringGet(target)); |
|
465 return true; |
|
466 } |
|
467 |
|
468 bool |
|
469 PluginInstanceParent::AnswerNPN_PostURL(const nsCString& url, |
|
470 const nsCString& target, |
|
471 const nsCString& buffer, |
|
472 const bool& file, |
|
473 NPError* result) |
|
474 { |
|
475 *result = mNPNIface->posturl(mNPP, url.get(), NullableStringGet(target), |
|
476 buffer.Length(), buffer.get(), file); |
|
477 return true; |
|
478 } |
|
479 |
|
480 PStreamNotifyParent* |
|
481 PluginInstanceParent::AllocPStreamNotifyParent(const nsCString& url, |
|
482 const nsCString& target, |
|
483 const bool& post, |
|
484 const nsCString& buffer, |
|
485 const bool& file, |
|
486 NPError* result) |
|
487 { |
|
488 return new StreamNotifyParent(); |
|
489 } |
|
490 |
|
491 bool |
|
492 PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor, |
|
493 const nsCString& url, |
|
494 const nsCString& target, |
|
495 const bool& post, |
|
496 const nsCString& buffer, |
|
497 const bool& file, |
|
498 NPError* result) |
|
499 { |
|
500 bool streamDestroyed = false; |
|
501 static_cast<StreamNotifyParent*>(actor)-> |
|
502 SetDestructionFlag(&streamDestroyed); |
|
503 |
|
504 if (!post) { |
|
505 *result = mNPNIface->geturlnotify(mNPP, |
|
506 NullableStringGet(url), |
|
507 NullableStringGet(target), |
|
508 actor); |
|
509 } |
|
510 else { |
|
511 *result = mNPNIface->posturlnotify(mNPP, |
|
512 NullableStringGet(url), |
|
513 NullableStringGet(target), |
|
514 buffer.Length(), |
|
515 NullableStringGet(buffer), |
|
516 file, actor); |
|
517 } |
|
518 |
|
519 if (streamDestroyed) { |
|
520 // If the stream was destroyed, we must return an error code in the |
|
521 // constructor. |
|
522 *result = NPERR_GENERIC_ERROR; |
|
523 } |
|
524 else { |
|
525 static_cast<StreamNotifyParent*>(actor)->ClearDestructionFlag(); |
|
526 if (*result != NPERR_NO_ERROR) |
|
527 return PStreamNotifyParent::Send__delete__(actor, |
|
528 NPERR_GENERIC_ERROR); |
|
529 } |
|
530 |
|
531 return true; |
|
532 } |
|
533 |
|
534 bool |
|
535 PluginInstanceParent::DeallocPStreamNotifyParent(PStreamNotifyParent* notifyData) |
|
536 { |
|
537 delete notifyData; |
|
538 return true; |
|
539 } |
|
540 |
|
541 bool |
|
542 PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect) |
|
543 { |
|
544 mNPNIface->invalidaterect(mNPP, const_cast<NPRect*>(&rect)); |
|
545 return true; |
|
546 } |
|
547 |
|
548 bool |
|
549 PluginInstanceParent::RecvShow(const NPRect& updatedRect, |
|
550 const SurfaceDescriptor& newSurface, |
|
551 SurfaceDescriptor* prevSurface) |
|
552 { |
|
553 PLUGIN_LOG_DEBUG( |
|
554 ("[InstanceParent][%p] RecvShow for <x=%d,y=%d, w=%d,h=%d>", |
|
555 this, updatedRect.left, updatedRect.top, |
|
556 updatedRect.right - updatedRect.left, |
|
557 updatedRect.bottom - updatedRect.top)); |
|
558 |
|
559 // XXXjwatt rewrite to use Moz2D |
|
560 nsRefPtr<gfxASurface> surface; |
|
561 if (newSurface.type() == SurfaceDescriptor::TShmem) { |
|
562 if (!newSurface.get_Shmem().IsReadable()) { |
|
563 NS_WARNING("back surface not readable"); |
|
564 return false; |
|
565 } |
|
566 surface = gfxSharedImageSurface::Open(newSurface.get_Shmem()); |
|
567 } |
|
568 #ifdef XP_MACOSX |
|
569 else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) { |
|
570 IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor(); |
|
571 |
|
572 RefPtr<MacIOSurface> newIOSurface = |
|
573 MacIOSurface::LookupSurface(iodesc.surfaceId(), |
|
574 iodesc.contentsScaleFactor()); |
|
575 |
|
576 if (!newIOSurface) { |
|
577 NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow"); |
|
578 return false; |
|
579 } |
|
580 |
|
581 if (mFrontIOSurface) |
|
582 *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID(), |
|
583 mFrontIOSurface->GetContentsScaleFactor()); |
|
584 else |
|
585 *prevSurface = null_t(); |
|
586 |
|
587 mFrontIOSurface = newIOSurface; |
|
588 |
|
589 RecvNPN_InvalidateRect(updatedRect); |
|
590 |
|
591 PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)", |
|
592 mFrontSurface.get())); |
|
593 |
|
594 return true; |
|
595 } |
|
596 #endif |
|
597 #ifdef MOZ_X11 |
|
598 else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) { |
|
599 surface = newSurface.get_SurfaceDescriptorX11().OpenForeign(); |
|
600 } |
|
601 #endif |
|
602 #ifdef XP_WIN |
|
603 else if (newSurface.type() == SurfaceDescriptor::TPPluginSurfaceParent) { |
|
604 PluginSurfaceParent* s = |
|
605 static_cast<PluginSurfaceParent*>(newSurface.get_PPluginSurfaceParent()); |
|
606 surface = s->Surface(); |
|
607 } |
|
608 #endif |
|
609 |
|
610 if (mFrontSurface) { |
|
611 // This is the "old front buffer" we're about to hand back to |
|
612 // the plugin. We might still have drawing operations |
|
613 // referencing it. |
|
614 #ifdef MOZ_X11 |
|
615 if (mFrontSurface->GetType() == gfxSurfaceType::Xlib) { |
|
616 // Finish with the surface and XSync here to ensure the server has |
|
617 // finished operations on the surface before the plugin starts |
|
618 // scribbling on it again, or worse, destroys it. |
|
619 mFrontSurface->Finish(); |
|
620 FinishX(DefaultXDisplay()); |
|
621 } else |
|
622 #endif |
|
623 { |
|
624 mFrontSurface->Flush(); |
|
625 } |
|
626 } |
|
627 |
|
628 if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface)) |
|
629 *prevSurface = static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem(); |
|
630 else |
|
631 *prevSurface = null_t(); |
|
632 |
|
633 if (surface) { |
|
634 // Notify the cairo backend that this surface has changed behind |
|
635 // its back. |
|
636 gfxRect ur(updatedRect.left, updatedRect.top, |
|
637 updatedRect.right - updatedRect.left, |
|
638 updatedRect.bottom - updatedRect.top); |
|
639 surface->MarkDirty(ur); |
|
640 |
|
641 ImageContainer *container = GetImageContainer(); |
|
642 nsRefPtr<Image> image = container->CreateImage(ImageFormat::CAIRO_SURFACE); |
|
643 NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?"); |
|
644 CairoImage* cairoImage = static_cast<CairoImage*>(image.get()); |
|
645 CairoImage::Data cairoData; |
|
646 cairoData.mSize = surface->GetSize().ToIntSize(); |
|
647 cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface); |
|
648 cairoImage->SetData(cairoData); |
|
649 |
|
650 container->SetCurrentImage(cairoImage); |
|
651 } |
|
652 else if (mImageContainer) { |
|
653 mImageContainer->SetCurrentImage(nullptr); |
|
654 } |
|
655 |
|
656 mFrontSurface = surface; |
|
657 RecvNPN_InvalidateRect(updatedRect); |
|
658 |
|
659 PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)", |
|
660 mFrontSurface.get())); |
|
661 |
|
662 return true; |
|
663 } |
|
664 |
|
665 nsresult |
|
666 PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow) |
|
667 { |
|
668 NPRemoteWindow window; |
|
669 mWindowType = aWindow->type; |
|
670 window.window = reinterpret_cast<uint64_t>(aWindow->window); |
|
671 window.x = aWindow->x; |
|
672 window.y = aWindow->y; |
|
673 window.width = aWindow->width; |
|
674 window.height = aWindow->height; |
|
675 window.clipRect = aWindow->clipRect; |
|
676 window.type = aWindow->type; |
|
677 #ifdef XP_MACOSX |
|
678 double scaleFactor = 1.0; |
|
679 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); |
|
680 window.contentsScaleFactor = scaleFactor; |
|
681 #endif |
|
682 if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(), |
|
683 window)) |
|
684 return NS_ERROR_FAILURE; |
|
685 |
|
686 return NS_OK; |
|
687 } |
|
688 |
|
689 nsresult |
|
690 PluginInstanceParent::GetImageContainer(ImageContainer** aContainer) |
|
691 { |
|
692 #ifdef XP_MACOSX |
|
693 MacIOSurface* ioSurface = nullptr; |
|
694 |
|
695 if (mFrontIOSurface) { |
|
696 ioSurface = mFrontIOSurface; |
|
697 } else if (mIOSurface) { |
|
698 ioSurface = mIOSurface; |
|
699 } |
|
700 |
|
701 if (!mFrontSurface && !ioSurface) |
|
702 #else |
|
703 if (!mFrontSurface) |
|
704 #endif |
|
705 return NS_ERROR_NOT_AVAILABLE; |
|
706 |
|
707 ImageContainer *container = GetImageContainer(); |
|
708 |
|
709 if (!container) { |
|
710 return NS_ERROR_FAILURE; |
|
711 } |
|
712 |
|
713 if (IsAsyncDrawing()) { |
|
714 NS_IF_ADDREF(container); |
|
715 *aContainer = container; |
|
716 return NS_OK; |
|
717 } |
|
718 |
|
719 #ifdef XP_MACOSX |
|
720 if (ioSurface) { |
|
721 nsRefPtr<Image> image = container->CreateImage(ImageFormat::MAC_IOSURFACE); |
|
722 if (!image) { |
|
723 return NS_ERROR_FAILURE; |
|
724 } |
|
725 |
|
726 NS_ASSERTION(image->GetFormat() == ImageFormat::MAC_IOSURFACE, "Wrong format?"); |
|
727 |
|
728 MacIOSurfaceImage* pluginImage = static_cast<MacIOSurfaceImage*>(image.get()); |
|
729 pluginImage->SetSurface(ioSurface); |
|
730 |
|
731 container->SetCurrentImageInTransaction(pluginImage); |
|
732 |
|
733 NS_IF_ADDREF(container); |
|
734 *aContainer = container; |
|
735 return NS_OK; |
|
736 } |
|
737 #endif |
|
738 |
|
739 NS_IF_ADDREF(container); |
|
740 *aContainer = container; |
|
741 return NS_OK; |
|
742 } |
|
743 |
|
744 nsresult |
|
745 PluginInstanceParent::GetImageSize(nsIntSize* aSize) |
|
746 { |
|
747 if (mFrontSurface) { |
|
748 gfxIntSize size = mFrontSurface->GetSize(); |
|
749 *aSize = nsIntSize(size.width, size.height); |
|
750 return NS_OK; |
|
751 } |
|
752 |
|
753 #ifdef XP_MACOSX |
|
754 if (mFrontIOSurface) { |
|
755 *aSize = nsIntSize(mFrontIOSurface->GetWidth(), mFrontIOSurface->GetHeight()); |
|
756 return NS_OK; |
|
757 } else if (mIOSurface) { |
|
758 *aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight()); |
|
759 return NS_OK; |
|
760 } |
|
761 #endif |
|
762 |
|
763 return NS_ERROR_NOT_AVAILABLE; |
|
764 } |
|
765 |
|
766 #ifdef XP_MACOSX |
|
767 nsresult |
|
768 PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing) |
|
769 { |
|
770 *aDrawing = (NPDrawingModelCoreAnimation == (NPDrawingModel)mDrawingModel || |
|
771 NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel); |
|
772 return NS_OK; |
|
773 } |
|
774 |
|
775 nsresult |
|
776 PluginInstanceParent::ContentsScaleFactorChanged(double aContentsScaleFactor) |
|
777 { |
|
778 bool rv = SendContentsScaleFactorChanged(aContentsScaleFactor); |
|
779 return rv ? NS_OK : NS_ERROR_FAILURE; |
|
780 } |
|
781 #endif // #ifdef XP_MACOSX |
|
782 |
|
783 nsresult |
|
784 PluginInstanceParent::SetBackgroundUnknown() |
|
785 { |
|
786 PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this)); |
|
787 |
|
788 if (mBackground) { |
|
789 DestroyBackground(); |
|
790 NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed"); |
|
791 } |
|
792 |
|
793 return NS_OK; |
|
794 } |
|
795 |
|
796 nsresult |
|
797 PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect, |
|
798 gfxContext** aCtx) |
|
799 { |
|
800 PLUGIN_LOG_DEBUG( |
|
801 ("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>", |
|
802 this, aRect.x, aRect.y, aRect.width, aRect.height)); |
|
803 |
|
804 if (!mBackground) { |
|
805 // XXX if we failed to create a background surface on one |
|
806 // update, there's no guarantee that later updates will be for |
|
807 // the entire background area until successful. We might want |
|
808 // to fix that eventually. |
|
809 NS_ABORT_IF_FALSE(aRect.TopLeft() == nsIntPoint(0, 0), |
|
810 "Expecting rect for whole frame"); |
|
811 if (!CreateBackground(aRect.Size())) { |
|
812 *aCtx = nullptr; |
|
813 return NS_OK; |
|
814 } |
|
815 } |
|
816 |
|
817 gfxIntSize sz = mBackground->GetSize(); |
|
818 #ifdef DEBUG |
|
819 NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect), |
|
820 "Update outside of background area"); |
|
821 #endif |
|
822 |
|
823 RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()-> |
|
824 CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height)); |
|
825 nsRefPtr<gfxContext> ctx = new gfxContext(dt); |
|
826 ctx.forget(aCtx); |
|
827 |
|
828 return NS_OK; |
|
829 } |
|
830 |
|
831 nsresult |
|
832 PluginInstanceParent::EndUpdateBackground(gfxContext* aCtx, |
|
833 const nsIntRect& aRect) |
|
834 { |
|
835 PLUGIN_LOG_DEBUG( |
|
836 ("[InstanceParent][%p] EndUpdateBackground for <x=%d,y=%d, w=%d,h=%d>", |
|
837 this, aRect.x, aRect.y, aRect.width, aRect.height)); |
|
838 |
|
839 #ifdef MOZ_X11 |
|
840 // Have to XSync here to avoid the plugin trying to draw with this |
|
841 // surface racing with its creation in the X server. We also want |
|
842 // to avoid the plugin drawing onto stale pixels, then handing us |
|
843 // back a front surface from those pixels that we might |
|
844 // recomposite for "a while" until the next update. This XSync |
|
845 // still doesn't guarantee that the plugin draws onto a consistent |
|
846 // view of its background, but it does mean that the plugin is |
|
847 // drawing onto pixels no older than those in the latest |
|
848 // EndUpdateBackground(). |
|
849 XSync(DefaultXDisplay(), False); |
|
850 #endif |
|
851 |
|
852 unused << SendUpdateBackground(BackgroundDescriptor(), aRect); |
|
853 |
|
854 return NS_OK; |
|
855 } |
|
856 |
|
857 bool |
|
858 PluginInstanceParent::CreateBackground(const nsIntSize& aSize) |
|
859 { |
|
860 NS_ABORT_IF_FALSE(!mBackground, "Already have a background"); |
|
861 |
|
862 // XXX refactor me |
|
863 |
|
864 #if defined(MOZ_X11) |
|
865 Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay()); |
|
866 Visual* visual = DefaultVisualOfScreen(screen); |
|
867 mBackground = gfxXlibSurface::Create(screen, visual, |
|
868 gfxIntSize(aSize.width, aSize.height)); |
|
869 return !!mBackground; |
|
870 |
|
871 #elif defined(XP_WIN) |
|
872 // We have chosen to create an unsafe surface in which the plugin |
|
873 // can read from the region while we're writing to it. |
|
874 mBackground = |
|
875 gfxSharedImageSurface::CreateUnsafe( |
|
876 this, |
|
877 gfxIntSize(aSize.width, aSize.height), |
|
878 gfxImageFormat::RGB24); |
|
879 return !!mBackground; |
|
880 #else |
|
881 return nullptr; |
|
882 #endif |
|
883 } |
|
884 |
|
885 void |
|
886 PluginInstanceParent::DestroyBackground() |
|
887 { |
|
888 if (!mBackground) { |
|
889 return; |
|
890 } |
|
891 |
|
892 // Relinquish ownership of |mBackground| to its destroyer |
|
893 PPluginBackgroundDestroyerParent* pbd = |
|
894 new PluginBackgroundDestroyerParent(mBackground); |
|
895 mBackground = nullptr; |
|
896 |
|
897 // If this fails, there's no problem: |bd| will be destroyed along |
|
898 // with the old background surface. |
|
899 unused << SendPPluginBackgroundDestroyerConstructor(pbd); |
|
900 } |
|
901 |
|
902 mozilla::plugins::SurfaceDescriptor |
|
903 PluginInstanceParent::BackgroundDescriptor() |
|
904 { |
|
905 NS_ABORT_IF_FALSE(mBackground, "Need a background here"); |
|
906 |
|
907 // XXX refactor me |
|
908 |
|
909 #ifdef MOZ_X11 |
|
910 gfxXlibSurface* xsurf = static_cast<gfxXlibSurface*>(mBackground.get()); |
|
911 return SurfaceDescriptorX11(xsurf); |
|
912 #endif |
|
913 |
|
914 #ifdef XP_WIN |
|
915 NS_ABORT_IF_FALSE(gfxSharedImageSurface::IsSharedImage(mBackground), |
|
916 "Expected shared image surface"); |
|
917 gfxSharedImageSurface* shmem = |
|
918 static_cast<gfxSharedImageSurface*>(mBackground.get()); |
|
919 return shmem->GetShmem(); |
|
920 #endif |
|
921 |
|
922 // If this is ever used, which it shouldn't be, it will trigger a |
|
923 // hard assertion in IPDL-generated code. |
|
924 return mozilla::plugins::SurfaceDescriptor(); |
|
925 } |
|
926 |
|
927 ImageContainer* |
|
928 PluginInstanceParent::GetImageContainer() |
|
929 { |
|
930 if (mImageContainer) { |
|
931 return mImageContainer; |
|
932 } |
|
933 |
|
934 mImageContainer = LayerManager::CreateImageContainer(); |
|
935 return mImageContainer; |
|
936 } |
|
937 |
|
938 PPluginBackgroundDestroyerParent* |
|
939 PluginInstanceParent::AllocPPluginBackgroundDestroyerParent() |
|
940 { |
|
941 NS_RUNTIMEABORT("'Power-user' ctor is used exclusively"); |
|
942 return nullptr; |
|
943 } |
|
944 |
|
945 bool |
|
946 PluginInstanceParent::DeallocPPluginBackgroundDestroyerParent( |
|
947 PPluginBackgroundDestroyerParent* aActor) |
|
948 { |
|
949 delete aActor; |
|
950 return true; |
|
951 } |
|
952 |
|
953 NPError |
|
954 PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) |
|
955 { |
|
956 PLUGIN_LOG_DEBUG(("%s (aWindow=%p)", FULLFUNCTION, (void*) aWindow)); |
|
957 |
|
958 NS_ENSURE_TRUE(aWindow, NPERR_GENERIC_ERROR); |
|
959 |
|
960 NPRemoteWindow window; |
|
961 mWindowType = aWindow->type; |
|
962 |
|
963 #if defined(OS_WIN) |
|
964 // On windowless controls, reset the shared memory surface as needed. |
|
965 if (mWindowType == NPWindowTypeDrawable) { |
|
966 // SharedSurfaceSetWindow will take care of NPRemoteWindow. |
|
967 if (!SharedSurfaceSetWindow(aWindow, window)) { |
|
968 return NPERR_OUT_OF_MEMORY_ERROR; |
|
969 } |
|
970 } |
|
971 else { |
|
972 SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window)); |
|
973 |
|
974 window.window = reinterpret_cast<uint64_t>(aWindow->window); |
|
975 window.x = aWindow->x; |
|
976 window.y = aWindow->y; |
|
977 window.width = aWindow->width; |
|
978 window.height = aWindow->height; |
|
979 window.type = aWindow->type; |
|
980 } |
|
981 #else |
|
982 window.window = reinterpret_cast<uint64_t>(aWindow->window); |
|
983 window.x = aWindow->x; |
|
984 window.y = aWindow->y; |
|
985 window.width = aWindow->width; |
|
986 window.height = aWindow->height; |
|
987 window.clipRect = aWindow->clipRect; // MacOS specific |
|
988 window.type = aWindow->type; |
|
989 #endif |
|
990 |
|
991 #if defined(XP_MACOSX) |
|
992 double floatScaleFactor = 1.0; |
|
993 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor); |
|
994 int scaleFactor = ceil(floatScaleFactor); |
|
995 window.contentsScaleFactor = floatScaleFactor; |
|
996 |
|
997 if (mShWidth != window.width * scaleFactor || mShHeight != window.height * scaleFactor) { |
|
998 if (mDrawingModel == NPDrawingModelCoreAnimation || |
|
999 mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) { |
|
1000 mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height, |
|
1001 floatScaleFactor); |
|
1002 } else if (uint32_t(mShWidth * mShHeight) != |
|
1003 window.width * scaleFactor * window.height * scaleFactor) { |
|
1004 if (mShWidth != 0 && mShHeight != 0) { |
|
1005 DeallocShmem(mShSurface); |
|
1006 mShWidth = 0; |
|
1007 mShHeight = 0; |
|
1008 } |
|
1009 |
|
1010 if (window.width != 0 && window.height != 0) { |
|
1011 if (!AllocShmem(window.width * scaleFactor * window.height*4 * scaleFactor, |
|
1012 SharedMemory::TYPE_BASIC, &mShSurface)) { |
|
1013 PLUGIN_LOG_DEBUG(("Shared memory could not be allocated.")); |
|
1014 return NPERR_GENERIC_ERROR; |
|
1015 } |
|
1016 } |
|
1017 } |
|
1018 mShWidth = window.width * scaleFactor; |
|
1019 mShHeight = window.height * scaleFactor; |
|
1020 } |
|
1021 #endif |
|
1022 |
|
1023 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) |
|
1024 const NPSetWindowCallbackStruct* ws_info = |
|
1025 static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info); |
|
1026 window.visualID = ws_info->visual ? ws_info->visual->visualid : None; |
|
1027 window.colormap = ws_info->colormap; |
|
1028 #endif |
|
1029 |
|
1030 if (!CallNPP_SetWindow(window)) |
|
1031 return NPERR_GENERIC_ERROR; |
|
1032 |
|
1033 return NPERR_NO_ERROR; |
|
1034 } |
|
1035 |
|
1036 NPError |
|
1037 PluginInstanceParent::NPP_GetValue(NPPVariable aVariable, |
|
1038 void* _retval) |
|
1039 { |
|
1040 switch (aVariable) { |
|
1041 |
|
1042 case NPPVpluginWantsAllNetworkStreams: { |
|
1043 bool wantsAllStreams; |
|
1044 NPError rv; |
|
1045 |
|
1046 if (!CallNPP_GetValue_NPPVpluginWantsAllNetworkStreams(&wantsAllStreams, &rv)) { |
|
1047 return NPERR_GENERIC_ERROR; |
|
1048 } |
|
1049 |
|
1050 if (NPERR_NO_ERROR != rv) { |
|
1051 return rv; |
|
1052 } |
|
1053 |
|
1054 (*(NPBool*)_retval) = wantsAllStreams; |
|
1055 return NPERR_NO_ERROR; |
|
1056 } |
|
1057 |
|
1058 #ifdef MOZ_X11 |
|
1059 case NPPVpluginNeedsXEmbed: { |
|
1060 bool needsXEmbed; |
|
1061 NPError rv; |
|
1062 |
|
1063 if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed, &rv)) { |
|
1064 return NPERR_GENERIC_ERROR; |
|
1065 } |
|
1066 |
|
1067 if (NPERR_NO_ERROR != rv) { |
|
1068 return rv; |
|
1069 } |
|
1070 |
|
1071 (*(NPBool*)_retval) = needsXEmbed; |
|
1072 return NPERR_NO_ERROR; |
|
1073 } |
|
1074 #endif |
|
1075 |
|
1076 case NPPVpluginScriptableNPObject: { |
|
1077 PPluginScriptableObjectParent* actor; |
|
1078 NPError rv; |
|
1079 if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor, &rv)) { |
|
1080 return NPERR_GENERIC_ERROR; |
|
1081 } |
|
1082 |
|
1083 if (NPERR_NO_ERROR != rv) { |
|
1084 return rv; |
|
1085 } |
|
1086 |
|
1087 if (!actor) { |
|
1088 NS_ERROR("NPPVpluginScriptableNPObject succeeded but null."); |
|
1089 return NPERR_GENERIC_ERROR; |
|
1090 } |
|
1091 |
|
1092 const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs(); |
|
1093 if (!npn) { |
|
1094 NS_WARNING("No netscape functions?!"); |
|
1095 return NPERR_GENERIC_ERROR; |
|
1096 } |
|
1097 |
|
1098 NPObject* object = |
|
1099 static_cast<PluginScriptableObjectParent*>(actor)->GetObject(true); |
|
1100 NS_ASSERTION(object, "This shouldn't ever be null!"); |
|
1101 |
|
1102 (*(NPObject**)_retval) = npn->retainobject(object); |
|
1103 return NPERR_NO_ERROR; |
|
1104 } |
|
1105 |
|
1106 #ifdef MOZ_ACCESSIBILITY_ATK |
|
1107 case NPPVpluginNativeAccessibleAtkPlugId: { |
|
1108 nsCString plugId; |
|
1109 NPError rv; |
|
1110 if (!CallNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(&plugId, &rv)) { |
|
1111 return NPERR_GENERIC_ERROR; |
|
1112 } |
|
1113 |
|
1114 if (NPERR_NO_ERROR != rv) { |
|
1115 return rv; |
|
1116 } |
|
1117 |
|
1118 (*(nsCString*)_retval) = plugId; |
|
1119 return NPERR_NO_ERROR; |
|
1120 } |
|
1121 #endif |
|
1122 |
|
1123 default: |
|
1124 PR_LOG(GetPluginLog(), PR_LOG_WARNING, |
|
1125 ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)", |
|
1126 (int) aVariable, NPPVariableToString(aVariable))); |
|
1127 return NPERR_GENERIC_ERROR; |
|
1128 } |
|
1129 } |
|
1130 |
|
1131 NPError |
|
1132 PluginInstanceParent::NPP_SetValue(NPNVariable variable, void* value) |
|
1133 { |
|
1134 switch (variable) { |
|
1135 case NPNVprivateModeBool: |
|
1136 NPError result; |
|
1137 if (!CallNPP_SetValue_NPNVprivateModeBool(*static_cast<NPBool*>(value), |
|
1138 &result)) |
|
1139 return NPERR_GENERIC_ERROR; |
|
1140 |
|
1141 return result; |
|
1142 |
|
1143 default: |
|
1144 NS_ERROR("Unhandled NPNVariable in NPP_SetValue"); |
|
1145 PR_LOG(GetPluginLog(), PR_LOG_WARNING, |
|
1146 ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)", |
|
1147 (int) variable, NPNVariableToString(variable))); |
|
1148 return NPERR_GENERIC_ERROR; |
|
1149 } |
|
1150 } |
|
1151 |
|
1152 void |
|
1153 PluginInstanceParent::NPP_URLRedirectNotify(const char* url, int32_t status, |
|
1154 void* notifyData) |
|
1155 { |
|
1156 if (!notifyData) |
|
1157 return; |
|
1158 |
|
1159 PStreamNotifyParent* streamNotify = static_cast<PStreamNotifyParent*>(notifyData); |
|
1160 unused << streamNotify->SendRedirectNotify(NullableString(url), status); |
|
1161 } |
|
1162 |
|
1163 int16_t |
|
1164 PluginInstanceParent::NPP_HandleEvent(void* event) |
|
1165 { |
|
1166 PLUGIN_LOG_DEBUG_FUNCTION; |
|
1167 |
|
1168 #if defined(XP_MACOSX) |
|
1169 NPCocoaEvent* npevent = reinterpret_cast<NPCocoaEvent*>(event); |
|
1170 #else |
|
1171 NPEvent* npevent = reinterpret_cast<NPEvent*>(event); |
|
1172 #endif |
|
1173 NPRemoteEvent npremoteevent; |
|
1174 npremoteevent.event = *npevent; |
|
1175 #if defined(XP_MACOSX) |
|
1176 double scaleFactor = 1.0; |
|
1177 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); |
|
1178 npremoteevent.contentsScaleFactor = scaleFactor; |
|
1179 #endif |
|
1180 int16_t handled = 0; |
|
1181 |
|
1182 #if defined(OS_WIN) |
|
1183 if (mWindowType == NPWindowTypeDrawable) { |
|
1184 if (IsAsyncDrawing()) { |
|
1185 if (npevent->event == WM_PAINT || npevent->event == DoublePassRenderingEvent()) { |
|
1186 // This plugin maintains its own async drawing. |
|
1187 return handled; |
|
1188 } |
|
1189 } |
|
1190 if (DoublePassRenderingEvent() == npevent->event) { |
|
1191 return CallPaint(npremoteevent, &handled) && handled; |
|
1192 } |
|
1193 |
|
1194 switch (npevent->event) { |
|
1195 case WM_PAINT: |
|
1196 { |
|
1197 RECT rect; |
|
1198 SharedSurfaceBeforePaint(rect, npremoteevent); |
|
1199 if (!CallPaint(npremoteevent, &handled)) { |
|
1200 handled = false; |
|
1201 } |
|
1202 SharedSurfaceAfterPaint(npevent); |
|
1203 return handled; |
|
1204 } |
|
1205 break; |
|
1206 |
|
1207 case WM_KILLFOCUS: |
|
1208 { |
|
1209 // When the user selects fullscreen mode in Flash video players, |
|
1210 // WM_KILLFOCUS will be delayed by deferred event processing: |
|
1211 // WM_LBUTTONUP results in a call to CreateWindow within Flash, |
|
1212 // which fires WM_KILLFOCUS. Delayed delivery causes Flash to |
|
1213 // misinterpret the event, dropping back out of fullscreen. Trap |
|
1214 // this event and drop it. |
|
1215 wchar_t szClass[26]; |
|
1216 HWND hwnd = GetForegroundWindow(); |
|
1217 if (hwnd && hwnd != mPluginHWND && |
|
1218 GetClassNameW(hwnd, szClass, |
|
1219 sizeof(szClass)/sizeof(char16_t)) && |
|
1220 !wcscmp(szClass, kFlashFullscreenClass)) { |
|
1221 return 0; |
|
1222 } |
|
1223 } |
|
1224 break; |
|
1225 |
|
1226 case WM_WINDOWPOSCHANGED: |
|
1227 { |
|
1228 // We send this in nsObjectFrame just before painting |
|
1229 return SendWindowPosChanged(npremoteevent); |
|
1230 } |
|
1231 break; |
|
1232 } |
|
1233 } |
|
1234 #endif |
|
1235 |
|
1236 #if defined(MOZ_X11) |
|
1237 switch (npevent->type) { |
|
1238 case GraphicsExpose: |
|
1239 PLUGIN_LOG_DEBUG((" schlepping drawable 0x%lx across the pipe\n", |
|
1240 npevent->xgraphicsexpose.drawable)); |
|
1241 // Make sure the X server has created the Drawable and completes any |
|
1242 // drawing before the plugin draws on top. |
|
1243 // |
|
1244 // XSync() waits for the X server to complete. Really this parent |
|
1245 // process does not need to wait; the child is the process that needs |
|
1246 // to wait. A possibly-slightly-better alternative would be to send |
|
1247 // an X event to the child that the child would wait for. |
|
1248 FinishX(DefaultXDisplay()); |
|
1249 |
|
1250 return CallPaint(npremoteevent, &handled) ? handled : 0; |
|
1251 |
|
1252 case ButtonPress: |
|
1253 // Release any active pointer grab so that the plugin X client can |
|
1254 // grab the pointer if it wishes. |
|
1255 Display *dpy = DefaultXDisplay(); |
|
1256 # ifdef MOZ_WIDGET_GTK |
|
1257 // GDK attempts to (asynchronously) track whether there is an active |
|
1258 // grab so ungrab through GDK. |
|
1259 gdk_pointer_ungrab(npevent->xbutton.time); |
|
1260 # else |
|
1261 XUngrabPointer(dpy, npevent->xbutton.time); |
|
1262 # endif |
|
1263 // Wait for the ungrab to complete. |
|
1264 XSync(dpy, False); |
|
1265 break; |
|
1266 } |
|
1267 #endif |
|
1268 |
|
1269 #ifdef XP_MACOSX |
|
1270 if (npevent->type == NPCocoaEventDrawRect) { |
|
1271 if (mDrawingModel == NPDrawingModelCoreAnimation || |
|
1272 mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) { |
|
1273 if (!mIOSurface) { |
|
1274 NS_ERROR("No IOSurface allocated."); |
|
1275 return false; |
|
1276 } |
|
1277 if (!CallNPP_HandleEvent_IOSurface(npremoteevent, |
|
1278 mIOSurface->GetIOSurfaceID(), |
|
1279 &handled)) |
|
1280 return false; // no good way to handle errors here... |
|
1281 |
|
1282 CGContextRef cgContext = npevent->data.draw.context; |
|
1283 if (!mShColorSpace) { |
|
1284 mShColorSpace = CreateSystemColorSpace(); |
|
1285 } |
|
1286 if (!mShColorSpace) { |
|
1287 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); |
|
1288 return false; |
|
1289 } |
|
1290 if (cgContext) { |
|
1291 nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface, |
|
1292 mShColorSpace, |
|
1293 npevent->data.draw.x, |
|
1294 npevent->data.draw.y, |
|
1295 npevent->data.draw.width, |
|
1296 npevent->data.draw.height); |
|
1297 } |
|
1298 return true; |
|
1299 } else if (mFrontIOSurface) { |
|
1300 CGContextRef cgContext = npevent->data.draw.context; |
|
1301 if (!mShColorSpace) { |
|
1302 mShColorSpace = CreateSystemColorSpace(); |
|
1303 } |
|
1304 if (!mShColorSpace) { |
|
1305 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); |
|
1306 return false; |
|
1307 } |
|
1308 if (cgContext) { |
|
1309 nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface, |
|
1310 mShColorSpace, |
|
1311 npevent->data.draw.x, |
|
1312 npevent->data.draw.y, |
|
1313 npevent->data.draw.width, |
|
1314 npevent->data.draw.height); |
|
1315 } |
|
1316 return true; |
|
1317 } else { |
|
1318 if (mShWidth == 0 && mShHeight == 0) { |
|
1319 PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0.")); |
|
1320 return false; |
|
1321 } |
|
1322 if (!mShSurface.IsReadable()) { |
|
1323 PLUGIN_LOG_DEBUG(("Shmem is not readable.")); |
|
1324 return false; |
|
1325 } |
|
1326 |
|
1327 if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, |
|
1328 &handled, &mShSurface)) |
|
1329 return false; // no good way to handle errors here... |
|
1330 |
|
1331 if (!mShSurface.IsReadable()) { |
|
1332 PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed " |
|
1333 "or we have a bug.")); |
|
1334 return false; |
|
1335 } |
|
1336 |
|
1337 char* shContextByte = mShSurface.get<char>(); |
|
1338 |
|
1339 if (!mShColorSpace) { |
|
1340 mShColorSpace = CreateSystemColorSpace(); |
|
1341 } |
|
1342 if (!mShColorSpace) { |
|
1343 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); |
|
1344 return false; |
|
1345 } |
|
1346 CGContextRef shContext = ::CGBitmapContextCreate(shContextByte, |
|
1347 mShWidth, mShHeight, 8, |
|
1348 mShWidth*4, mShColorSpace, |
|
1349 kCGImageAlphaPremultipliedFirst | |
|
1350 kCGBitmapByteOrder32Host); |
|
1351 if (!shContext) { |
|
1352 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); |
|
1353 return false; |
|
1354 } |
|
1355 |
|
1356 CGImageRef shImage = ::CGBitmapContextCreateImage(shContext); |
|
1357 if (shImage) { |
|
1358 CGContextRef cgContext = npevent->data.draw.context; |
|
1359 |
|
1360 ::CGContextDrawImage(cgContext, |
|
1361 CGRectMake(0,0,mShWidth,mShHeight), |
|
1362 shImage); |
|
1363 ::CGImageRelease(shImage); |
|
1364 } else { |
|
1365 ::CGContextRelease(shContext); |
|
1366 return false; |
|
1367 } |
|
1368 ::CGContextRelease(shContext); |
|
1369 return true; |
|
1370 } |
|
1371 } |
|
1372 #endif |
|
1373 |
|
1374 if (!CallNPP_HandleEvent(npremoteevent, &handled)) |
|
1375 return 0; // no good way to handle errors here... |
|
1376 |
|
1377 return handled; |
|
1378 } |
|
1379 |
|
1380 NPError |
|
1381 PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream, |
|
1382 NPBool seekable, uint16_t* stype) |
|
1383 { |
|
1384 PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)", |
|
1385 FULLFUNCTION, (char*) type, (void*) stream, (int) seekable)); |
|
1386 |
|
1387 BrowserStreamParent* bs = new BrowserStreamParent(this, stream); |
|
1388 |
|
1389 NPError err; |
|
1390 if (!CallPBrowserStreamConstructor(bs, |
|
1391 NullableString(stream->url), |
|
1392 stream->end, |
|
1393 stream->lastmodified, |
|
1394 static_cast<PStreamNotifyParent*>(stream->notifyData), |
|
1395 NullableString(stream->headers), |
|
1396 NullableString(type), seekable, |
|
1397 &err, stype)) |
|
1398 return NPERR_GENERIC_ERROR; |
|
1399 |
|
1400 if (NPERR_NO_ERROR != err) |
|
1401 unused << PBrowserStreamParent::Send__delete__(bs); |
|
1402 |
|
1403 return err; |
|
1404 } |
|
1405 |
|
1406 NPError |
|
1407 PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason) |
|
1408 { |
|
1409 PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)", |
|
1410 FULLFUNCTION, (void*) stream, (int) reason)); |
|
1411 |
|
1412 AStream* s = static_cast<AStream*>(stream->pdata); |
|
1413 if (s->IsBrowserStream()) { |
|
1414 BrowserStreamParent* sp = |
|
1415 static_cast<BrowserStreamParent*>(s); |
|
1416 if (sp->mNPP != this) |
|
1417 NS_RUNTIMEABORT("Mismatched plugin data"); |
|
1418 |
|
1419 sp->NPP_DestroyStream(reason); |
|
1420 return NPERR_NO_ERROR; |
|
1421 } |
|
1422 else { |
|
1423 PluginStreamParent* sp = |
|
1424 static_cast<PluginStreamParent*>(s); |
|
1425 if (sp->mInstance != this) |
|
1426 NS_RUNTIMEABORT("Mismatched plugin data"); |
|
1427 |
|
1428 return PPluginStreamParent::Call__delete__(sp, reason, false) ? |
|
1429 NPERR_NO_ERROR : NPERR_GENERIC_ERROR; |
|
1430 } |
|
1431 } |
|
1432 |
|
1433 void |
|
1434 PluginInstanceParent::NPP_Print(NPPrint* platformPrint) |
|
1435 { |
|
1436 // TODO: implement me |
|
1437 NS_ERROR("Not implemented"); |
|
1438 } |
|
1439 |
|
1440 PPluginScriptableObjectParent* |
|
1441 PluginInstanceParent::AllocPPluginScriptableObjectParent() |
|
1442 { |
|
1443 return new PluginScriptableObjectParent(Proxy); |
|
1444 } |
|
1445 |
|
1446 #ifdef DEBUG |
|
1447 namespace { |
|
1448 |
|
1449 struct ActorSearchData |
|
1450 { |
|
1451 PluginScriptableObjectParent* actor; |
|
1452 bool found; |
|
1453 }; |
|
1454 |
|
1455 PLDHashOperator |
|
1456 ActorSearch(NPObject* aKey, |
|
1457 PluginScriptableObjectParent* aData, |
|
1458 void* aUserData) |
|
1459 { |
|
1460 ActorSearchData* asd = reinterpret_cast<ActorSearchData*>(aUserData); |
|
1461 if (asd->actor == aData) { |
|
1462 asd->found = true; |
|
1463 return PL_DHASH_STOP; |
|
1464 } |
|
1465 return PL_DHASH_NEXT; |
|
1466 } |
|
1467 |
|
1468 } // anonymous namespace |
|
1469 #endif // DEBUG |
|
1470 |
|
1471 bool |
|
1472 PluginInstanceParent::DeallocPPluginScriptableObjectParent( |
|
1473 PPluginScriptableObjectParent* aObject) |
|
1474 { |
|
1475 PluginScriptableObjectParent* actor = |
|
1476 static_cast<PluginScriptableObjectParent*>(aObject); |
|
1477 |
|
1478 NPObject* object = actor->GetObject(false); |
|
1479 if (object) { |
|
1480 NS_ASSERTION(mScriptableObjects.Get(object, nullptr), |
|
1481 "NPObject not in the hash!"); |
|
1482 mScriptableObjects.Remove(object); |
|
1483 } |
|
1484 #ifdef DEBUG |
|
1485 else { |
|
1486 ActorSearchData asd = { actor, false }; |
|
1487 mScriptableObjects.EnumerateRead(ActorSearch, &asd); |
|
1488 NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!"); |
|
1489 } |
|
1490 #endif |
|
1491 |
|
1492 delete actor; |
|
1493 return true; |
|
1494 } |
|
1495 |
|
1496 bool |
|
1497 PluginInstanceParent::RecvPPluginScriptableObjectConstructor( |
|
1498 PPluginScriptableObjectParent* aActor) |
|
1499 { |
|
1500 // This is only called in response to the child process requesting the |
|
1501 // creation of an actor. This actor will represent an NPObject that is |
|
1502 // created by the plugin and returned to the browser. |
|
1503 PluginScriptableObjectParent* actor = |
|
1504 static_cast<PluginScriptableObjectParent*>(aActor); |
|
1505 NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!"); |
|
1506 |
|
1507 actor->InitializeProxy(); |
|
1508 NS_ASSERTION(actor->GetObject(false), "Actor should have an object!"); |
|
1509 |
|
1510 return true; |
|
1511 } |
|
1512 |
|
1513 void |
|
1514 PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason, |
|
1515 void* notifyData) |
|
1516 { |
|
1517 PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)", |
|
1518 FULLFUNCTION, url, (int) reason, notifyData)); |
|
1519 |
|
1520 PStreamNotifyParent* streamNotify = |
|
1521 static_cast<PStreamNotifyParent*>(notifyData); |
|
1522 unused << PStreamNotifyParent::Send__delete__(streamNotify, reason); |
|
1523 } |
|
1524 |
|
1525 bool |
|
1526 PluginInstanceParent::RegisterNPObjectForActor( |
|
1527 NPObject* aObject, |
|
1528 PluginScriptableObjectParent* aActor) |
|
1529 { |
|
1530 NS_ASSERTION(aObject && aActor, "Null pointers!"); |
|
1531 NS_ASSERTION(!mScriptableObjects.Get(aObject, nullptr), "Duplicate entry!"); |
|
1532 mScriptableObjects.Put(aObject, aActor); |
|
1533 return true; |
|
1534 } |
|
1535 |
|
1536 void |
|
1537 PluginInstanceParent::UnregisterNPObject(NPObject* aObject) |
|
1538 { |
|
1539 NS_ASSERTION(aObject, "Null pointer!"); |
|
1540 NS_ASSERTION(mScriptableObjects.Get(aObject, nullptr), "Unknown entry!"); |
|
1541 mScriptableObjects.Remove(aObject); |
|
1542 } |
|
1543 |
|
1544 PluginScriptableObjectParent* |
|
1545 PluginInstanceParent::GetActorForNPObject(NPObject* aObject) |
|
1546 { |
|
1547 NS_ASSERTION(aObject, "Null pointer!"); |
|
1548 |
|
1549 if (aObject->_class == PluginScriptableObjectParent::GetClass()) { |
|
1550 // One of ours! |
|
1551 ParentNPObject* object = static_cast<ParentNPObject*>(aObject); |
|
1552 NS_ASSERTION(object->parent, "Null actor!"); |
|
1553 return object->parent; |
|
1554 } |
|
1555 |
|
1556 PluginScriptableObjectParent* actor; |
|
1557 if (mScriptableObjects.Get(aObject, &actor)) { |
|
1558 return actor; |
|
1559 } |
|
1560 |
|
1561 actor = new PluginScriptableObjectParent(LocalObject); |
|
1562 if (!actor) { |
|
1563 NS_ERROR("Out of memory!"); |
|
1564 return nullptr; |
|
1565 } |
|
1566 |
|
1567 if (!SendPPluginScriptableObjectConstructor(actor)) { |
|
1568 NS_WARNING("Failed to send constructor message!"); |
|
1569 return nullptr; |
|
1570 } |
|
1571 |
|
1572 actor->InitializeLocal(aObject); |
|
1573 return actor; |
|
1574 } |
|
1575 |
|
1576 PPluginSurfaceParent* |
|
1577 PluginInstanceParent::AllocPPluginSurfaceParent(const WindowsSharedMemoryHandle& handle, |
|
1578 const gfxIntSize& size, |
|
1579 const bool& transparent) |
|
1580 { |
|
1581 #ifdef XP_WIN |
|
1582 return new PluginSurfaceParent(handle, size, transparent); |
|
1583 #else |
|
1584 NS_ERROR("This shouldn't be called!"); |
|
1585 return nullptr; |
|
1586 #endif |
|
1587 } |
|
1588 |
|
1589 bool |
|
1590 PluginInstanceParent::DeallocPPluginSurfaceParent(PPluginSurfaceParent* s) |
|
1591 { |
|
1592 #ifdef XP_WIN |
|
1593 delete s; |
|
1594 return true; |
|
1595 #else |
|
1596 return false; |
|
1597 #endif |
|
1598 } |
|
1599 |
|
1600 bool |
|
1601 PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState) |
|
1602 { |
|
1603 mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0); |
|
1604 return true; |
|
1605 } |
|
1606 |
|
1607 bool |
|
1608 PluginInstanceParent::AnswerNPN_PopPopupsEnabledState() |
|
1609 { |
|
1610 mNPNIface->poppopupsenabledstate(mNPP); |
|
1611 return true; |
|
1612 } |
|
1613 |
|
1614 bool |
|
1615 PluginInstanceParent::AnswerNPN_GetValueForURL(const NPNURLVariable& variable, |
|
1616 const nsCString& url, |
|
1617 nsCString* value, |
|
1618 NPError* result) |
|
1619 { |
|
1620 char* v; |
|
1621 uint32_t len; |
|
1622 |
|
1623 *result = mNPNIface->getvalueforurl(mNPP, (NPNURLVariable) variable, |
|
1624 url.get(), &v, &len); |
|
1625 if (NPERR_NO_ERROR == *result) |
|
1626 value->Adopt(v, len); |
|
1627 |
|
1628 return true; |
|
1629 } |
|
1630 |
|
1631 bool |
|
1632 PluginInstanceParent::AnswerNPN_SetValueForURL(const NPNURLVariable& variable, |
|
1633 const nsCString& url, |
|
1634 const nsCString& value, |
|
1635 NPError* result) |
|
1636 { |
|
1637 *result = mNPNIface->setvalueforurl(mNPP, (NPNURLVariable) variable, |
|
1638 url.get(), value.get(), |
|
1639 value.Length()); |
|
1640 return true; |
|
1641 } |
|
1642 |
|
1643 bool |
|
1644 PluginInstanceParent::AnswerNPN_GetAuthenticationInfo(const nsCString& protocol, |
|
1645 const nsCString& host, |
|
1646 const int32_t& port, |
|
1647 const nsCString& scheme, |
|
1648 const nsCString& realm, |
|
1649 nsCString* username, |
|
1650 nsCString* password, |
|
1651 NPError* result) |
|
1652 { |
|
1653 char* u; |
|
1654 uint32_t ulen; |
|
1655 char* p; |
|
1656 uint32_t plen; |
|
1657 |
|
1658 *result = mNPNIface->getauthenticationinfo(mNPP, protocol.get(), |
|
1659 host.get(), port, |
|
1660 scheme.get(), realm.get(), |
|
1661 &u, &ulen, &p, &plen); |
|
1662 if (NPERR_NO_ERROR == *result) { |
|
1663 username->Adopt(u, ulen); |
|
1664 password->Adopt(p, plen); |
|
1665 } |
|
1666 return true; |
|
1667 } |
|
1668 |
|
1669 bool |
|
1670 PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX, |
|
1671 const bool& ignoreDestX, |
|
1672 const double& sourceY, |
|
1673 const bool& ignoreDestY, |
|
1674 const NPCoordinateSpace& sourceSpace, |
|
1675 const NPCoordinateSpace& destSpace, |
|
1676 double *destX, |
|
1677 double *destY, |
|
1678 bool *result) |
|
1679 { |
|
1680 *result = mNPNIface->convertpoint(mNPP, sourceX, sourceY, sourceSpace, |
|
1681 ignoreDestX ? nullptr : destX, |
|
1682 ignoreDestY ? nullptr : destY, |
|
1683 destSpace); |
|
1684 |
|
1685 return true; |
|
1686 } |
|
1687 |
|
1688 bool |
|
1689 PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size, |
|
1690 const NPImageFormat& format, |
|
1691 NPRemoteAsyncSurface* surfData, |
|
1692 bool* result) |
|
1693 { |
|
1694 if (!IsAsyncDrawing()) { |
|
1695 *result = false; |
|
1696 return true; |
|
1697 } |
|
1698 |
|
1699 switch (mDrawingModel) { |
|
1700 case NPDrawingModelAsyncBitmapSurface: { |
|
1701 Shmem sharedMem; |
|
1702 if (!AllocUnsafeShmem(size.width * size.height * 4, SharedMemory::TYPE_BASIC, &sharedMem)) { |
|
1703 *result = false; |
|
1704 return true; |
|
1705 } |
|
1706 |
|
1707 surfData->size() = size; |
|
1708 surfData->hostPtr() = (uintptr_t)sharedMem.get<unsigned char>(); |
|
1709 surfData->stride() = size.width * 4; |
|
1710 surfData->format() = format; |
|
1711 surfData->data() = sharedMem; |
|
1712 *result = true; |
|
1713 return true; |
|
1714 } |
|
1715 #ifdef XP_WIN |
|
1716 case NPDrawingModelAsyncWindowsDXGISurface: { |
|
1717 ID3D10Device1 *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); |
|
1718 |
|
1719 nsRefPtr<ID3D10Texture2D> texture; |
|
1720 |
|
1721 CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, size.width, size.height, 1, 1); |
|
1722 desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; |
|
1723 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; |
|
1724 if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)))) { |
|
1725 *result = false; |
|
1726 return true; |
|
1727 } |
|
1728 |
|
1729 nsRefPtr<IDXGIResource> resource; |
|
1730 if (FAILED(texture->QueryInterface(IID_IDXGIResource, getter_AddRefs(resource)))) { |
|
1731 *result = false; |
|
1732 return true; |
|
1733 } |
|
1734 |
|
1735 HANDLE sharedHandle; |
|
1736 |
|
1737 if (FAILED(resource->GetSharedHandle(&sharedHandle))) { |
|
1738 *result = false; |
|
1739 return true; |
|
1740 } |
|
1741 |
|
1742 surfData->size() = size; |
|
1743 surfData->data() = sharedHandle; |
|
1744 surfData->format() = format; |
|
1745 |
|
1746 mTextureMap.Put(sharedHandle, texture); |
|
1747 *result = true; |
|
1748 } |
|
1749 #endif |
|
1750 } |
|
1751 |
|
1752 return true; |
|
1753 } |
|
1754 |
|
1755 bool |
|
1756 PluginInstanceParent::RecvRedrawPlugin() |
|
1757 { |
|
1758 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata); |
|
1759 if (!inst) { |
|
1760 return false; |
|
1761 } |
|
1762 |
|
1763 inst->RedrawPlugin(); |
|
1764 return true; |
|
1765 } |
|
1766 |
|
1767 bool |
|
1768 PluginInstanceParent::RecvNegotiatedCarbon() |
|
1769 { |
|
1770 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata); |
|
1771 if (!inst) { |
|
1772 return false; |
|
1773 } |
|
1774 inst->CarbonNPAPIFailure(); |
|
1775 return true; |
|
1776 } |
|
1777 |
|
1778 bool |
|
1779 PluginInstanceParent::RecvReleaseDXGISharedSurface(const DXGISharedSurfaceHandle &aHandle) |
|
1780 { |
|
1781 #ifdef XP_WIN |
|
1782 mTextureMap.Remove(aHandle); |
|
1783 #endif |
|
1784 return true; |
|
1785 } |
|
1786 |
|
1787 #if defined(OS_WIN) |
|
1788 |
|
1789 /* |
|
1790 plugin focus changes between processes |
|
1791 |
|
1792 focus from dom -> child: |
|
1793 Focus manager calls on widget to set the focus on the window. |
|
1794 We pick up the resulting wm_setfocus event here, and forward |
|
1795 that over ipc to the child which calls set focus on itself. |
|
1796 |
|
1797 focus from child -> focus manager: |
|
1798 Child picks up the local wm_setfocus and sends it via ipc over |
|
1799 here. We then post a custom event to widget/windows/nswindow |
|
1800 which fires off a gui event letting the browser know. |
|
1801 */ |
|
1802 |
|
1803 static const wchar_t kPluginInstanceParentProperty[] = |
|
1804 L"PluginInstanceParentProperty"; |
|
1805 |
|
1806 // static |
|
1807 LRESULT CALLBACK |
|
1808 PluginInstanceParent::PluginWindowHookProc(HWND hWnd, |
|
1809 UINT message, |
|
1810 WPARAM wParam, |
|
1811 LPARAM lParam) |
|
1812 { |
|
1813 PluginInstanceParent* self = reinterpret_cast<PluginInstanceParent*>( |
|
1814 ::GetPropW(hWnd, kPluginInstanceParentProperty)); |
|
1815 if (!self) { |
|
1816 NS_NOTREACHED("PluginInstanceParent::PluginWindowHookProc null this ptr!"); |
|
1817 return DefWindowProc(hWnd, message, wParam, lParam); |
|
1818 } |
|
1819 |
|
1820 NS_ASSERTION(self->mPluginHWND == hWnd, "Wrong window!"); |
|
1821 |
|
1822 switch (message) { |
|
1823 case WM_SETFOCUS: |
|
1824 // Let the child plugin window know it should take focus. |
|
1825 unused << self->CallSetPluginFocus(); |
|
1826 break; |
|
1827 |
|
1828 case WM_CLOSE: |
|
1829 self->UnsubclassPluginWindow(); |
|
1830 break; |
|
1831 } |
|
1832 |
|
1833 if (self->mPluginWndProc == PluginWindowHookProc) { |
|
1834 NS_NOTREACHED( |
|
1835 "PluginWindowHookProc invoking mPluginWndProc w/" |
|
1836 "mPluginWndProc == PluginWindowHookProc????"); |
|
1837 return DefWindowProc(hWnd, message, wParam, lParam); |
|
1838 } |
|
1839 return ::CallWindowProc(self->mPluginWndProc, hWnd, message, wParam, |
|
1840 lParam); |
|
1841 } |
|
1842 |
|
1843 void |
|
1844 PluginInstanceParent::SubclassPluginWindow(HWND aWnd) |
|
1845 { |
|
1846 NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND), |
|
1847 "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!"); |
|
1848 |
|
1849 if (!mPluginHWND) { |
|
1850 mPluginHWND = aWnd; |
|
1851 mPluginWndProc = |
|
1852 (WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, |
|
1853 reinterpret_cast<LONG_PTR>(PluginWindowHookProc)); |
|
1854 DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this); |
|
1855 NS_ASSERTION(mPluginWndProc, |
|
1856 "PluginInstanceParent::SubclassPluginWindow failed to set subclass!"); |
|
1857 NS_ASSERTION(bRes, |
|
1858 "PluginInstanceParent::SubclassPluginWindow failed to set prop!"); |
|
1859 } |
|
1860 } |
|
1861 |
|
1862 void |
|
1863 PluginInstanceParent::UnsubclassPluginWindow() |
|
1864 { |
|
1865 if (mPluginHWND && mPluginWndProc) { |
|
1866 ::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, |
|
1867 reinterpret_cast<LONG_PTR>(mPluginWndProc)); |
|
1868 |
|
1869 ::RemovePropW(mPluginHWND, kPluginInstanceParentProperty); |
|
1870 |
|
1871 mPluginWndProc = nullptr; |
|
1872 mPluginHWND = nullptr; |
|
1873 } |
|
1874 } |
|
1875 |
|
1876 /* windowless drawing helpers */ |
|
1877 |
|
1878 /* |
|
1879 * Origin info: |
|
1880 * |
|
1881 * windowless, offscreen: |
|
1882 * |
|
1883 * WM_WINDOWPOSCHANGED: origin is relative to container |
|
1884 * setwindow: origin is 0,0 |
|
1885 * WM_PAINT: origin is 0,0 |
|
1886 * |
|
1887 * windowless, native: |
|
1888 * |
|
1889 * WM_WINDOWPOSCHANGED: origin is relative to container |
|
1890 * setwindow: origin is relative to container |
|
1891 * WM_PAINT: origin is relative to container |
|
1892 * |
|
1893 * PluginInstanceParent: |
|
1894 * |
|
1895 * painting: mPluginPort (nsIntRect, saved in SetWindow) |
|
1896 */ |
|
1897 |
|
1898 void |
|
1899 PluginInstanceParent::SharedSurfaceRelease() |
|
1900 { |
|
1901 mSharedSurfaceDib.Close(); |
|
1902 } |
|
1903 |
|
1904 bool |
|
1905 PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow, |
|
1906 NPRemoteWindow& aRemoteWindow) |
|
1907 { |
|
1908 aRemoteWindow.window = 0; |
|
1909 aRemoteWindow.x = aWindow->x; |
|
1910 aRemoteWindow.y = aWindow->y; |
|
1911 aRemoteWindow.width = aWindow->width; |
|
1912 aRemoteWindow.height = aWindow->height; |
|
1913 aRemoteWindow.type = aWindow->type; |
|
1914 |
|
1915 nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height); |
|
1916 |
|
1917 // save the the rect location within the browser window. |
|
1918 mPluginPort = newPort; |
|
1919 |
|
1920 // move the port to our shared surface origin |
|
1921 newPort.MoveTo(0,0); |
|
1922 |
|
1923 // check to see if we have the room in shared surface |
|
1924 if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) { |
|
1925 // ok to paint |
|
1926 aRemoteWindow.surfaceHandle = 0; |
|
1927 return true; |
|
1928 } |
|
1929 |
|
1930 // allocate a new shared surface |
|
1931 SharedSurfaceRelease(); |
|
1932 if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window), |
|
1933 newPort.width, newPort.height, false))) |
|
1934 return false; |
|
1935 |
|
1936 // save the new shared surface size we just allocated |
|
1937 mSharedSize = newPort; |
|
1938 |
|
1939 base::SharedMemoryHandle handle; |
|
1940 if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle))) |
|
1941 return false; |
|
1942 |
|
1943 aRemoteWindow.surfaceHandle = handle; |
|
1944 |
|
1945 return true; |
|
1946 } |
|
1947 |
|
1948 void |
|
1949 PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect, |
|
1950 NPRemoteEvent& npremoteevent) |
|
1951 { |
|
1952 RECT* dr = (RECT*)npremoteevent.event.lParam; |
|
1953 HDC parentHdc = (HDC)npremoteevent.event.wParam; |
|
1954 |
|
1955 nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); |
|
1956 dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect |
|
1957 |
|
1958 ::BitBlt(mSharedSurfaceDib.GetHDC(), |
|
1959 dirtyRect.x, |
|
1960 dirtyRect.y, |
|
1961 dirtyRect.width, |
|
1962 dirtyRect.height, |
|
1963 parentHdc, |
|
1964 dr->left, |
|
1965 dr->top, |
|
1966 SRCCOPY); |
|
1967 |
|
1968 // setup the translated dirty rect we'll send to the child |
|
1969 rect.left = dirtyRect.x; |
|
1970 rect.top = dirtyRect.y; |
|
1971 rect.right = dirtyRect.x + dirtyRect.width; |
|
1972 rect.bottom = dirtyRect.y + dirtyRect.height; |
|
1973 |
|
1974 npremoteevent.event.wParam = WPARAM(0); |
|
1975 npremoteevent.event.lParam = LPARAM(&rect); |
|
1976 } |
|
1977 |
|
1978 void |
|
1979 PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent) |
|
1980 { |
|
1981 RECT* dr = (RECT*)npevent->lParam; |
|
1982 HDC parentHdc = (HDC)npevent->wParam; |
|
1983 |
|
1984 nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); |
|
1985 dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); |
|
1986 |
|
1987 // src copy the shared dib into the parent surface we are handed. |
|
1988 ::BitBlt(parentHdc, |
|
1989 dr->left, |
|
1990 dr->top, |
|
1991 dirtyRect.width, |
|
1992 dirtyRect.height, |
|
1993 mSharedSurfaceDib.GetHDC(), |
|
1994 dirtyRect.x, |
|
1995 dirtyRect.y, |
|
1996 SRCCOPY); |
|
1997 } |
|
1998 |
|
1999 #endif // defined(OS_WIN) |
|
2000 |
|
2001 bool |
|
2002 PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus) |
|
2003 { |
|
2004 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); |
|
2005 |
|
2006 // Currently only in use on windows - an rpc event we receive from the |
|
2007 // child when it's plugin window (or one of it's children) receives keyboard |
|
2008 // focus. We forward the event down to widget so the dom/focus manager can |
|
2009 // be updated. |
|
2010 #if defined(OS_WIN) |
|
2011 ::SendMessage(mPluginHWND, gOOPPPluginFocusEvent, gotFocus ? 1 : 0, 0); |
|
2012 return true; |
|
2013 #else |
|
2014 NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!"); |
|
2015 return false; |
|
2016 #endif |
|
2017 } |