dom/plugins/ipc/PluginInstanceParent.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:b6b466e084d8
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 }

mercurial