Bumping manifests a=b2g-bump
[gecko.git] / dom / plugins / ipc / PluginInstanceParent.cpp
blobbcde836e9e6ecd256374f4c04f66c62c8eb0c0d8
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/. */
7 #include "mozilla/DebugOnly.h"
8 #include <stdint.h> // for intptr_t
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 "ImageContainer.h"
32 #include "GLContext.h"
33 #include "GLContextProvider.h"
35 #ifdef XP_MACOSX
36 #include "MacIOSurfaceImage.h"
37 #endif
39 #if defined(OS_WIN)
40 #include <windowsx.h>
41 #include "gfxWindowsPlatform.h"
42 #include "mozilla/plugins/PluginSurfaceParent.h"
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)
55 using namespace mozilla::plugins;
56 using namespace mozilla::layers;
57 using namespace mozilla::gl;
59 void
60 StreamNotifyParent::ActorDestroy(ActorDestroyReason aWhy)
62 // Implement me! Bug 1005162
65 bool
66 StreamNotifyParent::RecvRedirectNotifyResponse(const bool& allow)
68 PluginInstanceParent* instance = static_cast<PluginInstanceParent*>(Manager());
69 instance->mNPNIface->urlredirectresponse(instance->mNPP, this, static_cast<NPBool>(allow));
70 return true;
73 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
74 NPP npp,
75 const nsCString& aMimeType,
76 const NPNetscapeFuncs* npniface)
77 : mParent(parent)
78 , mNPP(npp)
79 , mNPNIface(npniface)
80 , mWindowType(NPWindowTypeWindow)
81 , mDrawingModel(kDefaultDrawingModel)
82 #if defined(OS_WIN)
83 , mPluginHWND(nullptr)
84 , mPluginWndProc(nullptr)
85 , mNestedEventState(false)
86 #endif // defined(XP_WIN)
87 #if defined(XP_MACOSX)
88 , mShWidth(0)
89 , mShHeight(0)
90 , mShColorSpace(nullptr)
91 #endif
95 PluginInstanceParent::~PluginInstanceParent()
97 if (mNPP)
98 mNPP->pdata = nullptr;
100 #if defined(OS_WIN)
101 NS_ASSERTION(!(mPluginHWND || mPluginWndProc),
102 "Subclass was not reset correctly before the dtor was reached!");
103 #endif
104 #if defined(MOZ_WIDGET_COCOA)
105 if (mShWidth != 0 && mShHeight != 0) {
106 DeallocShmem(mShSurface);
108 if (mShColorSpace)
109 ::CGColorSpaceRelease(mShColorSpace);
110 #endif
111 if (mRemoteImageDataShmem.IsWritable()) {
112 if (mImageContainer) {
113 mImageContainer->SetRemoteImageData(nullptr, nullptr);
114 mImageContainer->SetCompositionNotifySink(nullptr);
116 DeallocShmem(mRemoteImageDataShmem);
120 bool
121 PluginInstanceParent::Init()
123 return true;
126 void
127 PluginInstanceParent::ActorDestroy(ActorDestroyReason why)
129 #if defined(OS_WIN)
130 if (why == AbnormalShutdown) {
131 // If the plugin process crashes, this is the only
132 // chance we get to destroy resources.
133 SharedSurfaceRelease();
134 UnsubclassPluginWindow();
136 #endif
137 // After this method, the data backing the remote surface may no
138 // longer be valid. The X surface may be destroyed, or the shared
139 // memory backing this surface may no longer be valid.
140 if (mFrontSurface) {
141 mFrontSurface = nullptr;
142 if (mImageContainer) {
143 mImageContainer->SetCurrentImage(nullptr);
145 #ifdef MOZ_X11
146 FinishX(DefaultXDisplay());
147 #endif
151 NPError
152 PluginInstanceParent::Destroy()
154 NPError retval;
155 if (!CallNPP_Destroy(&retval))
156 retval = NPERR_GENERIC_ERROR;
158 #if defined(OS_WIN)
159 SharedSurfaceRelease();
160 UnsubclassPluginWindow();
161 #endif
163 return retval;
166 PBrowserStreamParent*
167 PluginInstanceParent::AllocPBrowserStreamParent(const nsCString& url,
168 const uint32_t& length,
169 const uint32_t& lastmodified,
170 PStreamNotifyParent* notifyData,
171 const nsCString& headers,
172 const nsCString& mimeType,
173 const bool& seekable,
174 NPError* rv,
175 uint16_t *stype)
177 NS_RUNTIMEABORT("Not reachable");
178 return nullptr;
181 bool
182 PluginInstanceParent::DeallocPBrowserStreamParent(PBrowserStreamParent* stream)
184 delete stream;
185 return true;
188 PPluginStreamParent*
189 PluginInstanceParent::AllocPPluginStreamParent(const nsCString& mimeType,
190 const nsCString& target,
191 NPError* result)
193 return new PluginStreamParent(this, mimeType, target, result);
196 bool
197 PluginInstanceParent::DeallocPPluginStreamParent(PPluginStreamParent* stream)
199 delete stream;
200 return true;
203 bool
204 PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle* value,
205 NPError* result)
207 #ifdef XP_WIN
208 HWND id;
209 #elif defined(MOZ_X11)
210 XID id;
211 #elif defined(XP_MACOSX)
212 intptr_t id;
213 #elif defined(ANDROID)
214 // TODO: Need Android impl
215 int id;
216 #elif defined(MOZ_WIDGET_QT)
217 // TODO: Need Qt non X impl
218 int id;
219 #else
220 #warning Implement me
221 #endif
223 *result = mNPNIface->getvalue(mNPP, NPNVnetscapeWindow, &id);
224 *value = id;
225 return true;
228 bool
229 PluginInstanceParent::InternalGetValueForNPObject(
230 NPNVariable aVariable,
231 PPluginScriptableObjectParent** aValue,
232 NPError* aResult)
234 NPObject* npobject;
235 NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject);
236 if (result == NPERR_NO_ERROR) {
237 NS_ASSERTION(npobject, "Shouldn't return null and NPERR_NO_ERROR!");
239 PluginScriptableObjectParent* actor = GetActorForNPObject(npobject);
240 mNPNIface->releaseobject(npobject);
241 if (actor) {
242 *aValue = actor;
243 *aResult = NPERR_NO_ERROR;
244 return true;
247 NS_ERROR("Failed to get actor!");
248 result = NPERR_GENERIC_ERROR;
251 *aValue = nullptr;
252 *aResult = result;
253 return true;
256 bool
257 PluginInstanceParent::IsAsyncDrawing()
259 return IsDrawingModelAsync(mDrawingModel);
262 bool
263 PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject(
264 PPluginScriptableObjectParent** aValue,
265 NPError* aResult)
267 return InternalGetValueForNPObject(NPNVWindowNPObject, aValue, aResult);
270 bool
271 PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject(
272 PPluginScriptableObjectParent** aValue,
273 NPError* aResult)
275 return InternalGetValueForNPObject(NPNVPluginElementNPObject, aValue,
276 aResult);
279 bool
280 PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value,
281 NPError* result)
283 NPBool v;
284 *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v);
285 *value = v;
286 return true;
289 bool
290 PluginInstanceParent::AnswerNPN_GetValue_DrawingModelSupport(const NPNVariable& model, bool* value)
292 *value = false;
294 #ifdef XP_WIN
295 switch (model) {
296 case NPNVsupportsAsyncWindowsDXGISurfaceBool: {
297 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D) {
298 *value = true;
302 #endif
304 return true;
307 bool
308 PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value,
309 NPError* result)
311 void *v = nullptr;
312 *result = mNPNIface->getvalue(mNPP, NPNVdocumentOrigin, &v);
313 if (*result == NPERR_NO_ERROR && v) {
314 value->Adopt(static_cast<char*>(v));
316 return true;
319 bool
320 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
321 const bool& windowed, NPError* result)
323 // Yes, we are passing a boolean as a void*. We have to cast to intptr_t
324 // first to avoid gcc warnings about casting to a pointer from a
325 // non-pointer-sized integer.
326 *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
327 (void*)(intptr_t)windowed);
328 return true;
331 bool
332 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
333 const bool& transparent, NPError* result)
335 *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool,
336 (void*)(intptr_t)transparent);
337 return true;
340 bool
341 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor(
342 const bool& useDOMForCursor, NPError* result)
344 *result = mNPNIface->setvalue(mNPP, NPPVpluginUsesDOMForCursorBool,
345 (void*)(intptr_t)useDOMForCursor);
346 return true;
349 class NotificationSink : public CompositionNotifySink
351 public:
352 NotificationSink(PluginInstanceParent *aInstance) : mInstance(aInstance)
355 virtual void DidComposite() { mInstance->DidComposite(); }
356 private:
357 PluginInstanceParent *mInstance;
360 bool
361 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
362 const int& drawingModel, OptionalShmem *shmem, CrossProcessMutexHandle *mutex, NPError* result)
364 *shmem = null_t();
366 #ifdef XP_MACOSX
367 if (drawingModel == NPDrawingModelCoreAnimation ||
368 drawingModel == NPDrawingModelInvalidatingCoreAnimation) {
369 // We need to request CoreGraphics otherwise
370 // the nsObjectFrame will try to draw a CALayer
371 // that can not be shared across process.
372 mDrawingModel = drawingModel;
373 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
374 (void*)NPDrawingModelCoreGraphics);
375 } else
376 #endif
377 if (drawingModel == NPDrawingModelAsyncBitmapSurface
378 #ifdef XP_WIN
379 || drawingModel == NPDrawingModelAsyncWindowsDXGISurface
380 #endif
382 ImageContainer *container = GetImageContainer();
383 if (!container) {
384 *result = NPERR_GENERIC_ERROR;
385 return true;
388 #ifdef XP_WIN
389 if (drawingModel == NPDrawingModelAsyncWindowsDXGISurface &&
390 gfxWindowsPlatform::GetPlatform()->GetRenderMode() != gfxWindowsPlatform::RENDER_DIRECT2D) {
391 *result = NPERR_GENERIC_ERROR;
392 return true;
394 #endif
396 mDrawingModel = drawingModel;
397 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
398 reinterpret_cast<void*>(static_cast<uintptr_t>(drawingModel)));
401 if (*result != NPERR_NO_ERROR) {
402 return true;
405 AllocUnsafeShmem(sizeof(RemoteImageData), SharedMemory::TYPE_BASIC, &mRemoteImageDataShmem);
407 *shmem = mRemoteImageDataShmem;
409 mRemoteImageDataMutex = new CrossProcessMutex("PluginInstanceParent.mRemoteImageDataMutex");
411 *mutex = mRemoteImageDataMutex->ShareToProcess(OtherProcess());
412 container->SetRemoteImageData(mRemoteImageDataShmem.get<RemoteImageData>(), mRemoteImageDataMutex);
414 mNotifySink = new NotificationSink(this);
416 container->SetCompositionNotifySink(mNotifySink);
417 } else if (
418 #if defined(XP_WIN)
419 drawingModel == NPDrawingModelSyncWin
420 #elif defined(XP_MACOSX)
421 drawingModel == NPDrawingModelOpenGL ||
422 drawingModel == NPDrawingModelCoreGraphics
423 #elif defined(MOZ_X11)
424 drawingModel == NPDrawingModelSyncX
425 #else
426 false
427 #endif
429 *shmem = null_t();
431 mDrawingModel = drawingModel;
432 *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
433 (void*)(intptr_t)drawingModel);
435 if (mRemoteImageDataShmem.IsWritable()) {
436 if (mImageContainer) {
437 mImageContainer->SetRemoteImageData(nullptr, nullptr);
438 mImageContainer->SetCompositionNotifySink(nullptr);
440 DeallocShmem(mRemoteImageDataShmem);
441 mRemoteImageDataMutex = nullptr;
443 } else {
444 *result = NPERR_GENERIC_ERROR;
446 return true;
449 bool
450 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel(
451 const int& eventModel, NPError* result)
453 #ifdef XP_MACOSX
454 *result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel,
455 (void*)(intptr_t)eventModel);
456 return true;
457 #else
458 *result = NPERR_GENERIC_ERROR;
459 return true;
460 #endif
463 bool
464 PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url,
465 const nsCString& target,
466 NPError* result)
468 *result = mNPNIface->geturl(mNPP,
469 NullableStringGet(url),
470 NullableStringGet(target));
471 return true;
474 bool
475 PluginInstanceParent::AnswerNPN_PostURL(const nsCString& url,
476 const nsCString& target,
477 const nsCString& buffer,
478 const bool& file,
479 NPError* result)
481 *result = mNPNIface->posturl(mNPP, url.get(), NullableStringGet(target),
482 buffer.Length(), buffer.get(), file);
483 return true;
486 PStreamNotifyParent*
487 PluginInstanceParent::AllocPStreamNotifyParent(const nsCString& url,
488 const nsCString& target,
489 const bool& post,
490 const nsCString& buffer,
491 const bool& file,
492 NPError* result)
494 return new StreamNotifyParent();
497 bool
498 PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor,
499 const nsCString& url,
500 const nsCString& target,
501 const bool& post,
502 const nsCString& buffer,
503 const bool& file,
504 NPError* result)
506 bool streamDestroyed = false;
507 static_cast<StreamNotifyParent*>(actor)->
508 SetDestructionFlag(&streamDestroyed);
510 if (!post) {
511 *result = mNPNIface->geturlnotify(mNPP,
512 NullableStringGet(url),
513 NullableStringGet(target),
514 actor);
516 else {
517 *result = mNPNIface->posturlnotify(mNPP,
518 NullableStringGet(url),
519 NullableStringGet(target),
520 buffer.Length(),
521 NullableStringGet(buffer),
522 file, actor);
525 if (streamDestroyed) {
526 // If the stream was destroyed, we must return an error code in the
527 // constructor.
528 *result = NPERR_GENERIC_ERROR;
530 else {
531 static_cast<StreamNotifyParent*>(actor)->ClearDestructionFlag();
532 if (*result != NPERR_NO_ERROR)
533 return PStreamNotifyParent::Send__delete__(actor,
534 NPERR_GENERIC_ERROR);
537 return true;
540 bool
541 PluginInstanceParent::DeallocPStreamNotifyParent(PStreamNotifyParent* notifyData)
543 delete notifyData;
544 return true;
547 bool
548 PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect)
550 mNPNIface->invalidaterect(mNPP, const_cast<NPRect*>(&rect));
551 return true;
554 bool
555 PluginInstanceParent::RecvShow(const NPRect& updatedRect,
556 const SurfaceDescriptor& newSurface,
557 SurfaceDescriptor* prevSurface)
559 PLUGIN_LOG_DEBUG(
560 ("[InstanceParent][%p] RecvShow for <x=%d,y=%d, w=%d,h=%d>",
561 this, updatedRect.left, updatedRect.top,
562 updatedRect.right - updatedRect.left,
563 updatedRect.bottom - updatedRect.top));
565 // XXXjwatt rewrite to use Moz2D
566 nsRefPtr<gfxASurface> surface;
567 if (newSurface.type() == SurfaceDescriptor::TShmem) {
568 if (!newSurface.get_Shmem().IsReadable()) {
569 NS_WARNING("back surface not readable");
570 return false;
572 surface = gfxSharedImageSurface::Open(newSurface.get_Shmem());
574 #ifdef XP_MACOSX
575 else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) {
576 IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor();
578 RefPtr<MacIOSurface> newIOSurface =
579 MacIOSurface::LookupSurface(iodesc.surfaceId(),
580 iodesc.contentsScaleFactor());
582 if (!newIOSurface) {
583 NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow");
584 return false;
587 if (mFrontIOSurface)
588 *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID(),
589 mFrontIOSurface->GetContentsScaleFactor());
590 else
591 *prevSurface = null_t();
593 mFrontIOSurface = newIOSurface;
595 RecvNPN_InvalidateRect(updatedRect);
597 PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
598 mFrontSurface.get()));
600 return true;
602 #endif
603 #ifdef MOZ_X11
604 else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) {
605 surface = newSurface.get_SurfaceDescriptorX11().OpenForeign();
607 #endif
608 #ifdef XP_WIN
609 else if (newSurface.type() == SurfaceDescriptor::TPPluginSurfaceParent) {
610 PluginSurfaceParent* s =
611 static_cast<PluginSurfaceParent*>(newSurface.get_PPluginSurfaceParent());
612 surface = s->Surface();
614 #endif
616 if (mFrontSurface) {
617 // This is the "old front buffer" we're about to hand back to
618 // the plugin. We might still have drawing operations
619 // referencing it.
620 #ifdef MOZ_X11
621 if (mFrontSurface->GetType() == gfxSurfaceType::Xlib) {
622 // Finish with the surface and XSync here to ensure the server has
623 // finished operations on the surface before the plugin starts
624 // scribbling on it again, or worse, destroys it.
625 mFrontSurface->Finish();
626 FinishX(DefaultXDisplay());
627 } else
628 #endif
630 mFrontSurface->Flush();
634 if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
635 *prevSurface = static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();
636 else
637 *prevSurface = null_t();
639 if (surface) {
640 // Notify the cairo backend that this surface has changed behind
641 // its back.
642 gfxRect ur(updatedRect.left, updatedRect.top,
643 updatedRect.right - updatedRect.left,
644 updatedRect.bottom - updatedRect.top);
645 surface->MarkDirty(ur);
647 ImageContainer *container = GetImageContainer();
648 nsRefPtr<Image> image = container->CreateImage(ImageFormat::CAIRO_SURFACE);
649 NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?");
650 CairoImage* cairoImage = static_cast<CairoImage*>(image.get());
651 CairoImage::Data cairoData;
652 cairoData.mSize = surface->GetSize().ToIntSize();
653 cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
654 cairoImage->SetData(cairoData);
656 container->SetCurrentImage(cairoImage);
658 else if (mImageContainer) {
659 mImageContainer->SetCurrentImage(nullptr);
662 mFrontSurface = surface;
663 RecvNPN_InvalidateRect(updatedRect);
665 PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
666 mFrontSurface.get()));
668 return true;
671 nsresult
672 PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
674 NPRemoteWindow window;
675 mWindowType = aWindow->type;
676 window.window = reinterpret_cast<uint64_t>(aWindow->window);
677 window.x = aWindow->x;
678 window.y = aWindow->y;
679 window.width = aWindow->width;
680 window.height = aWindow->height;
681 window.clipRect = aWindow->clipRect;
682 window.type = aWindow->type;
683 #ifdef XP_MACOSX
684 double scaleFactor = 1.0;
685 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor);
686 window.contentsScaleFactor = scaleFactor;
687 #endif
688 if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
689 window))
690 return NS_ERROR_FAILURE;
692 return NS_OK;
695 nsresult
696 PluginInstanceParent::GetImageContainer(ImageContainer** aContainer)
698 #ifdef XP_MACOSX
699 MacIOSurface* ioSurface = nullptr;
701 if (mFrontIOSurface) {
702 ioSurface = mFrontIOSurface;
703 } else if (mIOSurface) {
704 ioSurface = mIOSurface;
707 if (!mFrontSurface && !ioSurface)
708 #else
709 if (!mFrontSurface)
710 #endif
711 return NS_ERROR_NOT_AVAILABLE;
713 ImageContainer *container = GetImageContainer();
715 if (!container) {
716 return NS_ERROR_FAILURE;
719 if (IsAsyncDrawing()) {
720 NS_IF_ADDREF(container);
721 *aContainer = container;
722 return NS_OK;
725 #ifdef XP_MACOSX
726 if (ioSurface) {
727 nsRefPtr<Image> image = container->CreateImage(ImageFormat::MAC_IOSURFACE);
728 if (!image) {
729 return NS_ERROR_FAILURE;
732 NS_ASSERTION(image->GetFormat() == ImageFormat::MAC_IOSURFACE, "Wrong format?");
734 MacIOSurfaceImage* pluginImage = static_cast<MacIOSurfaceImage*>(image.get());
735 pluginImage->SetSurface(ioSurface);
737 container->SetCurrentImageInTransaction(pluginImage);
739 NS_IF_ADDREF(container);
740 *aContainer = container;
741 return NS_OK;
743 #endif
745 NS_IF_ADDREF(container);
746 *aContainer = container;
747 return NS_OK;
750 nsresult
751 PluginInstanceParent::GetImageSize(nsIntSize* aSize)
753 if (mFrontSurface) {
754 gfxIntSize size = mFrontSurface->GetSize();
755 *aSize = nsIntSize(size.width, size.height);
756 return NS_OK;
759 #ifdef XP_MACOSX
760 if (mFrontIOSurface) {
761 *aSize = nsIntSize(mFrontIOSurface->GetWidth(), mFrontIOSurface->GetHeight());
762 return NS_OK;
763 } else if (mIOSurface) {
764 *aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
765 return NS_OK;
767 #endif
769 return NS_ERROR_NOT_AVAILABLE;
772 #ifdef XP_MACOSX
773 nsresult
774 PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing)
776 *aDrawing = (NPDrawingModelCoreAnimation == (NPDrawingModel)mDrawingModel ||
777 NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel);
778 return NS_OK;
781 nsresult
782 PluginInstanceParent::ContentsScaleFactorChanged(double aContentsScaleFactor)
784 bool rv = SendContentsScaleFactorChanged(aContentsScaleFactor);
785 return rv ? NS_OK : NS_ERROR_FAILURE;
787 #endif // #ifdef XP_MACOSX
789 nsresult
790 PluginInstanceParent::SetBackgroundUnknown()
792 PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this));
794 if (mBackground) {
795 DestroyBackground();
796 NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed");
799 return NS_OK;
802 nsresult
803 PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
804 gfxContext** aCtx)
806 PLUGIN_LOG_DEBUG(
807 ("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
808 this, aRect.x, aRect.y, aRect.width, aRect.height));
810 if (!mBackground) {
811 // XXX if we failed to create a background surface on one
812 // update, there's no guarantee that later updates will be for
813 // the entire background area until successful. We might want
814 // to fix that eventually.
815 NS_ABORT_IF_FALSE(aRect.TopLeft() == nsIntPoint(0, 0),
816 "Expecting rect for whole frame");
817 if (!CreateBackground(aRect.Size())) {
818 *aCtx = nullptr;
819 return NS_OK;
823 gfxIntSize sz = mBackground->GetSize();
824 #ifdef DEBUG
825 NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
826 "Update outside of background area");
827 #endif
829 RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
830 CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
831 nsRefPtr<gfxContext> ctx = new gfxContext(dt);
832 ctx.forget(aCtx);
834 return NS_OK;
837 nsresult
838 PluginInstanceParent::EndUpdateBackground(gfxContext* aCtx,
839 const nsIntRect& aRect)
841 PLUGIN_LOG_DEBUG(
842 ("[InstanceParent][%p] EndUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
843 this, aRect.x, aRect.y, aRect.width, aRect.height));
845 #ifdef MOZ_X11
846 // Have to XSync here to avoid the plugin trying to draw with this
847 // surface racing with its creation in the X server. We also want
848 // to avoid the plugin drawing onto stale pixels, then handing us
849 // back a front surface from those pixels that we might
850 // recomposite for "a while" until the next update. This XSync
851 // still doesn't guarantee that the plugin draws onto a consistent
852 // view of its background, but it does mean that the plugin is
853 // drawing onto pixels no older than those in the latest
854 // EndUpdateBackground().
855 XSync(DefaultXDisplay(), False);
856 #endif
858 unused << SendUpdateBackground(BackgroundDescriptor(), aRect);
860 return NS_OK;
863 bool
864 PluginInstanceParent::CreateBackground(const nsIntSize& aSize)
866 NS_ABORT_IF_FALSE(!mBackground, "Already have a background");
868 // XXX refactor me
870 #if defined(MOZ_X11)
871 Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay());
872 Visual* visual = DefaultVisualOfScreen(screen);
873 mBackground = gfxXlibSurface::Create(screen, visual,
874 gfxIntSize(aSize.width, aSize.height));
875 return !!mBackground;
877 #elif defined(XP_WIN)
878 // We have chosen to create an unsafe surface in which the plugin
879 // can read from the region while we're writing to it.
880 mBackground =
881 gfxSharedImageSurface::CreateUnsafe(
882 this,
883 gfxIntSize(aSize.width, aSize.height),
884 gfxImageFormat::RGB24);
885 return !!mBackground;
886 #else
887 return nullptr;
888 #endif
891 void
892 PluginInstanceParent::DestroyBackground()
894 if (!mBackground) {
895 return;
898 // Relinquish ownership of |mBackground| to its destroyer
899 PPluginBackgroundDestroyerParent* pbd =
900 new PluginBackgroundDestroyerParent(mBackground);
901 mBackground = nullptr;
903 // If this fails, there's no problem: |bd| will be destroyed along
904 // with the old background surface.
905 unused << SendPPluginBackgroundDestroyerConstructor(pbd);
908 mozilla::plugins::SurfaceDescriptor
909 PluginInstanceParent::BackgroundDescriptor()
911 NS_ABORT_IF_FALSE(mBackground, "Need a background here");
913 // XXX refactor me
915 #ifdef MOZ_X11
916 gfxXlibSurface* xsurf = static_cast<gfxXlibSurface*>(mBackground.get());
917 return SurfaceDescriptorX11(xsurf);
918 #endif
920 #ifdef XP_WIN
921 NS_ABORT_IF_FALSE(gfxSharedImageSurface::IsSharedImage(mBackground),
922 "Expected shared image surface");
923 gfxSharedImageSurface* shmem =
924 static_cast<gfxSharedImageSurface*>(mBackground.get());
925 return shmem->GetShmem();
926 #endif
928 // If this is ever used, which it shouldn't be, it will trigger a
929 // hard assertion in IPDL-generated code.
930 return mozilla::plugins::SurfaceDescriptor();
933 ImageContainer*
934 PluginInstanceParent::GetImageContainer()
936 if (mImageContainer) {
937 return mImageContainer;
940 mImageContainer = LayerManager::CreateImageContainer();
941 return mImageContainer;
944 PPluginBackgroundDestroyerParent*
945 PluginInstanceParent::AllocPPluginBackgroundDestroyerParent()
947 NS_RUNTIMEABORT("'Power-user' ctor is used exclusively");
948 return nullptr;
951 bool
952 PluginInstanceParent::DeallocPPluginBackgroundDestroyerParent(
953 PPluginBackgroundDestroyerParent* aActor)
955 delete aActor;
956 return true;
959 NPError
960 PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
962 PLUGIN_LOG_DEBUG(("%s (aWindow=%p)", FULLFUNCTION, (void*) aWindow));
964 NS_ENSURE_TRUE(aWindow, NPERR_GENERIC_ERROR);
966 NPRemoteWindow window;
967 mWindowType = aWindow->type;
969 #if defined(OS_WIN)
970 // On windowless controls, reset the shared memory surface as needed.
971 if (mWindowType == NPWindowTypeDrawable) {
972 // SharedSurfaceSetWindow will take care of NPRemoteWindow.
973 if (!SharedSurfaceSetWindow(aWindow, window)) {
974 return NPERR_OUT_OF_MEMORY_ERROR;
977 else {
978 SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
980 window.window = reinterpret_cast<uint64_t>(aWindow->window);
981 window.x = aWindow->x;
982 window.y = aWindow->y;
983 window.width = aWindow->width;
984 window.height = aWindow->height;
985 window.type = aWindow->type;
987 #else
988 window.window = reinterpret_cast<uint64_t>(aWindow->window);
989 window.x = aWindow->x;
990 window.y = aWindow->y;
991 window.width = aWindow->width;
992 window.height = aWindow->height;
993 window.clipRect = aWindow->clipRect; // MacOS specific
994 window.type = aWindow->type;
995 #endif
997 #if defined(XP_MACOSX)
998 double floatScaleFactor = 1.0;
999 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor);
1000 int scaleFactor = ceil(floatScaleFactor);
1001 window.contentsScaleFactor = floatScaleFactor;
1003 if (mShWidth != window.width * scaleFactor || mShHeight != window.height * scaleFactor) {
1004 if (mDrawingModel == NPDrawingModelCoreAnimation ||
1005 mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
1006 mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height,
1007 floatScaleFactor);
1008 } else if (uint32_t(mShWidth * mShHeight) !=
1009 window.width * scaleFactor * window.height * scaleFactor) {
1010 if (mShWidth != 0 && mShHeight != 0) {
1011 DeallocShmem(mShSurface);
1012 mShWidth = 0;
1013 mShHeight = 0;
1016 if (window.width != 0 && window.height != 0) {
1017 if (!AllocShmem(window.width * scaleFactor * window.height*4 * scaleFactor,
1018 SharedMemory::TYPE_BASIC, &mShSurface)) {
1019 PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
1020 return NPERR_GENERIC_ERROR;
1024 mShWidth = window.width * scaleFactor;
1025 mShHeight = window.height * scaleFactor;
1027 #endif
1029 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
1030 const NPSetWindowCallbackStruct* ws_info =
1031 static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
1032 window.visualID = ws_info->visual ? ws_info->visual->visualid : None;
1033 window.colormap = ws_info->colormap;
1034 #endif
1036 if (!CallNPP_SetWindow(window))
1037 return NPERR_GENERIC_ERROR;
1039 return NPERR_NO_ERROR;
1042 NPError
1043 PluginInstanceParent::NPP_GetValue(NPPVariable aVariable,
1044 void* _retval)
1046 switch (aVariable) {
1048 case NPPVpluginWantsAllNetworkStreams: {
1049 bool wantsAllStreams;
1050 NPError rv;
1052 if (!CallNPP_GetValue_NPPVpluginWantsAllNetworkStreams(&wantsAllStreams, &rv)) {
1053 return NPERR_GENERIC_ERROR;
1056 if (NPERR_NO_ERROR != rv) {
1057 return rv;
1060 (*(NPBool*)_retval) = wantsAllStreams;
1061 return NPERR_NO_ERROR;
1064 #ifdef MOZ_X11
1065 case NPPVpluginNeedsXEmbed: {
1066 bool needsXEmbed;
1067 NPError rv;
1069 if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed, &rv)) {
1070 return NPERR_GENERIC_ERROR;
1073 if (NPERR_NO_ERROR != rv) {
1074 return rv;
1077 (*(NPBool*)_retval) = needsXEmbed;
1078 return NPERR_NO_ERROR;
1080 #endif
1082 case NPPVpluginScriptableNPObject: {
1083 PPluginScriptableObjectParent* actor;
1084 NPError rv;
1085 if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor, &rv)) {
1086 return NPERR_GENERIC_ERROR;
1089 if (NPERR_NO_ERROR != rv) {
1090 return rv;
1093 if (!actor) {
1094 NS_ERROR("NPPVpluginScriptableNPObject succeeded but null.");
1095 return NPERR_GENERIC_ERROR;
1098 const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
1099 if (!npn) {
1100 NS_WARNING("No netscape functions?!");
1101 return NPERR_GENERIC_ERROR;
1104 NPObject* object =
1105 static_cast<PluginScriptableObjectParent*>(actor)->GetObject(true);
1106 NS_ASSERTION(object, "This shouldn't ever be null!");
1108 (*(NPObject**)_retval) = npn->retainobject(object);
1109 return NPERR_NO_ERROR;
1112 #ifdef MOZ_ACCESSIBILITY_ATK
1113 case NPPVpluginNativeAccessibleAtkPlugId: {
1114 nsCString plugId;
1115 NPError rv;
1116 if (!CallNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(&plugId, &rv)) {
1117 return NPERR_GENERIC_ERROR;
1120 if (NPERR_NO_ERROR != rv) {
1121 return rv;
1124 (*(nsCString*)_retval) = plugId;
1125 return NPERR_NO_ERROR;
1127 #endif
1129 default:
1130 PR_LOG(GetPluginLog(), PR_LOG_WARNING,
1131 ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)",
1132 (int) aVariable, NPPVariableToString(aVariable)));
1133 return NPERR_GENERIC_ERROR;
1137 NPError
1138 PluginInstanceParent::NPP_SetValue(NPNVariable variable, void* value)
1140 switch (variable) {
1141 case NPNVprivateModeBool:
1142 NPError result;
1143 if (!CallNPP_SetValue_NPNVprivateModeBool(*static_cast<NPBool*>(value),
1144 &result))
1145 return NPERR_GENERIC_ERROR;
1147 return result;
1149 default:
1150 NS_ERROR("Unhandled NPNVariable in NPP_SetValue");
1151 PR_LOG(GetPluginLog(), PR_LOG_WARNING,
1152 ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)",
1153 (int) variable, NPNVariableToString(variable)));
1154 return NPERR_GENERIC_ERROR;
1158 void
1159 PluginInstanceParent::NPP_URLRedirectNotify(const char* url, int32_t status,
1160 void* notifyData)
1162 if (!notifyData)
1163 return;
1165 PStreamNotifyParent* streamNotify = static_cast<PStreamNotifyParent*>(notifyData);
1166 unused << streamNotify->SendRedirectNotify(NullableString(url), status);
1169 int16_t
1170 PluginInstanceParent::NPP_HandleEvent(void* event)
1172 PLUGIN_LOG_DEBUG_FUNCTION;
1174 #if defined(XP_MACOSX)
1175 NPCocoaEvent* npevent = reinterpret_cast<NPCocoaEvent*>(event);
1176 #else
1177 NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
1178 #endif
1179 NPRemoteEvent npremoteevent;
1180 npremoteevent.event = *npevent;
1181 #if defined(XP_MACOSX)
1182 double scaleFactor = 1.0;
1183 mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor);
1184 npremoteevent.contentsScaleFactor = scaleFactor;
1185 #endif
1186 int16_t handled = 0;
1188 #if defined(OS_WIN)
1189 if (mWindowType == NPWindowTypeDrawable) {
1190 if (IsAsyncDrawing()) {
1191 if (npevent->event == WM_PAINT || npevent->event == DoublePassRenderingEvent()) {
1192 // This plugin maintains its own async drawing.
1193 return handled;
1196 if (DoublePassRenderingEvent() == npevent->event) {
1197 return CallPaint(npremoteevent, &handled) && handled;
1200 switch (npevent->event) {
1201 case WM_PAINT:
1203 RECT rect;
1204 SharedSurfaceBeforePaint(rect, npremoteevent);
1205 if (!CallPaint(npremoteevent, &handled)) {
1206 handled = false;
1208 SharedSurfaceAfterPaint(npevent);
1209 return handled;
1211 break;
1213 case WM_KILLFOCUS:
1215 // When the user selects fullscreen mode in Flash video players,
1216 // WM_KILLFOCUS will be delayed by deferred event processing:
1217 // WM_LBUTTONUP results in a call to CreateWindow within Flash,
1218 // which fires WM_KILLFOCUS. Delayed delivery causes Flash to
1219 // misinterpret the event, dropping back out of fullscreen. Trap
1220 // this event and drop it.
1221 wchar_t szClass[26];
1222 HWND hwnd = GetForegroundWindow();
1223 if (hwnd && hwnd != mPluginHWND &&
1224 GetClassNameW(hwnd, szClass,
1225 sizeof(szClass)/sizeof(char16_t)) &&
1226 !wcscmp(szClass, kFlashFullscreenClass)) {
1227 return 0;
1230 break;
1232 case WM_WINDOWPOSCHANGED:
1234 // We send this in nsObjectFrame just before painting
1235 return SendWindowPosChanged(npremoteevent);
1237 break;
1240 #endif
1242 #if defined(MOZ_X11)
1243 switch (npevent->type) {
1244 case GraphicsExpose:
1245 PLUGIN_LOG_DEBUG((" schlepping drawable 0x%lx across the pipe\n",
1246 npevent->xgraphicsexpose.drawable));
1247 // Make sure the X server has created the Drawable and completes any
1248 // drawing before the plugin draws on top.
1250 // XSync() waits for the X server to complete. Really this parent
1251 // process does not need to wait; the child is the process that needs
1252 // to wait. A possibly-slightly-better alternative would be to send
1253 // an X event to the child that the child would wait for.
1254 FinishX(DefaultXDisplay());
1256 return CallPaint(npremoteevent, &handled) ? handled : 0;
1258 case ButtonPress:
1259 // Release any active pointer grab so that the plugin X client can
1260 // grab the pointer if it wishes.
1261 Display *dpy = DefaultXDisplay();
1262 # ifdef MOZ_WIDGET_GTK
1263 // GDK attempts to (asynchronously) track whether there is an active
1264 // grab so ungrab through GDK.
1265 gdk_pointer_ungrab(npevent->xbutton.time);
1266 # else
1267 XUngrabPointer(dpy, npevent->xbutton.time);
1268 # endif
1269 // Wait for the ungrab to complete.
1270 XSync(dpy, False);
1271 break;
1273 #endif
1275 #ifdef XP_MACOSX
1276 if (npevent->type == NPCocoaEventDrawRect) {
1277 if (mDrawingModel == NPDrawingModelCoreAnimation ||
1278 mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
1279 if (!mIOSurface) {
1280 NS_ERROR("No IOSurface allocated.");
1281 return false;
1283 if (!CallNPP_HandleEvent_IOSurface(npremoteevent,
1284 mIOSurface->GetIOSurfaceID(),
1285 &handled))
1286 return false; // no good way to handle errors here...
1288 CGContextRef cgContext = npevent->data.draw.context;
1289 if (!mShColorSpace) {
1290 mShColorSpace = CreateSystemColorSpace();
1292 if (!mShColorSpace) {
1293 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
1294 return false;
1296 if (cgContext) {
1297 nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface,
1298 mShColorSpace,
1299 npevent->data.draw.x,
1300 npevent->data.draw.y,
1301 npevent->data.draw.width,
1302 npevent->data.draw.height);
1304 return true;
1305 } else if (mFrontIOSurface) {
1306 CGContextRef cgContext = npevent->data.draw.context;
1307 if (!mShColorSpace) {
1308 mShColorSpace = CreateSystemColorSpace();
1310 if (!mShColorSpace) {
1311 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
1312 return false;
1314 if (cgContext) {
1315 nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface,
1316 mShColorSpace,
1317 npevent->data.draw.x,
1318 npevent->data.draw.y,
1319 npevent->data.draw.width,
1320 npevent->data.draw.height);
1322 return true;
1323 } else {
1324 if (mShWidth == 0 && mShHeight == 0) {
1325 PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
1326 return false;
1328 if (!mShSurface.IsReadable()) {
1329 PLUGIN_LOG_DEBUG(("Shmem is not readable."));
1330 return false;
1333 if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface,
1334 &handled, &mShSurface))
1335 return false; // no good way to handle errors here...
1337 if (!mShSurface.IsReadable()) {
1338 PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed "
1339 "or we have a bug."));
1340 return false;
1343 char* shContextByte = mShSurface.get<char>();
1345 if (!mShColorSpace) {
1346 mShColorSpace = CreateSystemColorSpace();
1348 if (!mShColorSpace) {
1349 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
1350 return false;
1352 CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
1353 mShWidth, mShHeight, 8,
1354 mShWidth*4, mShColorSpace,
1355 kCGImageAlphaPremultipliedFirst |
1356 kCGBitmapByteOrder32Host);
1357 if (!shContext) {
1358 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
1359 return false;
1362 CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
1363 if (shImage) {
1364 CGContextRef cgContext = npevent->data.draw.context;
1366 ::CGContextDrawImage(cgContext,
1367 CGRectMake(0,0,mShWidth,mShHeight),
1368 shImage);
1369 ::CGImageRelease(shImage);
1370 } else {
1371 ::CGContextRelease(shContext);
1372 return false;
1374 ::CGContextRelease(shContext);
1375 return true;
1378 #endif
1380 if (!CallNPP_HandleEvent(npremoteevent, &handled))
1381 return 0; // no good way to handle errors here...
1383 return handled;
1386 NPError
1387 PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
1388 NPBool seekable, uint16_t* stype)
1390 PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)",
1391 FULLFUNCTION, (char*) type, (void*) stream, (int) seekable));
1393 BrowserStreamParent* bs = new BrowserStreamParent(this, stream);
1395 NPError err;
1396 if (!CallPBrowserStreamConstructor(bs,
1397 NullableString(stream->url),
1398 stream->end,
1399 stream->lastmodified,
1400 static_cast<PStreamNotifyParent*>(stream->notifyData),
1401 NullableString(stream->headers),
1402 NullableString(type), seekable,
1403 &err, stype))
1404 return NPERR_GENERIC_ERROR;
1406 if (NPERR_NO_ERROR != err)
1407 unused << PBrowserStreamParent::Send__delete__(bs);
1409 return err;
1412 NPError
1413 PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
1415 PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)",
1416 FULLFUNCTION, (void*) stream, (int) reason));
1418 AStream* s = static_cast<AStream*>(stream->pdata);
1419 if (s->IsBrowserStream()) {
1420 BrowserStreamParent* sp =
1421 static_cast<BrowserStreamParent*>(s);
1422 if (sp->mNPP != this)
1423 NS_RUNTIMEABORT("Mismatched plugin data");
1425 sp->NPP_DestroyStream(reason);
1426 return NPERR_NO_ERROR;
1428 else {
1429 PluginStreamParent* sp =
1430 static_cast<PluginStreamParent*>(s);
1431 if (sp->mInstance != this)
1432 NS_RUNTIMEABORT("Mismatched plugin data");
1434 return PPluginStreamParent::Call__delete__(sp, reason, false) ?
1435 NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1439 void
1440 PluginInstanceParent::NPP_Print(NPPrint* platformPrint)
1442 // TODO: implement me
1443 NS_ERROR("Not implemented");
1446 PPluginScriptableObjectParent*
1447 PluginInstanceParent::AllocPPluginScriptableObjectParent()
1449 return new PluginScriptableObjectParent(Proxy);
1452 #ifdef DEBUG
1453 namespace {
1455 struct ActorSearchData
1457 PluginScriptableObjectParent* actor;
1458 bool found;
1461 PLDHashOperator
1462 ActorSearch(NPObject* aKey,
1463 PluginScriptableObjectParent* aData,
1464 void* aUserData)
1466 ActorSearchData* asd = reinterpret_cast<ActorSearchData*>(aUserData);
1467 if (asd->actor == aData) {
1468 asd->found = true;
1469 return PL_DHASH_STOP;
1471 return PL_DHASH_NEXT;
1474 } // anonymous namespace
1475 #endif // DEBUG
1477 bool
1478 PluginInstanceParent::DeallocPPluginScriptableObjectParent(
1479 PPluginScriptableObjectParent* aObject)
1481 PluginScriptableObjectParent* actor =
1482 static_cast<PluginScriptableObjectParent*>(aObject);
1484 NPObject* object = actor->GetObject(false);
1485 if (object) {
1486 NS_ASSERTION(mScriptableObjects.Get(object, nullptr),
1487 "NPObject not in the hash!");
1488 mScriptableObjects.Remove(object);
1490 #ifdef DEBUG
1491 else {
1492 ActorSearchData asd = { actor, false };
1493 mScriptableObjects.EnumerateRead(ActorSearch, &asd);
1494 NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!");
1496 #endif
1498 delete actor;
1499 return true;
1502 bool
1503 PluginInstanceParent::RecvPPluginScriptableObjectConstructor(
1504 PPluginScriptableObjectParent* aActor)
1506 // This is only called in response to the child process requesting the
1507 // creation of an actor. This actor will represent an NPObject that is
1508 // created by the plugin and returned to the browser.
1509 PluginScriptableObjectParent* actor =
1510 static_cast<PluginScriptableObjectParent*>(aActor);
1511 NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!");
1513 actor->InitializeProxy();
1514 NS_ASSERTION(actor->GetObject(false), "Actor should have an object!");
1516 return true;
1519 void
1520 PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason,
1521 void* notifyData)
1523 PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)",
1524 FULLFUNCTION, url, (int) reason, notifyData));
1526 PStreamNotifyParent* streamNotify =
1527 static_cast<PStreamNotifyParent*>(notifyData);
1528 unused << PStreamNotifyParent::Send__delete__(streamNotify, reason);
1531 bool
1532 PluginInstanceParent::RegisterNPObjectForActor(
1533 NPObject* aObject,
1534 PluginScriptableObjectParent* aActor)
1536 NS_ASSERTION(aObject && aActor, "Null pointers!");
1537 NS_ASSERTION(!mScriptableObjects.Get(aObject, nullptr), "Duplicate entry!");
1538 mScriptableObjects.Put(aObject, aActor);
1539 return true;
1542 void
1543 PluginInstanceParent::UnregisterNPObject(NPObject* aObject)
1545 NS_ASSERTION(aObject, "Null pointer!");
1546 NS_ASSERTION(mScriptableObjects.Get(aObject, nullptr), "Unknown entry!");
1547 mScriptableObjects.Remove(aObject);
1550 PluginScriptableObjectParent*
1551 PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
1553 NS_ASSERTION(aObject, "Null pointer!");
1555 if (aObject->_class == PluginScriptableObjectParent::GetClass()) {
1556 // One of ours!
1557 ParentNPObject* object = static_cast<ParentNPObject*>(aObject);
1558 NS_ASSERTION(object->parent, "Null actor!");
1559 return object->parent;
1562 PluginScriptableObjectParent* actor;
1563 if (mScriptableObjects.Get(aObject, &actor)) {
1564 return actor;
1567 actor = new PluginScriptableObjectParent(LocalObject);
1568 if (!actor) {
1569 NS_ERROR("Out of memory!");
1570 return nullptr;
1573 if (!SendPPluginScriptableObjectConstructor(actor)) {
1574 NS_WARNING("Failed to send constructor message!");
1575 return nullptr;
1578 actor->InitializeLocal(aObject);
1579 return actor;
1582 PPluginSurfaceParent*
1583 PluginInstanceParent::AllocPPluginSurfaceParent(const WindowsSharedMemoryHandle& handle,
1584 const gfxIntSize& size,
1585 const bool& transparent)
1587 #ifdef XP_WIN
1588 return new PluginSurfaceParent(handle, size, transparent);
1589 #else
1590 NS_ERROR("This shouldn't be called!");
1591 return nullptr;
1592 #endif
1595 bool
1596 PluginInstanceParent::DeallocPPluginSurfaceParent(PPluginSurfaceParent* s)
1598 #ifdef XP_WIN
1599 delete s;
1600 return true;
1601 #else
1602 return false;
1603 #endif
1606 bool
1607 PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState)
1609 mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0);
1610 return true;
1613 bool
1614 PluginInstanceParent::AnswerNPN_PopPopupsEnabledState()
1616 mNPNIface->poppopupsenabledstate(mNPP);
1617 return true;
1620 bool
1621 PluginInstanceParent::AnswerNPN_GetValueForURL(const NPNURLVariable& variable,
1622 const nsCString& url,
1623 nsCString* value,
1624 NPError* result)
1626 char* v;
1627 uint32_t len;
1629 *result = mNPNIface->getvalueforurl(mNPP, (NPNURLVariable) variable,
1630 url.get(), &v, &len);
1631 if (NPERR_NO_ERROR == *result)
1632 value->Adopt(v, len);
1634 return true;
1637 bool
1638 PluginInstanceParent::AnswerNPN_SetValueForURL(const NPNURLVariable& variable,
1639 const nsCString& url,
1640 const nsCString& value,
1641 NPError* result)
1643 *result = mNPNIface->setvalueforurl(mNPP, (NPNURLVariable) variable,
1644 url.get(), value.get(),
1645 value.Length());
1646 return true;
1649 bool
1650 PluginInstanceParent::AnswerNPN_GetAuthenticationInfo(const nsCString& protocol,
1651 const nsCString& host,
1652 const int32_t& port,
1653 const nsCString& scheme,
1654 const nsCString& realm,
1655 nsCString* username,
1656 nsCString* password,
1657 NPError* result)
1659 char* u;
1660 uint32_t ulen;
1661 char* p;
1662 uint32_t plen;
1664 *result = mNPNIface->getauthenticationinfo(mNPP, protocol.get(),
1665 host.get(), port,
1666 scheme.get(), realm.get(),
1667 &u, &ulen, &p, &plen);
1668 if (NPERR_NO_ERROR == *result) {
1669 username->Adopt(u, ulen);
1670 password->Adopt(p, plen);
1672 return true;
1675 bool
1676 PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX,
1677 const bool& ignoreDestX,
1678 const double& sourceY,
1679 const bool& ignoreDestY,
1680 const NPCoordinateSpace& sourceSpace,
1681 const NPCoordinateSpace& destSpace,
1682 double *destX,
1683 double *destY,
1684 bool *result)
1686 *result = mNPNIface->convertpoint(mNPP, sourceX, sourceY, sourceSpace,
1687 ignoreDestX ? nullptr : destX,
1688 ignoreDestY ? nullptr : destY,
1689 destSpace);
1691 return true;
1694 bool
1695 PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size,
1696 const NPImageFormat& format,
1697 NPRemoteAsyncSurface* surfData,
1698 bool* result)
1700 if (!IsAsyncDrawing()) {
1701 *result = false;
1702 return true;
1705 switch (mDrawingModel) {
1706 case NPDrawingModelAsyncBitmapSurface: {
1707 Shmem sharedMem;
1708 if (!AllocUnsafeShmem(size.width * size.height * 4, SharedMemory::TYPE_BASIC, &sharedMem)) {
1709 *result = false;
1710 return true;
1713 surfData->size() = size;
1714 surfData->hostPtr() = (uintptr_t)sharedMem.get<unsigned char>();
1715 surfData->stride() = size.width * 4;
1716 surfData->format() = format;
1717 surfData->data() = sharedMem;
1718 *result = true;
1719 return true;
1721 #ifdef XP_WIN
1722 case NPDrawingModelAsyncWindowsDXGISurface: {
1723 ID3D10Device1 *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
1725 nsRefPtr<ID3D10Texture2D> texture;
1727 CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, size.width, size.height, 1, 1);
1728 desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
1729 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
1730 if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)))) {
1731 *result = false;
1732 return true;
1735 nsRefPtr<IDXGIResource> resource;
1736 if (FAILED(texture->QueryInterface(IID_IDXGIResource, getter_AddRefs(resource)))) {
1737 *result = false;
1738 return true;
1741 HANDLE sharedHandle;
1743 if (FAILED(resource->GetSharedHandle(&sharedHandle))) {
1744 *result = false;
1745 return true;
1748 surfData->size() = size;
1749 surfData->data() = sharedHandle;
1750 surfData->format() = format;
1752 mTextureMap.Put(sharedHandle, texture);
1753 *result = true;
1755 #endif
1758 return true;
1761 bool
1762 PluginInstanceParent::RecvRedrawPlugin()
1764 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
1765 if (!inst) {
1766 return false;
1769 inst->RedrawPlugin();
1770 return true;
1773 bool
1774 PluginInstanceParent::RecvNegotiatedCarbon()
1776 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
1777 if (!inst) {
1778 return false;
1780 inst->CarbonNPAPIFailure();
1781 return true;
1784 bool
1785 PluginInstanceParent::RecvReleaseDXGISharedSurface(const DXGISharedSurfaceHandle &aHandle)
1787 #ifdef XP_WIN
1788 mTextureMap.Remove(aHandle);
1789 #endif
1790 return true;
1793 #if defined(OS_WIN)
1796 plugin focus changes between processes
1798 focus from dom -> child:
1799 Focus manager calls on widget to set the focus on the window.
1800 We pick up the resulting wm_setfocus event here, and forward
1801 that over ipc to the child which calls set focus on itself.
1803 focus from child -> focus manager:
1804 Child picks up the local wm_setfocus and sends it via ipc over
1805 here. We then post a custom event to widget/windows/nswindow
1806 which fires off a gui event letting the browser know.
1809 static const wchar_t kPluginInstanceParentProperty[] =
1810 L"PluginInstanceParentProperty";
1812 // static
1813 LRESULT CALLBACK
1814 PluginInstanceParent::PluginWindowHookProc(HWND hWnd,
1815 UINT message,
1816 WPARAM wParam,
1817 LPARAM lParam)
1819 PluginInstanceParent* self = reinterpret_cast<PluginInstanceParent*>(
1820 ::GetPropW(hWnd, kPluginInstanceParentProperty));
1821 if (!self) {
1822 NS_NOTREACHED("PluginInstanceParent::PluginWindowHookProc null this ptr!");
1823 return DefWindowProc(hWnd, message, wParam, lParam);
1826 NS_ASSERTION(self->mPluginHWND == hWnd, "Wrong window!");
1828 switch (message) {
1829 case WM_SETFOCUS:
1830 // Let the child plugin window know it should take focus.
1831 unused << self->CallSetPluginFocus();
1832 break;
1834 case WM_CLOSE:
1835 self->UnsubclassPluginWindow();
1836 break;
1839 if (self->mPluginWndProc == PluginWindowHookProc) {
1840 NS_NOTREACHED(
1841 "PluginWindowHookProc invoking mPluginWndProc w/"
1842 "mPluginWndProc == PluginWindowHookProc????");
1843 return DefWindowProc(hWnd, message, wParam, lParam);
1845 return ::CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
1846 lParam);
1849 void
1850 PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
1852 NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
1853 "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
1855 if (!mPluginHWND) {
1856 mPluginHWND = aWnd;
1857 mPluginWndProc =
1858 (WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
1859 reinterpret_cast<LONG_PTR>(PluginWindowHookProc));
1860 DebugOnly<bool> bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this);
1861 NS_ASSERTION(mPluginWndProc,
1862 "PluginInstanceParent::SubclassPluginWindow failed to set subclass!");
1863 NS_ASSERTION(bRes,
1864 "PluginInstanceParent::SubclassPluginWindow failed to set prop!");
1868 void
1869 PluginInstanceParent::UnsubclassPluginWindow()
1871 if (mPluginHWND && mPluginWndProc) {
1872 ::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
1873 reinterpret_cast<LONG_PTR>(mPluginWndProc));
1875 ::RemovePropW(mPluginHWND, kPluginInstanceParentProperty);
1877 mPluginWndProc = nullptr;
1878 mPluginHWND = nullptr;
1882 /* windowless drawing helpers */
1885 * Origin info:
1887 * windowless, offscreen:
1889 * WM_WINDOWPOSCHANGED: origin is relative to container
1890 * setwindow: origin is 0,0
1891 * WM_PAINT: origin is 0,0
1893 * windowless, native:
1895 * WM_WINDOWPOSCHANGED: origin is relative to container
1896 * setwindow: origin is relative to container
1897 * WM_PAINT: origin is relative to container
1899 * PluginInstanceParent:
1901 * painting: mPluginPort (nsIntRect, saved in SetWindow)
1904 void
1905 PluginInstanceParent::SharedSurfaceRelease()
1907 mSharedSurfaceDib.Close();
1910 bool
1911 PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
1912 NPRemoteWindow& aRemoteWindow)
1914 aRemoteWindow.window = 0;
1915 aRemoteWindow.x = aWindow->x;
1916 aRemoteWindow.y = aWindow->y;
1917 aRemoteWindow.width = aWindow->width;
1918 aRemoteWindow.height = aWindow->height;
1919 aRemoteWindow.type = aWindow->type;
1921 nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height);
1923 // save the the rect location within the browser window.
1924 mPluginPort = newPort;
1926 // move the port to our shared surface origin
1927 newPort.MoveTo(0,0);
1929 // check to see if we have the room in shared surface
1930 if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) {
1931 // ok to paint
1932 aRemoteWindow.surfaceHandle = 0;
1933 return true;
1936 // allocate a new shared surface
1937 SharedSurfaceRelease();
1938 if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window),
1939 newPort.width, newPort.height, false)))
1940 return false;
1942 // save the new shared surface size we just allocated
1943 mSharedSize = newPort;
1945 base::SharedMemoryHandle handle;
1946 if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle)))
1947 return false;
1949 aRemoteWindow.surfaceHandle = handle;
1951 return true;
1954 void
1955 PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect,
1956 NPRemoteEvent& npremoteevent)
1958 RECT* dr = (RECT*)npremoteevent.event.lParam;
1959 HDC parentHdc = (HDC)npremoteevent.event.wParam;
1961 nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
1962 dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect
1964 ::BitBlt(mSharedSurfaceDib.GetHDC(),
1965 dirtyRect.x,
1966 dirtyRect.y,
1967 dirtyRect.width,
1968 dirtyRect.height,
1969 parentHdc,
1970 dr->left,
1971 dr->top,
1972 SRCCOPY);
1974 // setup the translated dirty rect we'll send to the child
1975 rect.left = dirtyRect.x;
1976 rect.top = dirtyRect.y;
1977 rect.right = dirtyRect.x + dirtyRect.width;
1978 rect.bottom = dirtyRect.y + dirtyRect.height;
1980 npremoteevent.event.wParam = WPARAM(0);
1981 npremoteevent.event.lParam = LPARAM(&rect);
1984 void
1985 PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent)
1987 RECT* dr = (RECT*)npevent->lParam;
1988 HDC parentHdc = (HDC)npevent->wParam;
1990 nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
1991 dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y);
1993 // src copy the shared dib into the parent surface we are handed.
1994 ::BitBlt(parentHdc,
1995 dr->left,
1996 dr->top,
1997 dirtyRect.width,
1998 dirtyRect.height,
1999 mSharedSurfaceDib.GetHDC(),
2000 dirtyRect.x,
2001 dirtyRect.y,
2002 SRCCOPY);
2005 #endif // defined(OS_WIN)
2007 bool
2008 PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus)
2010 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
2012 // Currently only in use on windows - an rpc event we receive from the
2013 // child when it's plugin window (or one of it's children) receives keyboard
2014 // focus. We forward the event down to widget so the dom/focus manager can
2015 // be updated.
2016 #if defined(OS_WIN)
2017 ::SendMessage(mPluginHWND, gOOPPPluginFocusEvent, gotFocus ? 1 : 0, 0);
2018 return true;
2019 #else
2020 NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!");
2021 return false;
2022 #endif