1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Plugin App.
18 * The Initial Developer of the Original Code is
19 * Chris Jones <jones.chris.g@gmail.com>
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
24 * Jim Mathies <jmathies@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "PluginInstanceParent.h"
42 #include "BrowserStreamParent.h"
43 #include "PluginModuleParent.h"
44 #include "PluginStreamParent.h"
45 #include "StreamNotifyParent.h"
47 #include "npfunctions.h"
48 #include "nsAutoPtr.h"
54 using namespace mozilla::plugins
;
56 PluginInstanceParent::PluginInstanceParent(PluginModuleParent
* parent
,
58 const NPNetscapeFuncs
* npniface
)
62 mWindowType(NPWindowTypeWindow
)
66 PluginInstanceParent::~PluginInstanceParent()
73 PluginInstanceParent::Destroy()
75 // Copy the actors here so we don't enumerate a mutating array.
76 nsAutoTArray
<PluginScriptableObjectParent
*, 10> objects
;
77 PRUint32 count
= mScriptableObjects
.Length();
78 for (PRUint32 index
= 0; index
< count
; index
++) {
79 objects
.AppendElement(mScriptableObjects
[index
]);
82 count
= objects
.Length();
83 for (PRUint32 index
= 0; index
< count
; index
++) {
84 NPObject
* object
= objects
[index
]->GetObject();
85 if (object
->_class
== PluginScriptableObjectParent::GetClass()) {
86 PluginScriptableObjectParent::ScriptableInvalidate(object
);
91 SharedSurfaceRelease();
96 PluginInstanceParent::AllocPBrowserStream(const nsCString
& url
,
97 const uint32_t& length
,
98 const uint32_t& lastmodified
,
99 PStreamNotifyParent
* notifyData
,
100 const nsCString
& headers
,
101 const nsCString
& mimeType
,
102 const bool& seekable
,
106 NS_RUNTIMEABORT("Not reachable");
111 PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent
* stream
)
118 PluginInstanceParent::AllocPPluginStream(const nsCString
& mimeType
,
119 const nsCString
& target
,
122 return new PluginStreamParent(this, mimeType
, target
, result
);
126 PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent
* stream
)
133 PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
138 *result
= mNPNIface
->getvalue(mNPP
, NPNVjavascriptEnabledBool
, &v
);
144 PluginInstanceParent::AnswerNPN_GetValue_NPNVisOfflineBool(bool* value
,
148 *result
= mNPNIface
->getvalue(mNPP
, NPNVisOfflineBool
, &v
);
154 PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(intptr_t* value
,
159 *result
= mNPNIface
->getvalue(mNPP
, NPNVnetscapeWindow
, &hwnd
);
160 *value
= (intptr_t)hwnd
;
167 PluginInstanceParent::InternalGetValueForNPObject(
168 NPNVariable aVariable
,
169 PPluginScriptableObjectParent
** aValue
,
173 NPError result
= mNPNIface
->getvalue(mNPP
, aVariable
, (void*)&npobject
);
174 if (result
== NPERR_NO_ERROR
) {
175 NS_ASSERTION(npobject
, "Shouldn't return null and NPERR_NO_ERROR!");
177 PluginScriptableObjectParent
* actor
= GetActorForNPObject(npobject
);
178 mNPNIface
->releaseobject(npobject
);
181 *aResult
= NPERR_NO_ERROR
;
185 NS_ERROR("Failed to get actor!");
186 result
= NPERR_GENERIC_ERROR
;
195 PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject(
196 PPluginScriptableObjectParent
** aValue
,
199 return InternalGetValueForNPObject(NPNVWindowNPObject
, aValue
, aResult
);
203 PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject(
204 PPluginScriptableObjectParent
** aValue
,
207 return InternalGetValueForNPObject(NPNVPluginElementNPObject
, aValue
,
212 PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value
,
216 *result
= mNPNIface
->getvalue(mNPP
, NPNVprivateModeBool
, &v
);
223 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
224 const bool& windowed
, NPError
* result
)
226 NPBool isWindowed
= windowed
;
227 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginWindowBool
,
233 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
234 const bool& transparent
, NPError
* result
)
236 NPBool isTransparent
= transparent
;
237 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginTransparentBool
,
238 (void*)isTransparent
);
244 PluginInstanceParent::AnswerNPN_GetURL(const nsCString
& url
,
245 const nsCString
& target
,
248 *result
= mNPNIface
->geturl(mNPP
,
249 NullableStringGet(url
),
250 NullableStringGet(target
));
255 PluginInstanceParent::AnswerNPN_PostURL(const nsCString
& url
,
256 const nsCString
& target
,
257 const nsCString
& buffer
,
261 *result
= mNPNIface
->posturl(mNPP
, url
.get(), NullableStringGet(target
),
262 buffer
.Length(), buffer
.get(), file
);
267 PluginInstanceParent::AllocPStreamNotify(const nsCString
& url
,
268 const nsCString
& target
,
270 const nsCString
& buffer
,
274 return new StreamNotifyParent();
278 PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent
* actor
,
279 const nsCString
& url
,
280 const nsCString
& target
,
282 const nsCString
& buffer
,
286 bool streamDestroyed
= false;
287 static_cast<StreamNotifyParent
*>(actor
)->
288 SetDestructionFlag(&streamDestroyed
);
291 *result
= mNPNIface
->geturlnotify(mNPP
,
292 NullableStringGet(url
),
293 NullableStringGet(target
),
297 *result
= mNPNIface
->posturlnotify(mNPP
,
298 NullableStringGet(url
),
299 NullableStringGet(target
),
301 NullableStringGet(buffer
),
305 if (!streamDestroyed
) {
306 static_cast<StreamNotifyParent
*>(actor
)->ClearDestructionFlag();
307 if (*result
!= NPERR_NO_ERROR
)
308 PStreamNotifyParent::Call__delete__(actor
, NPERR_GENERIC_ERROR
);
315 PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent
* notifyData
)
322 PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect
& rect
)
324 mNPNIface
->invalidaterect(mNPP
, const_cast<NPRect
*>(&rect
));
329 PluginInstanceParent::NPP_SetWindow(const NPWindow
* aWindow
)
331 PLUGIN_LOG_DEBUG(("%s (aWindow=%p)", FULLFUNCTION
, (void*) aWindow
));
333 NS_ENSURE_TRUE(aWindow
, NPERR_GENERIC_ERROR
);
335 NPRemoteWindow window
;
336 mWindowType
= aWindow
->type
;
339 // On windowless controls, reset the shared memory surface as needed.
340 if (mWindowType
== NPWindowTypeDrawable
) {
341 // SharedSurfaceSetWindow will take care of NPRemoteWindow.
342 if (!SharedSurfaceSetWindow(aWindow
, window
)) {
343 return NPERR_OUT_OF_MEMORY_ERROR
;
347 window
.window
= reinterpret_cast<unsigned long>(aWindow
->window
);
348 window
.x
= aWindow
->x
;
349 window
.y
= aWindow
->y
;
350 window
.width
= aWindow
->width
;
351 window
.height
= aWindow
->height
;
352 window
.type
= aWindow
->type
;
355 window
.window
= reinterpret_cast<unsigned long>(aWindow
->window
);
356 window
.x
= aWindow
->x
;
357 window
.y
= aWindow
->y
;
358 window
.width
= aWindow
->width
;
359 window
.height
= aWindow
->height
;
360 window
.clipRect
= aWindow
->clipRect
; // MacOS specific
361 window
.type
= aWindow
->type
;
364 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
365 const NPSetWindowCallbackStruct
* ws_info
=
366 static_cast<NPSetWindowCallbackStruct
*>(aWindow
->ws_info
);
367 window
.visualID
= ws_info
->visual
? ws_info
->visual
->visualid
: None
;
368 window
.colormap
= ws_info
->colormap
;
372 if (!CallNPP_SetWindow(window
, &prv
))
373 return NPERR_GENERIC_ERROR
;
378 PluginInstanceParent::NPP_GetValue(NPPVariable aVariable
,
383 case NPPVpluginWindowBool
: {
387 if (!CallNPP_GetValue_NPPVpluginWindow(&windowed
, &rv
)) {
388 return NPERR_GENERIC_ERROR
;
391 if (NPERR_NO_ERROR
!= rv
) {
395 (*(NPBool
*)_retval
) = windowed
;
396 return NPERR_NO_ERROR
;
399 case NPPVpluginTransparentBool
: {
403 if (!CallNPP_GetValue_NPPVpluginTransparent(&transparent
, &rv
)) {
404 return NPERR_GENERIC_ERROR
;
407 if (NPERR_NO_ERROR
!= rv
) {
411 (*(NPBool
*)_retval
) = transparent
;
412 return NPERR_NO_ERROR
;
416 case NPPVpluginNeedsXEmbed
: {
420 if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed
, &rv
)) {
421 return NPERR_GENERIC_ERROR
;
424 if (NPERR_NO_ERROR
!= rv
) {
428 (*(NPBool
*)_retval
) = needsXEmbed
;
429 return NPERR_NO_ERROR
;
433 case NPPVpluginScriptableNPObject
: {
434 PPluginScriptableObjectParent
* actor
;
436 if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor
, &rv
)) {
437 return NPERR_GENERIC_ERROR
;
440 if (NPERR_NO_ERROR
!= rv
) {
445 NS_ERROR("NPPVpluginScriptableNPObject succeeded but null.");
446 return NPERR_GENERIC_ERROR
;
449 const NPNetscapeFuncs
* npn
= mParent
->GetNetscapeFuncs();
451 NS_WARNING("No netscape functions?!");
452 return NPERR_GENERIC_ERROR
;
456 static_cast<PluginScriptableObjectParent
*>(actor
)->GetObject();
457 NS_ASSERTION(object
, "This shouldn't ever be null!");
459 (*(NPObject
**)_retval
) = npn
->retainobject(object
);
460 return NPERR_NO_ERROR
;
464 PR_LOG(gPluginLog
, PR_LOG_WARNING
,
465 ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)",
466 (int) aVariable
, NPPVariableToString(aVariable
)));
467 return NPERR_GENERIC_ERROR
;
472 PluginInstanceParent::NPP_HandleEvent(void* event
)
474 PLUGIN_LOG_DEBUG_FUNCTION
;
476 NPEvent
* npevent
= reinterpret_cast<NPEvent
*>(event
);
477 NPRemoteEvent npremoteevent
;
478 npremoteevent
.event
= *npevent
;
482 if (mWindowType
== NPWindowTypeDrawable
) {
483 switch(npevent
->event
) {
487 SharedSurfaceBeforePaint(rect
, npremoteevent
);
488 if (!CallNPP_HandleEvent(npremoteevent
, &handled
))
491 SharedSurfaceAfterPaint(npevent
);
495 if (!CallNPP_HandleEvent(npremoteevent
, &handled
))
501 if (!CallNPP_HandleEvent(npremoteevent
, &handled
))
507 if (GraphicsExpose
== npevent
->type
) {
508 printf(" schlepping drawable 0x%lx across the pipe\n",
509 npevent
->xgraphicsexpose
.drawable
);
510 // Make sure the X server has created the Drawable and completes any
511 // drawing before the plugin draws on top.
513 // XSync() waits for the X server to complete. Really this parent
514 // process does not need to wait; the child is the process that needs
515 // to wait. A possibly-slightly-better alternative would be to send
516 // an X event to the child that the child would wait for.
517 # ifdef MOZ_WIDGET_GTK2
518 XSync(GDK_DISPLAY(), False
);
522 if (!CallNPP_HandleEvent(npremoteevent
, &handled
))
523 return 0; // no good way to handle errors here...
530 PluginInstanceParent::NPP_NewStream(NPMIMEType type
, NPStream
* stream
,
531 NPBool seekable
, uint16_t* stype
)
533 PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)",
534 FULLFUNCTION
, (char*) type
, (void*) stream
, (int) seekable
));
536 BrowserStreamParent
* bs
= new BrowserStreamParent(this, stream
);
539 if (!CallPBrowserStreamConstructor(bs
,
540 NullableString(stream
->url
),
542 stream
->lastmodified
,
543 static_cast<PStreamNotifyParent
*>(stream
->notifyData
),
544 NullableString(stream
->headers
),
545 NullableString(type
), seekable
,
547 return NPERR_GENERIC_ERROR
;
549 if (NPERR_NO_ERROR
!= err
)
550 PBrowserStreamParent::Call__delete__(bs
, NPERR_GENERIC_ERROR
, true);
556 PluginInstanceParent::NPP_DestroyStream(NPStream
* stream
, NPReason reason
)
558 PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)",
559 FULLFUNCTION
, (void*) stream
, (int) reason
));
561 AStream
* s
= static_cast<AStream
*>(stream
->pdata
);
562 if (s
->IsBrowserStream()) {
563 BrowserStreamParent
* sp
=
564 static_cast<BrowserStreamParent
*>(s
);
565 if (sp
->mNPP
!= this)
566 NS_RUNTIMEABORT("Mismatched plugin data");
568 PBrowserStreamParent::Call__delete__(sp
, reason
, false);
569 return NPERR_NO_ERROR
;
572 PluginStreamParent
* sp
=
573 static_cast<PluginStreamParent
*>(s
);
574 if (sp
->mInstance
!= this)
575 NS_RUNTIMEABORT("Mismatched plugin data");
577 PPluginStreamParent::Call__delete__(sp
, reason
, false);
578 return NPERR_NO_ERROR
;
582 PPluginScriptableObjectParent
*
583 PluginInstanceParent::AllocPPluginScriptableObject()
585 nsAutoPtr
<PluginScriptableObjectParent
>* object
=
586 mScriptableObjects
.AppendElement();
587 NS_ENSURE_TRUE(object
, nsnull
);
589 *object
= new PluginScriptableObjectParent();
590 NS_ENSURE_TRUE(*object
, nsnull
);
592 return object
->get();
596 PluginInstanceParent::DeallocPPluginScriptableObject(
597 PPluginScriptableObjectParent
* aObject
)
599 PluginScriptableObjectParent
* object
=
600 reinterpret_cast<PluginScriptableObjectParent
*>(aObject
);
602 PRUint32 count
= mScriptableObjects
.Length();
603 for (PRUint32 index
= 0; index
< count
; index
++) {
604 if (mScriptableObjects
[index
] == object
) {
605 mScriptableObjects
.RemoveElementAt(index
);
609 NS_NOTREACHED("An actor we don't know about?!");
614 PluginInstanceParent::AnswerPPluginScriptableObjectConstructor(
615 PPluginScriptableObjectParent
* aActor
)
617 // This is only called in response to the child process requesting the
618 // creation of an actor. This actor will represent an NPObject that is
619 // created by the plugin and returned to the browser.
620 const NPNetscapeFuncs
* npn
= mParent
->GetNetscapeFuncs();
622 NS_WARNING("No netscape function pointers?!");
627 const_cast<NPClass
*>(PluginScriptableObjectParent::GetClass());
629 ParentNPObject
* object
= reinterpret_cast<ParentNPObject
*>(
630 npn
->createobject(mNPP
, npclass
));
632 NS_WARNING("Failed to create NPObject!");
636 static_cast<PluginScriptableObjectParent
*>(aActor
)->Initialize(
637 const_cast<PluginInstanceParent
*>(this), object
);
642 PluginInstanceParent::NPP_URLNotify(const char* url
, NPReason reason
,
645 PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)",
646 FULLFUNCTION
, url
, (int) reason
, notifyData
));
648 PStreamNotifyParent
* streamNotify
=
649 static_cast<PStreamNotifyParent
*>(notifyData
);
650 PStreamNotifyParent::Call__delete__(streamNotify
, reason
);
653 PluginScriptableObjectParent
*
654 PluginInstanceParent::GetActorForNPObject(NPObject
* aObject
)
656 NS_ASSERTION(aObject
, "Null pointer!");
658 if (aObject
->_class
== PluginScriptableObjectParent::GetClass()) {
660 ParentNPObject
* object
= static_cast<ParentNPObject
*>(aObject
);
661 NS_ASSERTION(object
->parent
, "Null actor!");
662 return object
->parent
;
665 PRUint32 count
= mScriptableObjects
.Length();
666 for (PRUint32 index
= 0; index
< count
; index
++) {
667 nsAutoPtr
<PluginScriptableObjectParent
>& actor
=
668 mScriptableObjects
[index
];
669 if (actor
->GetObject() == aObject
) {
674 PluginScriptableObjectParent
* actor
=
675 static_cast<PluginScriptableObjectParent
*>(
676 CallPPluginScriptableObjectConstructor());
677 NS_ENSURE_TRUE(actor
, nsnull
);
679 actor
->Initialize(const_cast<PluginInstanceParent
*>(this), aObject
);
684 PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState
,
687 *aSuccess
= mNPNIface
->pushpopupsenabledstate(mNPP
, aState
? 1 : 0);
692 PluginInstanceParent::AnswerNPN_PopPopupsEnabledState(bool* aSuccess
)
694 *aSuccess
= mNPNIface
->poppopupsenabledstate(mNPP
);
700 /* windowless drawing helpers */
705 * windowless, offscreen:
707 * WM_WINDOWPOSCHANGED: origin is relative to container
708 * setwindow: origin is 0,0
709 * WM_PAINT: origin is 0,0
711 * windowless, native:
713 * WM_WINDOWPOSCHANGED: origin is relative to container
714 * setwindow: origin is relative to container
715 * WM_PAINT: origin is relative to container
717 * PluginInstanceParent:
719 * painting: mPluginPort (nsIntRect, saved in SetWindow)
723 PluginInstanceParent::SharedSurfaceRelease()
725 mSharedSurfaceDib
.Close();
729 PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow
* aWindow
,
730 NPRemoteWindow
& aRemoteWindow
)
732 aRemoteWindow
.window
= nsnull
;
735 aRemoteWindow
.width
= aWindow
->width
;
736 aRemoteWindow
.height
= aWindow
->height
;
737 aRemoteWindow
.type
= aWindow
->type
;
739 nsIntRect
newPort(aWindow
->x
, aWindow
->y
, aWindow
->width
, aWindow
->height
);
741 // save the the rect location within the browser window.
742 mPluginPort
= newPort
;
744 // move the port to our shared surface origin
747 // check to see if we have the room in shared surface
748 if (mSharedSurfaceDib
.IsValid() && mSharedSize
.Contains(newPort
)) {
750 aRemoteWindow
.surfaceHandle
= 0;
754 // allocate a new shared surface
755 SharedSurfaceRelease();
756 if (NS_FAILED(mSharedSurfaceDib
.Create(reinterpret_cast<HDC
>(aWindow
->window
),
757 newPort
.width
, newPort
.height
, 32)))
760 // save the new shared surface size we just allocated
761 mSharedSize
= newPort
;
763 base::SharedMemoryHandle handle
;
764 if (NS_FAILED(mSharedSurfaceDib
.ShareToProcess(mParent
->ChildProcessHandle(), &handle
)))
767 aRemoteWindow
.surfaceHandle
= handle
;
773 PluginInstanceParent::SharedSurfaceBeforePaint(RECT
& rect
,
774 NPRemoteEvent
& npremoteevent
)
776 RECT
* dr
= (RECT
*)npremoteevent
.event
.lParam
;
777 HDC parentHdc
= (HDC
)npremoteevent
.event
.wParam
;
779 nsIntRect
dirtyRect(dr
->left
, dr
->top
, dr
->right
-dr
->left
, dr
->bottom
-dr
->top
);
780 dirtyRect
.MoveBy(-mPluginPort
.x
, -mPluginPort
.y
); // should always be smaller than dirtyRect
782 ::BitBlt(mSharedSurfaceDib
.GetHDC(),
792 // setup the translated dirty rect we'll send to the child
793 rect
.left
= dirtyRect
.x
;
794 rect
.top
= dirtyRect
.y
;
795 rect
.right
= dirtyRect
.x
+ dirtyRect
.width
;
796 rect
.bottom
= dirtyRect
.y
+ dirtyRect
.height
;
798 npremoteevent
.event
.wParam
= WPARAM(0);
799 npremoteevent
.event
.lParam
= LPARAM(&rect
);
803 PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent
* npevent
)
805 RECT
* dr
= (RECT
*)npevent
->lParam
;
806 HDC parentHdc
= (HDC
)npevent
->wParam
;
808 nsIntRect
dirtyRect(dr
->left
, dr
->top
, dr
->right
-dr
->left
, dr
->bottom
-dr
->top
);
809 dirtyRect
.MoveBy(-mPluginPort
.x
, -mPluginPort
.y
);
811 // src copy the shared dib into the parent surface we are handed.
817 mSharedSurfaceDib
.GetHDC(),
823 #endif // defined(OS_WIN)