Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set 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 #ifdef MOZ_WIDGET_QT
8 #include <unistd.h> // for _exit()
9 #include <QtCore/QTimer>
10 #include "nsQAppInstance.h"
11 #include "NestedLoopTimer.h"
12 #endif
14 #include "mozilla/plugins/PluginModuleChild.h"
16 /* This must occur *after* plugins/PluginModuleChild.h to avoid typedefs conflicts. */
17 #include "mozilla/ArrayUtils.h"
19 #include "mozilla/ipc/MessageChannel.h"
21 #ifdef MOZ_WIDGET_GTK
22 #include <gtk/gtk.h>
23 #if (MOZ_WIDGET_GTK == 3)
24 #include <gtk/gtkx.h>
25 #endif
26 #endif
28 #include "nsIFile.h"
30 #include "pratom.h"
31 #include "nsDebug.h"
32 #include "nsCOMPtr.h"
33 #include "nsPluginsDir.h"
34 #include "nsXULAppAPI.h"
36 #ifdef MOZ_X11
37 # include "mozilla/X11Util.h"
38 #endif
39 #include "mozilla/plugins/PluginInstanceChild.h"
40 #include "mozilla/plugins/StreamNotifyChild.h"
41 #include "mozilla/plugins/BrowserStreamChild.h"
42 #include "mozilla/plugins/PluginStreamChild.h"
43 #include "PluginIdentifierChild.h"
44 #include "mozilla/dom/CrashReporterChild.h"
46 #include "nsNPAPIPlugin.h"
48 #ifdef XP_WIN
49 #include "COMMessageFilter.h"
50 #include "nsWindowsDllInterceptor.h"
51 #include "mozilla/widget/AudioSession.h"
52 #endif
54 #ifdef MOZ_WIDGET_COCOA
55 #include "PluginInterposeOSX.h"
56 #include "PluginUtilsOSX.h"
57 #endif
59 #include "GeckoProfiler.h"
61 using namespace mozilla;
62 using namespace mozilla::plugins;
63 using mozilla::dom::CrashReporterChild;
64 using mozilla::dom::PCrashReporterChild;
66 #if defined(XP_WIN)
67 const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
68 const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
69 #endif
71 namespace {
72 PluginModuleChild* gInstance = nullptr;
73 }
75 #ifdef MOZ_WIDGET_QT
76 typedef void (*_gtk_init_fn)(int argc, char **argv);
77 static _gtk_init_fn s_gtk_init = nullptr;
78 static PRLibrary *sGtkLib = nullptr;
79 #endif
81 #ifdef XP_WIN
82 // Used with fix for flash fullscreen window loosing focus.
83 static bool gDelayFlashFocusReplyUntilEval = false;
84 // Used to fix GetWindowInfo problems with internal flash settings dialogs
85 static WindowsDllInterceptor sUser32Intercept;
86 typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
87 static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
88 static HWND sBrowserHwnd = nullptr;
89 #endif
91 PluginModuleChild::PluginModuleChild()
92 : mLibrary(0)
93 , mPluginFilename("")
94 , mQuirks(QUIRKS_NOT_INITIALIZED)
95 , mShutdownFunc(0)
96 , mInitializeFunc(0)
97 #if defined(OS_WIN) || defined(OS_MACOSX)
98 , mGetEntryPointsFunc(0)
99 #elif defined(MOZ_WIDGET_GTK)
100 , mNestedLoopTimerId(0)
101 #elif defined(MOZ_WIDGET_QT)
102 , mNestedLoopTimerObject(0)
103 #endif
104 #ifdef OS_WIN
105 , mNestedEventHook(nullptr)
106 , mGlobalCallWndProcHook(nullptr)
107 #endif
108 {
109 NS_ASSERTION(!gInstance, "Something terribly wrong here!");
110 memset(&mFunctions, 0, sizeof(mFunctions));
111 memset(&mSavedData, 0, sizeof(mSavedData));
112 gInstance = this;
113 mUserAgent.SetIsVoid(true);
114 #ifdef XP_MACOSX
115 mac_plugin_interposing::child::SetUpCocoaInterposing();
116 #endif
117 }
119 PluginModuleChild::~PluginModuleChild()
120 {
121 NS_ASSERTION(gInstance == this, "Something terribly wrong here!");
123 // We don't unload the plugin library in case it uses atexit handlers or
124 // other similar hooks.
126 DeinitGraphics();
128 gInstance = nullptr;
129 }
131 // static
132 PluginModuleChild*
133 PluginModuleChild::current()
134 {
135 NS_ASSERTION(gInstance, "Null instance!");
136 return gInstance;
137 }
139 bool
140 PluginModuleChild::Init(const std::string& aPluginFilename,
141 base::ProcessHandle aParentProcessHandle,
142 MessageLoop* aIOLoop,
143 IPC::Channel* aChannel)
144 {
145 PLUGIN_LOG_DEBUG_METHOD;
147 GetIPCChannel()->SetAbortOnError(true);
149 // Request Windows message deferral behavior on our channel. This
150 // applies to the top level and all sub plugin protocols since they
151 // all share the same channel.
152 GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
154 #ifdef XP_WIN
155 COMMessageFilter::Initialize(this);
156 #endif
158 NS_ASSERTION(aChannel, "need a channel");
160 if (!InitGraphics())
161 return false;
163 mPluginFilename = aPluginFilename.c_str();
164 nsCOMPtr<nsIFile> localFile;
165 NS_NewLocalFile(NS_ConvertUTF8toUTF16(mPluginFilename),
166 true,
167 getter_AddRefs(localFile));
169 bool exists;
170 localFile->Exists(&exists);
171 NS_ASSERTION(exists, "plugin file ain't there");
173 nsPluginFile pluginFile(localFile);
175 #if defined(MOZ_X11) || defined(OS_MACOSX)
176 nsPluginInfo info = nsPluginInfo();
177 if (NS_FAILED(pluginFile.GetPluginInfo(info, &mLibrary))) {
178 return false;
179 }
181 #if defined(MOZ_X11)
182 NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
183 if (StringBeginsWith(nsDependentCString(info.fDescription), flash10Head)) {
184 AddQuirk(QUIRK_FLASH_EXPOSE_COORD_TRANSLATION);
185 }
186 #else // defined(OS_MACOSX)
187 mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
188 #endif
190 pluginFile.FreePluginInfo(info);
192 if (!mLibrary)
193 #endif
194 {
195 nsresult rv = pluginFile.LoadPlugin(&mLibrary);
196 if (NS_FAILED(rv))
197 return false;
198 }
199 NS_ASSERTION(mLibrary, "couldn't open shared object");
201 if (!Open(aChannel, aParentProcessHandle, aIOLoop))
202 return false;
204 memset((void*) &mFunctions, 0, sizeof(mFunctions));
205 mFunctions.size = sizeof(mFunctions);
206 mFunctions.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
208 // TODO: use PluginPRLibrary here
210 #if defined(OS_LINUX) || defined(OS_BSD)
211 mShutdownFunc =
212 (NP_PLUGINSHUTDOWN) PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
214 // create the new plugin handler
216 mInitializeFunc =
217 (NP_PLUGINUNIXINIT) PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
218 NS_ASSERTION(mInitializeFunc, "couldn't find NP_Initialize()");
220 #elif defined(OS_WIN) || defined(OS_MACOSX)
221 mShutdownFunc =
222 (NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
224 mGetEntryPointsFunc =
225 (NP_GETENTRYPOINTS)PR_FindSymbol(mLibrary, "NP_GetEntryPoints");
226 NS_ENSURE_TRUE(mGetEntryPointsFunc, false);
228 mInitializeFunc =
229 (NP_PLUGININIT)PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
230 NS_ENSURE_TRUE(mInitializeFunc, false);
231 #else
233 # error Please copy the initialization code from nsNPAPIPlugin.cpp
235 #endif
237 return true;
238 }
240 #if defined(MOZ_WIDGET_GTK)
241 typedef void (*GObjectDisposeFn)(GObject*);
242 typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
243 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
245 static GObjectDisposeFn real_gtk_plug_dispose;
246 static GtkPlugEmbeddedFn real_gtk_plug_embedded;
248 static void
249 undo_bogus_unref(gpointer data, GObject* object, gboolean is_last_ref) {
250 if (!is_last_ref) // recursion in g_object_ref
251 return;
253 g_object_ref(object);
254 }
256 static void
257 wrap_gtk_plug_dispose(GObject* object) {
258 // Work around Flash Player bug described in bug 538914.
259 //
260 // This function is called during gtk_widget_destroy and/or before
261 // the object's last reference is removed. A reference to the
262 // object is held during the call so the ref count should not drop
263 // to zero. However, Flash Player tries to destroy the GtkPlug
264 // using g_object_unref instead of gtk_widget_destroy. The
265 // reference that Flash is removing actually belongs to the
266 // GtkPlug. During real_gtk_plug_dispose, the GtkPlug removes its
267 // reference.
268 //
269 // A toggle ref is added to prevent premature deletion of the object
270 // caused by Flash Player's extra unref, and to detect when there are
271 // unexpectedly no other references.
272 g_object_add_toggle_ref(object, undo_bogus_unref, nullptr);
273 (*real_gtk_plug_dispose)(object);
274 g_object_remove_toggle_ref(object, undo_bogus_unref, nullptr);
275 }
277 static gboolean
278 gtk_plug_scroll_event(GtkWidget *widget, GdkEventScroll *gdk_event)
279 {
280 if (!gtk_widget_is_toplevel(widget)) // in same process as its GtkSocket
281 return FALSE; // event not handled; propagate to GtkSocket
283 GdkWindow* socket_window = gtk_plug_get_socket_window(GTK_PLUG(widget));
284 if (!socket_window)
285 return FALSE;
287 // Propagate the event to the embedder.
288 GdkScreen* screen = gdk_window_get_screen(socket_window);
289 GdkWindow* plug_window = gtk_widget_get_window(widget);
290 GdkWindow* event_window = gdk_event->window;
291 gint x = gdk_event->x;
292 gint y = gdk_event->y;
293 unsigned int button;
294 unsigned int button_mask = 0;
295 XEvent xevent;
296 Display* dpy = GDK_WINDOW_XDISPLAY(socket_window);
298 /* Translate the event coordinates to the plug window,
299 * which should be aligned with the socket window.
300 */
301 while (event_window != plug_window)
302 {
303 gint dx, dy;
305 gdk_window_get_position(event_window, &dx, &dy);
306 x += dx;
307 y += dy;
309 event_window = gdk_window_get_parent(event_window);
310 if (!event_window)
311 return FALSE;
312 }
314 switch (gdk_event->direction) {
315 case GDK_SCROLL_UP:
316 button = 4;
317 button_mask = Button4Mask;
318 break;
319 case GDK_SCROLL_DOWN:
320 button = 5;
321 button_mask = Button5Mask;
322 break;
323 case GDK_SCROLL_LEFT:
324 button = 6;
325 break;
326 case GDK_SCROLL_RIGHT:
327 button = 7;
328 break;
329 default:
330 return FALSE; // unknown GdkScrollDirection
331 }
333 memset(&xevent, 0, sizeof(xevent));
334 xevent.xbutton.type = ButtonPress;
335 xevent.xbutton.window = gdk_x11_window_get_xid(socket_window);
336 xevent.xbutton.root = gdk_x11_window_get_xid(gdk_screen_get_root_window(screen));
337 xevent.xbutton.subwindow = gdk_x11_window_get_xid(plug_window);
338 xevent.xbutton.time = gdk_event->time;
339 xevent.xbutton.x = x;
340 xevent.xbutton.y = y;
341 xevent.xbutton.x_root = gdk_event->x_root;
342 xevent.xbutton.y_root = gdk_event->y_root;
343 xevent.xbutton.state = gdk_event->state;
344 xevent.xbutton.button = button;
345 xevent.xbutton.same_screen = True;
347 gdk_error_trap_push();
349 XSendEvent(dpy, xevent.xbutton.window,
350 True, ButtonPressMask, &xevent);
352 xevent.xbutton.type = ButtonRelease;
353 xevent.xbutton.state |= button_mask;
354 XSendEvent(dpy, xevent.xbutton.window,
355 True, ButtonReleaseMask, &xevent);
357 gdk_display_sync(gdk_screen_get_display(screen));
358 gdk_error_trap_pop();
360 return TRUE; // event handled
361 }
363 static void
364 wrap_gtk_plug_embedded(GtkPlug* plug) {
365 GdkWindow* socket_window = gtk_plug_get_socket_window(plug);
366 if (socket_window) {
367 if (gtk_check_version(2,18,7) != nullptr // older
368 && g_object_get_data(G_OBJECT(socket_window),
369 "moz-existed-before-set-window")) {
370 // Add missing reference for
371 // https://bugzilla.gnome.org/show_bug.cgi?id=607061
372 g_object_ref(socket_window);
373 }
375 // Ensure the window exists to make this GtkPlug behave like an
376 // in-process GtkPlug for Flash Player. (Bugs 561308 and 539138).
377 gtk_widget_realize(GTK_WIDGET(plug));
378 }
380 if (*real_gtk_plug_embedded) {
381 (*real_gtk_plug_embedded)(plug);
382 }
383 }
385 //
386 // The next four constants are knobs that can be tuned. They trade
387 // off potential UI lag from delayed event processing with CPU time.
388 //
389 static const gint kNestedLoopDetectorPriority = G_PRIORITY_HIGH_IDLE;
390 // 90ms so that we can hopefully break livelocks before the user
391 // notices UI lag (100ms)
392 static const guint kNestedLoopDetectorIntervalMs = 90;
394 static const gint kBrowserEventPriority = G_PRIORITY_HIGH_IDLE;
395 static const guint kBrowserEventIntervalMs = 10;
397 // static
398 gboolean
399 PluginModuleChild::DetectNestedEventLoop(gpointer data)
400 {
401 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
403 NS_ABORT_IF_FALSE(0 != pmc->mNestedLoopTimerId,
404 "callback after descheduling");
405 NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
406 "not canceled before returning to main event loop!");
408 PLUGIN_LOG_DEBUG(("Detected nested glib event loop"));
410 // just detected a nested loop; start a timer that will
411 // periodically rpc-call back into the browser and process some
412 // events
413 pmc->mNestedLoopTimerId =
414 g_timeout_add_full(kBrowserEventPriority,
415 kBrowserEventIntervalMs,
416 PluginModuleChild::ProcessBrowserEvents,
417 data,
418 nullptr);
419 // cancel the nested-loop detection timer
420 return FALSE;
421 }
423 // static
424 gboolean
425 PluginModuleChild::ProcessBrowserEvents(gpointer data)
426 {
427 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
429 NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
430 "not canceled before returning to main event loop!");
432 pmc->CallProcessSomeEvents();
434 return TRUE;
435 }
437 void
438 PluginModuleChild::EnteredCxxStack()
439 {
440 NS_ABORT_IF_FALSE(0 == mNestedLoopTimerId,
441 "previous timer not descheduled");
443 mNestedLoopTimerId =
444 g_timeout_add_full(kNestedLoopDetectorPriority,
445 kNestedLoopDetectorIntervalMs,
446 PluginModuleChild::DetectNestedEventLoop,
447 this,
448 nullptr);
450 #ifdef DEBUG
451 mTopLoopDepth = g_main_depth();
452 #endif
453 }
455 void
456 PluginModuleChild::ExitedCxxStack()
457 {
458 NS_ABORT_IF_FALSE(0 < mNestedLoopTimerId,
459 "nested loop timeout not scheduled");
461 g_source_remove(mNestedLoopTimerId);
462 mNestedLoopTimerId = 0;
463 }
464 #elif defined (MOZ_WIDGET_QT)
466 void
467 PluginModuleChild::EnteredCxxStack()
468 {
469 NS_ABORT_IF_FALSE(mNestedLoopTimerObject == nullptr,
470 "previous timer not descheduled");
471 mNestedLoopTimerObject = new NestedLoopTimer(this);
472 QTimer::singleShot(kNestedLoopDetectorIntervalMs,
473 mNestedLoopTimerObject, SLOT(timeOut()));
474 }
476 void
477 PluginModuleChild::ExitedCxxStack()
478 {
479 NS_ABORT_IF_FALSE(mNestedLoopTimerObject != nullptr,
480 "nested loop timeout not scheduled");
481 delete mNestedLoopTimerObject;
482 mNestedLoopTimerObject = nullptr;
483 }
485 #endif
487 bool
488 PluginModuleChild::RecvSetParentHangTimeout(const uint32_t& aSeconds)
489 {
490 #ifdef XP_WIN
491 SetReplyTimeoutMs(((aSeconds > 0) ? (1000 * aSeconds) : 0));
492 #endif
493 return true;
494 }
496 bool
497 PluginModuleChild::ShouldContinueFromReplyTimeout()
498 {
499 #ifdef XP_WIN
500 NS_RUNTIMEABORT("terminating child process");
501 #endif
502 return true;
503 }
505 bool
506 PluginModuleChild::InitGraphics()
507 {
508 #if defined(MOZ_WIDGET_GTK)
509 // Work around plugins that don't interact well with GDK
510 // client-side windows.
511 PR_SetEnv("GDK_NATIVE_WINDOWS=1");
513 gtk_init(0, 0);
515 // GtkPlug is a static class so will leak anyway but this ref makes sure.
516 gpointer gtk_plug_class = g_type_class_ref(GTK_TYPE_PLUG);
518 // The dispose method is a good place to hook into the destruction process
519 // because the reference count should be 1 the last time dispose is
520 // called. (Toggle references wouldn't detect if the reference count
521 // might be higher.)
522 GObjectDisposeFn* dispose = &G_OBJECT_CLASS(gtk_plug_class)->dispose;
523 NS_ABORT_IF_FALSE(*dispose != wrap_gtk_plug_dispose,
524 "InitGraphics called twice");
525 real_gtk_plug_dispose = *dispose;
526 *dispose = wrap_gtk_plug_dispose;
528 // If we ever stop setting GDK_NATIVE_WINDOWS, we'll also need to
529 // gtk_widget_add_events GDK_SCROLL_MASK or GDK client-side windows will
530 // not tell us about the scroll events that it intercepts. With native
531 // windows, this is called when GDK intercepts the events; if GDK doesn't
532 // intercept the events, then the X server will instead send them directly
533 // to an ancestor (embedder) window.
534 GtkWidgetScrollEventFn* scroll_event =
535 >K_WIDGET_CLASS(gtk_plug_class)->scroll_event;
536 if (!*scroll_event) {
537 *scroll_event = gtk_plug_scroll_event;
538 }
540 GtkPlugEmbeddedFn* embedded = >K_PLUG_CLASS(gtk_plug_class)->embedded;
541 real_gtk_plug_embedded = *embedded;
542 *embedded = wrap_gtk_plug_embedded;
544 #elif defined(MOZ_WIDGET_QT)
545 nsQAppInstance::AddRef();
546 // Work around plugins that don't interact well without gtk initialized
547 // see bug 566845
548 #if defined(MOZ_X11)
549 if (!sGtkLib)
550 sGtkLib = PR_LoadLibrary("libgtk-x11-2.0.so.0");
551 #endif
552 if (sGtkLib) {
553 s_gtk_init = (_gtk_init_fn)PR_FindFunctionSymbol(sGtkLib, "gtk_init");
554 if (s_gtk_init)
555 s_gtk_init(0, 0);
556 }
557 #else
558 // may not be necessary on all platforms
559 #endif
560 #ifdef MOZ_X11
561 // Do this after initializing GDK, or GDK will install its own handler.
562 XRE_InstallX11ErrorHandler();
563 #endif
564 return true;
565 }
567 void
568 PluginModuleChild::DeinitGraphics()
569 {
570 #ifdef MOZ_WIDGET_QT
571 nsQAppInstance::Release();
572 if (sGtkLib) {
573 PR_UnloadLibrary(sGtkLib);
574 sGtkLib = nullptr;
575 s_gtk_init = nullptr;
576 }
577 #endif
579 #if defined(MOZ_X11) && defined(NS_FREE_PERMANENT_DATA)
580 // We free some data off of XDisplay close hooks, ensure they're
581 // run. Closing the display is pretty scary, so we only do it to
582 // silence leak checkers.
583 XCloseDisplay(DefaultXDisplay());
584 #endif
585 }
587 bool
588 PluginModuleChild::AnswerNP_Shutdown(NPError *rv)
589 {
590 AssertPluginThread();
592 #if defined XP_WIN
593 mozilla::widget::StopAudioSession();
594 #endif
596 // the PluginModuleParent shuts down this process after this interrupt
597 // call pops off its stack
599 *rv = mShutdownFunc ? mShutdownFunc() : NPERR_NO_ERROR;
601 // weakly guard against re-entry after NP_Shutdown
602 memset(&mFunctions, 0, sizeof(mFunctions));
604 #ifdef OS_WIN
605 ResetEventHooks();
606 #endif
608 GetIPCChannel()->SetAbortOnError(false);
610 return true;
611 }
613 bool
614 PluginModuleChild::AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
615 bool *aClearSiteData,
616 bool *aGetSitesWithData)
617 {
618 *aURLRedirectNotify = !!mFunctions.urlredirectnotify;
619 *aClearSiteData = !!mFunctions.clearsitedata;
620 *aGetSitesWithData = !!mFunctions.getsiteswithdata;
621 return true;
622 }
624 bool
625 PluginModuleChild::AnswerNPP_ClearSiteData(const nsCString& aSite,
626 const uint64_t& aFlags,
627 const uint64_t& aMaxAge,
628 NPError* aResult)
629 {
630 *aResult =
631 mFunctions.clearsitedata(NullableStringGet(aSite), aFlags, aMaxAge);
632 return true;
633 }
635 bool
636 PluginModuleChild::AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult)
637 {
638 char** result = mFunctions.getsiteswithdata();
639 if (!result)
640 return true;
642 char** iterator = result;
643 while (*iterator) {
644 aResult->AppendElement(*iterator);
645 NS_Free(*iterator);
646 ++iterator;
647 }
648 NS_Free(result);
650 return true;
651 }
653 bool
654 PluginModuleChild::RecvSetAudioSessionData(const nsID& aId,
655 const nsString& aDisplayName,
656 const nsString& aIconPath)
657 {
658 #if !defined XP_WIN
659 NS_RUNTIMEABORT("Not Reached!");
660 return false;
661 #else
662 nsresult rv = mozilla::widget::RecvAudioSessionData(aId, aDisplayName, aIconPath);
663 NS_ENSURE_SUCCESS(rv, true); // Bail early if this fails
665 // Ignore failures here; we can't really do anything about them
666 mozilla::widget::StartAudioSession();
667 return true;
668 #endif
669 }
671 void
672 PluginModuleChild::QuickExit()
673 {
674 NS_WARNING("plugin process _exit()ing");
675 _exit(0);
676 }
678 PCrashReporterChild*
679 PluginModuleChild::AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
680 uint32_t* processType)
681 {
682 return new CrashReporterChild();
683 }
685 bool
686 PluginModuleChild::DeallocPCrashReporterChild(PCrashReporterChild* actor)
687 {
688 delete actor;
689 return true;
690 }
692 bool
693 PluginModuleChild::AnswerPCrashReporterConstructor(
694 PCrashReporterChild* actor,
695 mozilla::dom::NativeThreadId* id,
696 uint32_t* processType)
697 {
698 #ifdef MOZ_CRASHREPORTER
699 *id = CrashReporter::CurrentThreadId();
700 *processType = XRE_GetProcessType();
701 #endif
702 return true;
703 }
705 void
706 PluginModuleChild::ActorDestroy(ActorDestroyReason why)
707 {
708 if (AbnormalShutdown == why) {
709 NS_WARNING("shutting down early because of crash!");
710 QuickExit();
711 }
713 // doesn't matter why we're being destroyed; it's up to us to
714 // initiate (clean) shutdown
715 XRE_ShutdownChildProcess();
716 }
718 void
719 PluginModuleChild::CleanUp()
720 {
721 }
723 const char*
724 PluginModuleChild::GetUserAgent()
725 {
726 if (mUserAgent.IsVoid() && !CallNPN_UserAgent(&mUserAgent))
727 return nullptr;
729 return NullableStringGet(mUserAgent);
730 }
732 bool
733 PluginModuleChild::RegisterActorForNPObject(NPObject* aObject,
734 PluginScriptableObjectChild* aActor)
735 {
736 AssertPluginThread();
737 NS_ASSERTION(aObject && aActor, "Null pointer!");
739 NPObjectData* d = mObjectMap.GetEntry(aObject);
740 if (!d) {
741 NS_ERROR("NPObject not in object table");
742 return false;
743 }
745 d->actor = aActor;
746 return true;
747 }
749 void
750 PluginModuleChild::UnregisterActorForNPObject(NPObject* aObject)
751 {
752 AssertPluginThread();
753 NS_ASSERTION(aObject, "Null pointer!");
755 NPObjectData* d = mObjectMap.GetEntry(aObject);
756 NS_ASSERTION(d, "NPObject not in object table");
757 if (d) {
758 d->actor = nullptr;
759 }
760 }
762 PluginScriptableObjectChild*
763 PluginModuleChild::GetActorForNPObject(NPObject* aObject)
764 {
765 AssertPluginThread();
766 NS_ASSERTION(aObject, "Null pointer!");
768 NPObjectData* d = mObjectMap.GetEntry(aObject);
769 if (!d) {
770 NS_ERROR("Plugin using object not created with NPN_CreateObject?");
771 return nullptr;
772 }
774 return d->actor;
775 }
777 #ifdef DEBUG
778 bool
779 PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
780 {
781 return !!mObjectMap.GetEntry(aObject);
782 }
783 #endif
785 //-----------------------------------------------------------------------------
786 // FIXME/cjones: just getting this out of the way for the moment ...
788 namespace mozilla {
789 namespace plugins {
790 namespace child {
792 static NPError
793 _requestread(NPStream *pstream, NPByteRange *rangeList);
795 static NPError
796 _geturlnotify(NPP aNPP, const char* relativeURL, const char* target,
797 void* notifyData);
799 static NPError
800 _getvalue(NPP aNPP, NPNVariable variable, void *r_value);
802 static NPError
803 _setvalue(NPP aNPP, NPPVariable variable, void *r_value);
805 static NPError
806 _geturl(NPP aNPP, const char* relativeURL, const char* target);
808 static NPError
809 _posturlnotify(NPP aNPP, const char* relativeURL, const char *target,
810 uint32_t len, const char *buf, NPBool file, void* notifyData);
812 static NPError
813 _posturl(NPP aNPP, const char* relativeURL, const char *target, uint32_t len,
814 const char *buf, NPBool file);
816 static NPError
817 _newstream(NPP aNPP, NPMIMEType type, const char* window, NPStream** pstream);
819 static int32_t
820 _write(NPP aNPP, NPStream *pstream, int32_t len, void *buffer);
822 static NPError
823 _destroystream(NPP aNPP, NPStream *pstream, NPError reason);
825 static void
826 _status(NPP aNPP, const char *message);
828 static void
829 _memfree (void *ptr);
831 static uint32_t
832 _memflush(uint32_t size);
834 static void
835 _reloadplugins(NPBool reloadPages);
837 static void
838 _invalidaterect(NPP aNPP, NPRect *invalidRect);
840 static void
841 _invalidateregion(NPP aNPP, NPRegion invalidRegion);
843 static void
844 _forceredraw(NPP aNPP);
846 static const char*
847 _useragent(NPP aNPP);
849 static void*
850 _memalloc (uint32_t size);
852 // Deprecated entry points for the old Java plugin.
853 static void* /* OJI type: JRIEnv* */
854 _getjavaenv(void);
856 // Deprecated entry points for the old Java plugin.
857 static void* /* OJI type: jref */
858 _getjavapeer(NPP aNPP);
860 static bool
861 _invoke(NPP aNPP, NPObject* npobj, NPIdentifier method, const NPVariant *args,
862 uint32_t argCount, NPVariant *result);
864 static bool
865 _invokedefault(NPP aNPP, NPObject* npobj, const NPVariant *args,
866 uint32_t argCount, NPVariant *result);
868 static bool
869 _evaluate(NPP aNPP, NPObject* npobj, NPString *script, NPVariant *result);
871 static bool
872 _getproperty(NPP aNPP, NPObject* npobj, NPIdentifier property,
873 NPVariant *result);
875 static bool
876 _setproperty(NPP aNPP, NPObject* npobj, NPIdentifier property,
877 const NPVariant *value);
879 static bool
880 _removeproperty(NPP aNPP, NPObject* npobj, NPIdentifier property);
882 static bool
883 _hasproperty(NPP aNPP, NPObject* npobj, NPIdentifier propertyName);
885 static bool
886 _hasmethod(NPP aNPP, NPObject* npobj, NPIdentifier methodName);
888 static bool
889 _enumerate(NPP aNPP, NPObject *npobj, NPIdentifier **identifier,
890 uint32_t *count);
892 static bool
893 _construct(NPP aNPP, NPObject* npobj, const NPVariant *args,
894 uint32_t argCount, NPVariant *result);
896 static void
897 _releasevariantvalue(NPVariant *variant);
899 static void
900 _setexception(NPObject* npobj, const NPUTF8 *message);
902 static void
903 _pushpopupsenabledstate(NPP aNPP, NPBool enabled);
905 static void
906 _poppopupsenabledstate(NPP aNPP);
908 static void
909 _pluginthreadasynccall(NPP instance, PluginThreadCallback func,
910 void *userData);
912 static NPError
913 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
914 char **value, uint32_t *len);
916 static NPError
917 _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
918 const char *value, uint32_t len);
920 static NPError
921 _getauthenticationinfo(NPP npp, const char *protocol,
922 const char *host, int32_t port,
923 const char *scheme, const char *realm,
924 char **username, uint32_t *ulen,
925 char **password, uint32_t *plen);
927 static uint32_t
928 _scheduletimer(NPP instance, uint32_t interval, NPBool repeat,
929 void (*timerFunc)(NPP npp, uint32_t timerID));
931 static void
932 _unscheduletimer(NPP instance, uint32_t timerID);
934 static NPError
935 _popupcontextmenu(NPP instance, NPMenu* menu);
937 static NPBool
938 _convertpoint(NPP instance,
939 double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
940 double *destX, double *destY, NPCoordinateSpace destSpace);
942 static void
943 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
945 static NPError
946 _initasyncsurface(NPP instance, NPSize *size,
947 NPImageFormat format, void *initData,
948 NPAsyncSurface *surface);
950 static NPError
951 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface);
953 static void
954 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed);
956 } /* namespace child */
957 } /* namespace plugins */
958 } /* namespace mozilla */
960 const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = {
961 sizeof(sBrowserFuncs),
962 (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
963 mozilla::plugins::child::_geturl,
964 mozilla::plugins::child::_posturl,
965 mozilla::plugins::child::_requestread,
966 mozilla::plugins::child::_newstream,
967 mozilla::plugins::child::_write,
968 mozilla::plugins::child::_destroystream,
969 mozilla::plugins::child::_status,
970 mozilla::plugins::child::_useragent,
971 mozilla::plugins::child::_memalloc,
972 mozilla::plugins::child::_memfree,
973 mozilla::plugins::child::_memflush,
974 mozilla::plugins::child::_reloadplugins,
975 mozilla::plugins::child::_getjavaenv,
976 mozilla::plugins::child::_getjavapeer,
977 mozilla::plugins::child::_geturlnotify,
978 mozilla::plugins::child::_posturlnotify,
979 mozilla::plugins::child::_getvalue,
980 mozilla::plugins::child::_setvalue,
981 mozilla::plugins::child::_invalidaterect,
982 mozilla::plugins::child::_invalidateregion,
983 mozilla::plugins::child::_forceredraw,
984 PluginModuleChild::NPN_GetStringIdentifier,
985 PluginModuleChild::NPN_GetStringIdentifiers,
986 PluginModuleChild::NPN_GetIntIdentifier,
987 PluginModuleChild::NPN_IdentifierIsString,
988 PluginModuleChild::NPN_UTF8FromIdentifier,
989 PluginModuleChild::NPN_IntFromIdentifier,
990 PluginModuleChild::NPN_CreateObject,
991 PluginModuleChild::NPN_RetainObject,
992 PluginModuleChild::NPN_ReleaseObject,
993 mozilla::plugins::child::_invoke,
994 mozilla::plugins::child::_invokedefault,
995 mozilla::plugins::child::_evaluate,
996 mozilla::plugins::child::_getproperty,
997 mozilla::plugins::child::_setproperty,
998 mozilla::plugins::child::_removeproperty,
999 mozilla::plugins::child::_hasproperty,
1000 mozilla::plugins::child::_hasmethod,
1001 mozilla::plugins::child::_releasevariantvalue,
1002 mozilla::plugins::child::_setexception,
1003 mozilla::plugins::child::_pushpopupsenabledstate,
1004 mozilla::plugins::child::_poppopupsenabledstate,
1005 mozilla::plugins::child::_enumerate,
1006 mozilla::plugins::child::_pluginthreadasynccall,
1007 mozilla::plugins::child::_construct,
1008 mozilla::plugins::child::_getvalueforurl,
1009 mozilla::plugins::child::_setvalueforurl,
1010 mozilla::plugins::child::_getauthenticationinfo,
1011 mozilla::plugins::child::_scheduletimer,
1012 mozilla::plugins::child::_unscheduletimer,
1013 mozilla::plugins::child::_popupcontextmenu,
1014 mozilla::plugins::child::_convertpoint,
1015 nullptr, // handleevent, unimplemented
1016 nullptr, // unfocusinstance, unimplemented
1017 mozilla::plugins::child::_urlredirectresponse,
1018 mozilla::plugins::child::_initasyncsurface,
1019 mozilla::plugins::child::_finalizeasyncsurface,
1020 mozilla::plugins::child::_setcurrentasyncsurface
1021 };
1023 PluginInstanceChild*
1024 InstCast(NPP aNPP)
1025 {
1026 NS_ABORT_IF_FALSE(!!(aNPP->ndata), "nil instance");
1027 return static_cast<PluginInstanceChild*>(aNPP->ndata);
1028 }
1030 namespace mozilla {
1031 namespace plugins {
1032 namespace child {
1034 NPError
1035 _requestread(NPStream* aStream,
1036 NPByteRange* aRangeList)
1037 {
1038 PLUGIN_LOG_DEBUG_FUNCTION;
1039 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1041 BrowserStreamChild* bs =
1042 static_cast<BrowserStreamChild*>(static_cast<AStream*>(aStream->ndata));
1043 bs->EnsureCorrectStream(aStream);
1044 return bs->NPN_RequestRead(aRangeList);
1045 }
1047 NPError
1048 _geturlnotify(NPP aNPP,
1049 const char* aRelativeURL,
1050 const char* aTarget,
1051 void* aNotifyData)
1052 {
1053 PLUGIN_LOG_DEBUG_FUNCTION;
1054 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1056 if (!aNPP) // nullptr check for nspluginwrapper (bug 561690)
1057 return NPERR_INVALID_INSTANCE_ERROR;
1059 nsCString url = NullableString(aRelativeURL);
1060 StreamNotifyChild* sn = new StreamNotifyChild(url);
1062 NPError err;
1063 InstCast(aNPP)->CallPStreamNotifyConstructor(
1064 sn, url, NullableString(aTarget), false, nsCString(), false, &err);
1066 if (NPERR_NO_ERROR == err) {
1067 // If NPN_PostURLNotify fails, the parent will immediately send us
1068 // a PStreamNotifyDestructor, which should not call NPP_URLNotify.
1069 sn->SetValid(aNotifyData);
1070 }
1072 return err;
1073 }
1075 NPError
1076 _getvalue(NPP aNPP,
1077 NPNVariable aVariable,
1078 void* aValue)
1079 {
1080 PLUGIN_LOG_DEBUG_FUNCTION;
1081 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1083 switch (aVariable) {
1084 // Copied from nsNPAPIPlugin.cpp
1085 case NPNVToolkit:
1086 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
1087 *static_cast<NPNToolkitType*>(aValue) = NPNVGtk2;
1088 return NPERR_NO_ERROR;
1089 #endif
1090 return NPERR_GENERIC_ERROR;
1092 case NPNVjavascriptEnabledBool: // Intentional fall-through
1093 case NPNVasdEnabledBool: // Intentional fall-through
1094 case NPNVisOfflineBool: // Intentional fall-through
1095 case NPNVSupportsXEmbedBool: // Intentional fall-through
1096 case NPNVSupportsWindowless: { // Intentional fall-through
1097 NPError result;
1098 bool value;
1099 PluginModuleChild::current()->
1100 CallNPN_GetValue_WithBoolReturn(aVariable, &result, &value);
1101 *(NPBool*)aValue = value ? true : false;
1102 return result;
1103 }
1104 #if (MOZ_WIDGET_GTK == 2)
1105 case NPNVxDisplay: {
1106 if (aNPP) {
1107 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
1108 }
1109 else {
1110 *(void **)aValue = xt_client_get_display();
1111 }
1112 return NPERR_NO_ERROR;
1113 }
1114 case NPNVxtAppContext:
1115 return NPERR_GENERIC_ERROR;
1116 #endif
1117 default: {
1118 if (aNPP) {
1119 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
1120 }
1122 NS_WARNING("Null NPP!");
1123 return NPERR_INVALID_INSTANCE_ERROR;
1124 }
1125 }
1127 NS_NOTREACHED("Shouldn't get here!");
1128 return NPERR_GENERIC_ERROR;
1129 }
1131 NPError
1132 _setvalue(NPP aNPP,
1133 NPPVariable aVariable,
1134 void* aValue)
1135 {
1136 PLUGIN_LOG_DEBUG_FUNCTION;
1137 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1138 return InstCast(aNPP)->NPN_SetValue(aVariable, aValue);
1139 }
1141 NPError
1142 _geturl(NPP aNPP,
1143 const char* aRelativeURL,
1144 const char* aTarget)
1145 {
1146 PLUGIN_LOG_DEBUG_FUNCTION;
1147 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1149 NPError err;
1150 InstCast(aNPP)->CallNPN_GetURL(NullableString(aRelativeURL),
1151 NullableString(aTarget), &err);
1152 return err;
1153 }
1155 NPError
1156 _posturlnotify(NPP aNPP,
1157 const char* aRelativeURL,
1158 const char* aTarget,
1159 uint32_t aLength,
1160 const char* aBuffer,
1161 NPBool aIsFile,
1162 void* aNotifyData)
1163 {
1164 PLUGIN_LOG_DEBUG_FUNCTION;
1165 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1167 if (!aBuffer)
1168 return NPERR_INVALID_PARAM;
1170 nsCString url = NullableString(aRelativeURL);
1171 StreamNotifyChild* sn = new StreamNotifyChild(url);
1173 NPError err;
1174 InstCast(aNPP)->CallPStreamNotifyConstructor(
1175 sn, url, NullableString(aTarget), true,
1176 nsCString(aBuffer, aLength), aIsFile, &err);
1178 if (NPERR_NO_ERROR == err) {
1179 // If NPN_PostURLNotify fails, the parent will immediately send us
1180 // a PStreamNotifyDestructor, which should not call NPP_URLNotify.
1181 sn->SetValid(aNotifyData);
1182 }
1184 return err;
1185 }
1187 NPError
1188 _posturl(NPP aNPP,
1189 const char* aRelativeURL,
1190 const char* aTarget,
1191 uint32_t aLength,
1192 const char* aBuffer,
1193 NPBool aIsFile)
1194 {
1195 PLUGIN_LOG_DEBUG_FUNCTION;
1196 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1198 NPError err;
1199 // FIXME what should happen when |aBuffer| is null?
1200 InstCast(aNPP)->CallNPN_PostURL(NullableString(aRelativeURL),
1201 NullableString(aTarget),
1202 nsDependentCString(aBuffer, aLength),
1203 aIsFile, &err);
1204 return err;
1205 }
1207 NPError
1208 _newstream(NPP aNPP,
1209 NPMIMEType aMIMEType,
1210 const char* aWindow,
1211 NPStream** aStream)
1212 {
1213 PLUGIN_LOG_DEBUG_FUNCTION;
1214 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1215 return InstCast(aNPP)->NPN_NewStream(aMIMEType, aWindow, aStream);
1216 }
1218 int32_t
1219 _write(NPP aNPP,
1220 NPStream* aStream,
1221 int32_t aLength,
1222 void* aBuffer)
1223 {
1224 PLUGIN_LOG_DEBUG_FUNCTION;
1225 ENSURE_PLUGIN_THREAD(0);
1227 PluginStreamChild* ps =
1228 static_cast<PluginStreamChild*>(static_cast<AStream*>(aStream->ndata));
1229 ps->EnsureCorrectInstance(InstCast(aNPP));
1230 ps->EnsureCorrectStream(aStream);
1231 return ps->NPN_Write(aLength, aBuffer);
1232 }
1234 NPError
1235 _destroystream(NPP aNPP,
1236 NPStream* aStream,
1237 NPError aReason)
1238 {
1239 PLUGIN_LOG_DEBUG_FUNCTION;
1240 ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
1242 PluginInstanceChild* p = InstCast(aNPP);
1243 AStream* s = static_cast<AStream*>(aStream->ndata);
1244 if (s->IsBrowserStream()) {
1245 BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
1246 bs->EnsureCorrectInstance(p);
1247 bs->NPN_DestroyStream(aReason);
1248 }
1249 else {
1250 PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);
1251 ps->EnsureCorrectInstance(p);
1252 PPluginStreamChild::Call__delete__(ps, aReason, false);
1253 }
1254 return NPERR_NO_ERROR;
1255 }
1257 void
1258 _status(NPP aNPP,
1259 const char* aMessage)
1260 {
1261 PLUGIN_LOG_DEBUG_FUNCTION;
1262 ENSURE_PLUGIN_THREAD_VOID();
1263 NS_WARNING("Not yet implemented!");
1264 }
1266 void
1267 _memfree(void* aPtr)
1268 {
1269 PLUGIN_LOG_DEBUG_FUNCTION;
1270 // Only assert plugin thread here for consistency with in-process plugins.
1271 AssertPluginThread();
1272 NS_Free(aPtr);
1273 }
1275 uint32_t
1276 _memflush(uint32_t aSize)
1277 {
1278 PLUGIN_LOG_DEBUG_FUNCTION;
1279 // Only assert plugin thread here for consistency with in-process plugins.
1280 AssertPluginThread();
1281 return 0;
1282 }
1284 void
1285 _reloadplugins(NPBool aReloadPages)
1286 {
1287 PLUGIN_LOG_DEBUG_FUNCTION;
1288 ENSURE_PLUGIN_THREAD_VOID();
1290 PluginModuleChild::current()->SendNPN_ReloadPlugins(!!aReloadPages);
1291 }
1293 void
1294 _invalidaterect(NPP aNPP,
1295 NPRect* aInvalidRect)
1296 {
1297 PLUGIN_LOG_DEBUG_FUNCTION;
1298 ENSURE_PLUGIN_THREAD_VOID();
1299 // nullptr check for nspluginwrapper (bug 548434)
1300 if (aNPP) {
1301 InstCast(aNPP)->InvalidateRect(aInvalidRect);
1302 }
1303 }
1305 void
1306 _invalidateregion(NPP aNPP,
1307 NPRegion aInvalidRegion)
1308 {
1309 PLUGIN_LOG_DEBUG_FUNCTION;
1310 ENSURE_PLUGIN_THREAD_VOID();
1311 NS_WARNING("Not yet implemented!");
1312 }
1314 void
1315 _forceredraw(NPP aNPP)
1316 {
1317 PLUGIN_LOG_DEBUG_FUNCTION;
1318 ENSURE_PLUGIN_THREAD_VOID();
1320 // We ignore calls to NPN_ForceRedraw. Such calls should
1321 // never be necessary.
1322 }
1324 const char*
1325 _useragent(NPP aNPP)
1326 {
1327 PLUGIN_LOG_DEBUG_FUNCTION;
1328 ENSURE_PLUGIN_THREAD(nullptr);
1329 return PluginModuleChild::current()->GetUserAgent();
1330 }
1332 void*
1333 _memalloc(uint32_t aSize)
1334 {
1335 PLUGIN_LOG_DEBUG_FUNCTION;
1336 // Only assert plugin thread here for consistency with in-process plugins.
1337 AssertPluginThread();
1338 return NS_Alloc(aSize);
1339 }
1341 // Deprecated entry points for the old Java plugin.
1342 void* /* OJI type: JRIEnv* */
1343 _getjavaenv(void)
1344 {
1345 PLUGIN_LOG_DEBUG_FUNCTION;
1346 return 0;
1347 }
1349 void* /* OJI type: jref */
1350 _getjavapeer(NPP aNPP)
1351 {
1352 PLUGIN_LOG_DEBUG_FUNCTION;
1353 return 0;
1354 }
1356 bool
1357 _invoke(NPP aNPP,
1358 NPObject* aNPObj,
1359 NPIdentifier aMethod,
1360 const NPVariant* aArgs,
1361 uint32_t aArgCount,
1362 NPVariant* aResult)
1363 {
1364 PLUGIN_LOG_DEBUG_FUNCTION;
1365 ENSURE_PLUGIN_THREAD(false);
1367 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invoke)
1368 return false;
1370 return aNPObj->_class->invoke(aNPObj, aMethod, aArgs, aArgCount, aResult);
1371 }
1373 bool
1374 _invokedefault(NPP aNPP,
1375 NPObject* aNPObj,
1376 const NPVariant* aArgs,
1377 uint32_t aArgCount,
1378 NPVariant* aResult)
1379 {
1380 PLUGIN_LOG_DEBUG_FUNCTION;
1381 ENSURE_PLUGIN_THREAD(false);
1383 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invokeDefault)
1384 return false;
1386 return aNPObj->_class->invokeDefault(aNPObj, aArgs, aArgCount, aResult);
1387 }
1389 bool
1390 _evaluate(NPP aNPP,
1391 NPObject* aObject,
1392 NPString* aScript,
1393 NPVariant* aResult)
1394 {
1395 PLUGIN_LOG_DEBUG_FUNCTION;
1396 ENSURE_PLUGIN_THREAD(false);
1398 if (!(aNPP && aObject && aScript && aResult)) {
1399 NS_ERROR("Bad arguments!");
1400 return false;
1401 }
1403 PluginScriptableObjectChild* actor =
1404 InstCast(aNPP)->GetActorForNPObject(aObject);
1405 if (!actor) {
1406 NS_ERROR("Failed to create actor?!");
1407 return false;
1408 }
1410 #ifdef XP_WIN
1411 if (gDelayFlashFocusReplyUntilEval) {
1412 ReplyMessage(0);
1413 gDelayFlashFocusReplyUntilEval = false;
1414 }
1415 #endif
1417 return actor->Evaluate(aScript, aResult);
1418 }
1420 bool
1421 _getproperty(NPP aNPP,
1422 NPObject* aNPObj,
1423 NPIdentifier aPropertyName,
1424 NPVariant* aResult)
1425 {
1426 PLUGIN_LOG_DEBUG_FUNCTION;
1427 ENSURE_PLUGIN_THREAD(false);
1429 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->getProperty)
1430 return false;
1432 return aNPObj->_class->getProperty(aNPObj, aPropertyName, aResult);
1433 }
1435 bool
1436 _setproperty(NPP aNPP,
1437 NPObject* aNPObj,
1438 NPIdentifier aPropertyName,
1439 const NPVariant* aValue)
1440 {
1441 PLUGIN_LOG_DEBUG_FUNCTION;
1442 ENSURE_PLUGIN_THREAD(false);
1444 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->setProperty)
1445 return false;
1447 return aNPObj->_class->setProperty(aNPObj, aPropertyName, aValue);
1448 }
1450 bool
1451 _removeproperty(NPP aNPP,
1452 NPObject* aNPObj,
1453 NPIdentifier aPropertyName)
1454 {
1455 PLUGIN_LOG_DEBUG_FUNCTION;
1456 ENSURE_PLUGIN_THREAD(false);
1458 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->removeProperty)
1459 return false;
1461 return aNPObj->_class->removeProperty(aNPObj, aPropertyName);
1462 }
1464 bool
1465 _hasproperty(NPP aNPP,
1466 NPObject* aNPObj,
1467 NPIdentifier aPropertyName)
1468 {
1469 PLUGIN_LOG_DEBUG_FUNCTION;
1470 ENSURE_PLUGIN_THREAD(false);
1472 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasProperty)
1473 return false;
1475 return aNPObj->_class->hasProperty(aNPObj, aPropertyName);
1476 }
1478 bool
1479 _hasmethod(NPP aNPP,
1480 NPObject* aNPObj,
1481 NPIdentifier aMethodName)
1482 {
1483 PLUGIN_LOG_DEBUG_FUNCTION;
1484 ENSURE_PLUGIN_THREAD(false);
1486 if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasMethod)
1487 return false;
1489 return aNPObj->_class->hasMethod(aNPObj, aMethodName);
1490 }
1492 bool
1493 _enumerate(NPP aNPP,
1494 NPObject* aNPObj,
1495 NPIdentifier** aIdentifiers,
1496 uint32_t* aCount)
1497 {
1498 PLUGIN_LOG_DEBUG_FUNCTION;
1499 ENSURE_PLUGIN_THREAD(false);
1501 if (!aNPP || !aNPObj || !aNPObj->_class)
1502 return false;
1504 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(aNPObj->_class) ||
1505 !aNPObj->_class->enumerate) {
1506 *aIdentifiers = 0;
1507 *aCount = 0;
1508 return true;
1509 }
1511 return aNPObj->_class->enumerate(aNPObj, aIdentifiers, aCount);
1512 }
1514 bool
1515 _construct(NPP aNPP,
1516 NPObject* aNPObj,
1517 const NPVariant* aArgs,
1518 uint32_t aArgCount,
1519 NPVariant* aResult)
1520 {
1521 PLUGIN_LOG_DEBUG_FUNCTION;
1522 ENSURE_PLUGIN_THREAD(false);
1524 if (!aNPP || !aNPObj || !aNPObj->_class ||
1525 !NP_CLASS_STRUCT_VERSION_HAS_CTOR(aNPObj->_class) ||
1526 !aNPObj->_class->construct) {
1527 return false;
1528 }
1530 return aNPObj->_class->construct(aNPObj, aArgs, aArgCount, aResult);
1531 }
1533 void
1534 _releasevariantvalue(NPVariant* aVariant)
1535 {
1536 PLUGIN_LOG_DEBUG_FUNCTION;
1537 // Only assert plugin thread here for consistency with in-process plugins.
1538 AssertPluginThread();
1540 if (NPVARIANT_IS_STRING(*aVariant)) {
1541 NPString str = NPVARIANT_TO_STRING(*aVariant);
1542 free(const_cast<NPUTF8*>(str.UTF8Characters));
1543 }
1544 else if (NPVARIANT_IS_OBJECT(*aVariant)) {
1545 NPObject* object = NPVARIANT_TO_OBJECT(*aVariant);
1546 if (object) {
1547 PluginModuleChild::NPN_ReleaseObject(object);
1548 }
1549 }
1550 VOID_TO_NPVARIANT(*aVariant);
1551 }
1553 void
1554 _setexception(NPObject* aNPObj,
1555 const NPUTF8* aMessage)
1556 {
1557 PLUGIN_LOG_DEBUG_FUNCTION;
1558 ENSURE_PLUGIN_THREAD_VOID();
1560 PluginModuleChild* self = PluginModuleChild::current();
1561 PluginScriptableObjectChild* actor = nullptr;
1562 if (aNPObj) {
1563 actor = self->GetActorForNPObject(aNPObj);
1564 if (!actor) {
1565 NS_ERROR("Failed to get actor!");
1566 return;
1567 }
1568 }
1570 self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
1571 NullableString(aMessage));
1572 }
1574 void
1575 _pushpopupsenabledstate(NPP aNPP,
1576 NPBool aEnabled)
1577 {
1578 PLUGIN_LOG_DEBUG_FUNCTION;
1579 ENSURE_PLUGIN_THREAD_VOID();
1581 InstCast(aNPP)->CallNPN_PushPopupsEnabledState(aEnabled ? true : false);
1582 }
1584 void
1585 _poppopupsenabledstate(NPP aNPP)
1586 {
1587 PLUGIN_LOG_DEBUG_FUNCTION;
1588 ENSURE_PLUGIN_THREAD_VOID();
1590 InstCast(aNPP)->CallNPN_PopPopupsEnabledState();
1591 }
1593 void
1594 _pluginthreadasynccall(NPP aNPP,
1595 PluginThreadCallback aFunc,
1596 void* aUserData)
1597 {
1598 PLUGIN_LOG_DEBUG_FUNCTION;
1599 if (!aFunc)
1600 return;
1602 InstCast(aNPP)->AsyncCall(aFunc, aUserData);
1603 }
1605 NPError
1606 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
1607 char **value, uint32_t *len)
1608 {
1609 PLUGIN_LOG_DEBUG_FUNCTION;
1610 AssertPluginThread();
1612 if (!url)
1613 return NPERR_INVALID_URL;
1615 if (!npp || !value || !len)
1616 return NPERR_INVALID_PARAM;
1618 switch (variable) {
1619 case NPNURLVCookie:
1620 case NPNURLVProxy:
1621 nsCString v;
1622 NPError result;
1623 InstCast(npp)->
1624 CallNPN_GetValueForURL(variable, nsCString(url), &v, &result);
1625 if (NPERR_NO_ERROR == result) {
1626 *value = ToNewCString(v);
1627 *len = v.Length();
1628 }
1629 return result;
1630 }
1632 return NPERR_INVALID_PARAM;
1633 }
1635 NPError
1636 _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
1637 const char *value, uint32_t len)
1638 {
1639 PLUGIN_LOG_DEBUG_FUNCTION;
1640 AssertPluginThread();
1642 if (!value)
1643 return NPERR_INVALID_PARAM;
1645 if (!url)
1646 return NPERR_INVALID_URL;
1648 switch (variable) {
1649 case NPNURLVCookie:
1650 case NPNURLVProxy:
1651 NPError result;
1652 InstCast(npp)->CallNPN_SetValueForURL(variable, nsCString(url),
1653 nsDependentCString(value, len),
1654 &result);
1655 return result;
1656 }
1658 return NPERR_INVALID_PARAM;
1659 }
1661 NPError
1662 _getauthenticationinfo(NPP npp, const char *protocol,
1663 const char *host, int32_t port,
1664 const char *scheme, const char *realm,
1665 char **username, uint32_t *ulen,
1666 char **password, uint32_t *plen)
1667 {
1668 PLUGIN_LOG_DEBUG_FUNCTION;
1669 AssertPluginThread();
1671 if (!protocol || !host || !scheme || !realm || !username || !ulen ||
1672 !password || !plen)
1673 return NPERR_INVALID_PARAM;
1675 nsCString u;
1676 nsCString p;
1677 NPError result;
1678 InstCast(npp)->
1679 CallNPN_GetAuthenticationInfo(nsDependentCString(protocol),
1680 nsDependentCString(host),
1681 port,
1682 nsDependentCString(scheme),
1683 nsDependentCString(realm),
1684 &u, &p, &result);
1685 if (NPERR_NO_ERROR == result) {
1686 *username = ToNewCString(u);
1687 *ulen = u.Length();
1688 *password = ToNewCString(p);
1689 *plen = p.Length();
1690 }
1691 return result;
1692 }
1694 uint32_t
1695 _scheduletimer(NPP npp, uint32_t interval, NPBool repeat,
1696 void (*timerFunc)(NPP npp, uint32_t timerID))
1697 {
1698 PLUGIN_LOG_DEBUG_FUNCTION;
1699 AssertPluginThread();
1700 return InstCast(npp)->ScheduleTimer(interval, repeat, timerFunc);
1701 }
1703 void
1704 _unscheduletimer(NPP npp, uint32_t timerID)
1705 {
1706 PLUGIN_LOG_DEBUG_FUNCTION;
1707 AssertPluginThread();
1708 InstCast(npp)->UnscheduleTimer(timerID);
1709 }
1712 #ifdef OS_MACOSX
1713 static void ProcessBrowserEvents(void* pluginModule) {
1714 PluginModuleChild* pmc = static_cast<PluginModuleChild*>(pluginModule);
1716 if (!pmc)
1717 return;
1719 pmc->CallProcessSomeEvents();
1720 }
1721 #endif
1723 NPError
1724 _popupcontextmenu(NPP instance, NPMenu* menu)
1725 {
1726 PLUGIN_LOG_DEBUG_FUNCTION;
1727 AssertPluginThread();
1729 #ifdef MOZ_WIDGET_COCOA
1730 double pluginX, pluginY;
1731 double screenX, screenY;
1733 const NPCocoaEvent* currentEvent = InstCast(instance)->getCurrentEvent();
1734 if (!currentEvent) {
1735 return NPERR_GENERIC_ERROR;
1736 }
1738 // Ensure that the events has an x/y value.
1739 if (currentEvent->type != NPCocoaEventMouseDown &&
1740 currentEvent->type != NPCocoaEventMouseUp &&
1741 currentEvent->type != NPCocoaEventMouseMoved &&
1742 currentEvent->type != NPCocoaEventMouseEntered &&
1743 currentEvent->type != NPCocoaEventMouseExited &&
1744 currentEvent->type != NPCocoaEventMouseDragged) {
1745 return NPERR_GENERIC_ERROR;
1746 }
1748 pluginX = currentEvent->data.mouse.pluginX;
1749 pluginY = currentEvent->data.mouse.pluginY;
1751 if ((pluginX < 0.0) || (pluginY < 0.0))
1752 return NPERR_GENERIC_ERROR;
1754 NPBool success = _convertpoint(instance,
1755 pluginX, pluginY, NPCoordinateSpacePlugin,
1756 &screenX, &screenY, NPCoordinateSpaceScreen);
1758 if (success) {
1759 return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
1760 screenX, screenY,
1761 PluginModuleChild::current(),
1762 ProcessBrowserEvents);
1763 } else {
1764 NS_WARNING("Convertpoint failed, could not created contextmenu.");
1765 return NPERR_GENERIC_ERROR;
1766 }
1768 #else
1769 NS_WARNING("Not supported on this platform!");
1770 return NPERR_GENERIC_ERROR;
1771 #endif
1772 }
1774 NPBool
1775 _convertpoint(NPP instance,
1776 double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
1777 double *destX, double *destY, NPCoordinateSpace destSpace)
1778 {
1779 PLUGIN_LOG_DEBUG_FUNCTION;
1780 if (!IsPluginThread()) {
1781 NS_WARNING("Not running on the plugin's main thread!");
1782 return false;
1783 }
1785 double rDestX = 0;
1786 bool ignoreDestX = !destX;
1787 double rDestY = 0;
1788 bool ignoreDestY = !destY;
1789 bool result = false;
1790 InstCast(instance)->CallNPN_ConvertPoint(sourceX, ignoreDestX, sourceY, ignoreDestY, sourceSpace, destSpace,
1791 &rDestX, &rDestY, &result);
1792 if (result) {
1793 if (destX)
1794 *destX = rDestX;
1795 if (destY)
1796 *destY = rDestY;
1797 }
1799 return result;
1800 }
1802 void
1803 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
1804 {
1805 InstCast(instance)->NPN_URLRedirectResponse(notifyData, allow);
1806 }
1808 NPError
1809 _initasyncsurface(NPP instance, NPSize *size,
1810 NPImageFormat format, void *initData,
1811 NPAsyncSurface *surface)
1812 {
1813 return InstCast(instance)->NPN_InitAsyncSurface(size, format, initData, surface);
1814 }
1816 NPError
1817 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
1818 {
1819 return InstCast(instance)->NPN_FinalizeAsyncSurface(surface);
1820 }
1822 void
1823 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
1824 {
1825 InstCast(instance)->NPN_SetCurrentAsyncSurface(surface, changed);
1826 }
1828 } /* namespace child */
1829 } /* namespace plugins */
1830 } /* namespace mozilla */
1832 //-----------------------------------------------------------------------------
1834 bool
1835 PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
1836 {
1837 PLUGIN_LOG_DEBUG_METHOD;
1838 AssertPluginThread();
1840 #if defined(OS_LINUX) || defined(OS_BSD)
1841 return true;
1842 #elif defined(OS_WIN) || defined(OS_MACOSX)
1843 *_retval = mGetEntryPointsFunc(&mFunctions);
1844 return true;
1845 #else
1846 # error Please implement me for your platform
1847 #endif
1848 }
1850 bool
1851 PluginModuleChild::AnswerNP_Initialize(const uint32_t& aFlags, NPError* _retval)
1852 {
1853 PLUGIN_LOG_DEBUG_METHOD;
1854 AssertPluginThread();
1856 mAsyncDrawingAllowed = aFlags & kAllowAsyncDrawing;
1858 #ifdef OS_WIN
1859 SetEventHooks();
1860 #endif
1862 #ifdef MOZ_X11
1863 // Send the parent our X socket to act as a proxy reference for our X
1864 // resources.
1865 int xSocketFd = ConnectionNumber(DefaultXDisplay());
1866 SendBackUpXResources(FileDescriptor(xSocketFd));
1867 #endif
1869 #if defined(OS_LINUX) || defined(OS_BSD)
1870 *_retval = mInitializeFunc(&sBrowserFuncs, &mFunctions);
1871 return true;
1872 #elif defined(OS_WIN) || defined(OS_MACOSX)
1873 *_retval = mInitializeFunc(&sBrowserFuncs);
1874 return true;
1875 #else
1876 # error Please implement me for your platform
1877 #endif
1878 }
1880 PPluginIdentifierChild*
1881 PluginModuleChild::AllocPPluginIdentifierChild(const nsCString& aString,
1882 const int32_t& aInt,
1883 const bool& aTemporary)
1884 {
1885 // We cannot call SetPermanent within this function because Manager() isn't
1886 // set up yet.
1887 if (aString.IsVoid()) {
1888 return new PluginIdentifierChildInt(aInt);
1889 }
1890 return new PluginIdentifierChildString(aString);
1891 }
1893 bool
1894 PluginModuleChild::RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
1895 const nsCString& aString,
1896 const int32_t& aInt,
1897 const bool& aTemporary)
1898 {
1899 if (!aTemporary) {
1900 static_cast<PluginIdentifierChild*>(actor)->MakePermanent();
1901 }
1902 return true;
1903 }
1905 bool
1906 PluginModuleChild::DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor)
1907 {
1908 delete aActor;
1909 return true;
1910 }
1912 #if defined(XP_WIN)
1913 BOOL WINAPI
1914 PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
1915 {
1916 if (!pwi)
1917 return FALSE;
1919 if (!sGetWindowInfoPtrStub) {
1920 NS_ASSERTION(FALSE, "Something is horribly wrong in PMCGetWindowInfoHook!");
1921 return FALSE;
1922 }
1924 if (!sBrowserHwnd) {
1925 wchar_t szClass[20];
1926 if (GetClassNameW(hWnd, szClass, ArrayLength(szClass)) &&
1927 !wcscmp(szClass, kMozillaWindowClass)) {
1928 sBrowserHwnd = hWnd;
1929 }
1930 }
1931 // Oddity: flash does strange rect comparisons for mouse input destined for
1932 // it's internal settings window. Post removing sub widgets for tabs, touch
1933 // this up so they get the rect they expect.
1934 // XXX potentially tie this to a specific major version?
1935 BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
1936 if (sBrowserHwnd && sBrowserHwnd == hWnd)
1937 pwi->rcWindow = pwi->rcClient;
1938 return result;
1939 }
1940 #endif
1942 PPluginInstanceChild*
1943 PluginModuleChild::AllocPPluginInstanceChild(const nsCString& aMimeType,
1944 const uint16_t& aMode,
1945 const InfallibleTArray<nsCString>& aNames,
1946 const InfallibleTArray<nsCString>& aValues,
1947 NPError* rv)
1948 {
1949 PLUGIN_LOG_DEBUG_METHOD;
1950 AssertPluginThread();
1952 InitQuirksModes(aMimeType);
1954 #ifdef XP_WIN
1955 if ((mQuirks & QUIRK_FLASH_HOOK_GETWINDOWINFO) &&
1956 !sGetWindowInfoPtrStub) {
1957 sUser32Intercept.Init("user32.dll");
1958 sUser32Intercept.AddHook("GetWindowInfo", reinterpret_cast<intptr_t>(PMCGetWindowInfoHook),
1959 (void**) &sGetWindowInfoPtrStub);
1960 }
1961 #endif
1963 return new PluginInstanceChild(&mFunctions);
1964 }
1966 void
1967 PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
1968 {
1969 if (mQuirks != QUIRKS_NOT_INITIALIZED)
1970 return;
1971 mQuirks = 0;
1972 // application/x-silverlight
1973 // application/x-silverlight-2
1974 NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
1975 if (FindInReadable(silverlight, aMimeType)) {
1976 mQuirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT;
1977 #ifdef OS_WIN
1978 mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
1979 mQuirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT;
1980 #endif
1981 }
1983 #ifdef OS_WIN
1984 // application/x-shockwave-flash
1985 NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
1986 if (FindInReadable(flash, aMimeType)) {
1987 mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
1988 mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
1989 mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
1990 mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
1991 mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
1992 }
1994 // QuickTime plugin usually loaded with audio/mpeg mimetype
1995 NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin");
1996 if (FindInReadable(quicktime, mPluginFilename)) {
1997 mQuirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
1998 }
1999 #endif
2001 #ifdef XP_MACOSX
2002 // Whitelist Flash and Quicktime to support offline renderer
2003 NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
2004 NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin");
2005 if (FindInReadable(flash, aMimeType)) {
2006 mQuirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES;
2007 }
2008 if (FindInReadable(flash, aMimeType) ||
2009 FindInReadable(quicktime, mPluginFilename)) {
2010 mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
2011 }
2012 #endif
2013 }
2015 bool
2016 PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
2017 const nsCString& aMimeType,
2018 const uint16_t& aMode,
2019 const InfallibleTArray<nsCString>& aNames,
2020 const InfallibleTArray<nsCString>& aValues,
2021 NPError* rv)
2022 {
2023 PLUGIN_LOG_DEBUG_METHOD;
2024 AssertPluginThread();
2026 PluginInstanceChild* childInstance =
2027 reinterpret_cast<PluginInstanceChild*>(aActor);
2028 NS_ASSERTION(childInstance, "Null actor!");
2030 // unpack the arguments into a C format
2031 int argc = aNames.Length();
2032 NS_ASSERTION(argc == (int) aValues.Length(),
2033 "argn.length != argv.length");
2035 nsAutoArrayPtr<char*> argn(new char*[1 + argc]);
2036 nsAutoArrayPtr<char*> argv(new char*[1 + argc]);
2037 argn[argc] = 0;
2038 argv[argc] = 0;
2040 for (int i = 0; i < argc; ++i) {
2041 argn[i] = const_cast<char*>(NullableStringGet(aNames[i]));
2042 argv[i] = const_cast<char*>(NullableStringGet(aValues[i]));
2043 }
2045 NPP npp = childInstance->GetNPP();
2047 // FIXME/cjones: use SAFE_CALL stuff
2048 *rv = mFunctions.newp((char*)NullableStringGet(aMimeType),
2049 npp,
2050 aMode,
2051 argc,
2052 argn,
2053 argv,
2054 0);
2055 if (NPERR_NO_ERROR != *rv) {
2056 return true;
2057 }
2059 childInstance->Initialize();
2061 #if defined(XP_MACOSX) && defined(__i386__)
2062 // If an i386 Mac OS X plugin has selected the Carbon event model then
2063 // we have to fail. We do not support putting Carbon event model plugins
2064 // out of process. Note that Carbon is the default model so out of process
2065 // plugins need to actively negotiate something else in order to work
2066 // out of process.
2067 if (childInstance->EventModel() == NPEventModelCarbon) {
2068 // Send notification that a plugin tried to negotiate Carbon NPAPI so that
2069 // users can be notified that restarting the browser in i386 mode may allow
2070 // them to use the plugin.
2071 childInstance->SendNegotiatedCarbon();
2073 // Fail to instantiate.
2074 *rv = NPERR_MODULE_LOAD_FAILED_ERROR;
2075 }
2076 #endif
2078 return true;
2079 }
2081 bool
2082 PluginModuleChild::DeallocPPluginInstanceChild(PPluginInstanceChild* aActor)
2083 {
2084 PLUGIN_LOG_DEBUG_METHOD;
2085 AssertPluginThread();
2087 delete aActor;
2089 return true;
2090 }
2092 NPObject*
2093 PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
2094 {
2095 PLUGIN_LOG_DEBUG_FUNCTION;
2096 ENSURE_PLUGIN_THREAD(nullptr);
2098 PluginInstanceChild* i = InstCast(aNPP);
2099 if (i->mDeletingHash) {
2100 NS_ERROR("Plugin used NPP after NPP_Destroy");
2101 return nullptr;
2102 }
2104 NPObject* newObject;
2105 if (aClass && aClass->allocate) {
2106 newObject = aClass->allocate(aNPP, aClass);
2107 }
2108 else {
2109 newObject = reinterpret_cast<NPObject*>(child::_memalloc(sizeof(NPObject)));
2110 }
2112 if (newObject) {
2113 newObject->_class = aClass;
2114 newObject->referenceCount = 1;
2115 NS_LOG_ADDREF(newObject, 1, "NPObject", sizeof(NPObject));
2116 }
2118 NPObjectData* d = static_cast<PluginModuleChild*>(i->Manager())
2119 ->mObjectMap.PutEntry(newObject);
2120 NS_ASSERTION(!d->instance, "New NPObject already mapped?");
2121 d->instance = i;
2123 return newObject;
2124 }
2126 NPObject*
2127 PluginModuleChild::NPN_RetainObject(NPObject* aNPObj)
2128 {
2129 AssertPluginThread();
2131 #ifdef NS_BUILD_REFCNT_LOGGING
2132 int32_t refCnt =
2133 #endif
2134 PR_ATOMIC_INCREMENT((int32_t*)&aNPObj->referenceCount);
2135 NS_LOG_ADDREF(aNPObj, refCnt, "NPObject", sizeof(NPObject));
2137 return aNPObj;
2138 }
2140 void
2141 PluginModuleChild::NPN_ReleaseObject(NPObject* aNPObj)
2142 {
2143 AssertPluginThread();
2145 NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
2146 if (!d) {
2147 NS_ERROR("Releasing object not in mObjectMap?");
2148 return;
2149 }
2151 DeletingObjectEntry* doe = nullptr;
2152 if (d->instance->mDeletingHash) {
2153 doe = d->instance->mDeletingHash->GetEntry(aNPObj);
2154 if (!doe) {
2155 NS_ERROR("An object for a destroyed instance isn't in the instance deletion hash");
2156 return;
2157 }
2158 if (doe->mDeleted)
2159 return;
2160 }
2162 int32_t refCnt = PR_ATOMIC_DECREMENT((int32_t*)&aNPObj->referenceCount);
2163 NS_LOG_RELEASE(aNPObj, refCnt, "NPObject");
2165 if (refCnt == 0) {
2166 DeallocNPObject(aNPObj);
2167 if (doe)
2168 doe->mDeleted = true;
2169 }
2170 return;
2171 }
2173 void
2174 PluginModuleChild::DeallocNPObject(NPObject* aNPObj)
2175 {
2176 if (aNPObj->_class && aNPObj->_class->deallocate) {
2177 aNPObj->_class->deallocate(aNPObj);
2178 } else {
2179 child::_memfree(aNPObj);
2180 }
2182 NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
2183 if (d->actor)
2184 d->actor->NPObjectDestroyed();
2186 current()->mObjectMap.RemoveEntry(aNPObj);
2187 }
2189 void
2190 PluginModuleChild::FindNPObjectsForInstance(PluginInstanceChild* instance)
2191 {
2192 NS_ASSERTION(instance->mDeletingHash, "filling null mDeletingHash?");
2193 mObjectMap.EnumerateEntries(CollectForInstance, instance);
2194 }
2196 PLDHashOperator
2197 PluginModuleChild::CollectForInstance(NPObjectData* d, void* userArg)
2198 {
2199 PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
2200 if (d->instance == instance) {
2201 NPObject* o = d->GetKey();
2202 instance->mDeletingHash->PutEntry(o);
2203 }
2204 return PL_DHASH_NEXT;
2205 }
2207 NPIdentifier
2208 PluginModuleChild::NPN_GetStringIdentifier(const NPUTF8* aName)
2209 {
2210 PLUGIN_LOG_DEBUG_FUNCTION;
2211 AssertPluginThread();
2213 if (!aName)
2214 return 0;
2216 PluginModuleChild* self = PluginModuleChild::current();
2217 nsDependentCString name(aName);
2219 PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
2220 if (!ident) {
2221 nsCString nameCopy(name);
2223 ident = new PluginIdentifierChildString(nameCopy);
2224 self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
2225 }
2226 ident->MakePermanent();
2227 return ident;
2228 }
2230 void
2231 PluginModuleChild::NPN_GetStringIdentifiers(const NPUTF8** aNames,
2232 int32_t aNameCount,
2233 NPIdentifier* aIdentifiers)
2234 {
2235 PLUGIN_LOG_DEBUG_FUNCTION;
2236 AssertPluginThread();
2238 if (!(aNames && aNameCount > 0 && aIdentifiers)) {
2239 NS_RUNTIMEABORT("Bad input! Headed for a crash!");
2240 }
2242 PluginModuleChild* self = PluginModuleChild::current();
2244 for (int32_t index = 0; index < aNameCount; ++index) {
2245 if (!aNames[index]) {
2246 aIdentifiers[index] = 0;
2247 continue;
2248 }
2249 nsDependentCString name(aNames[index]);
2250 PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
2251 if (!ident) {
2252 nsCString nameCopy(name);
2254 ident = new PluginIdentifierChildString(nameCopy);
2255 self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
2256 }
2257 ident->MakePermanent();
2258 aIdentifiers[index] = ident;
2259 }
2260 }
2262 bool
2263 PluginModuleChild::NPN_IdentifierIsString(NPIdentifier aIdentifier)
2264 {
2265 PLUGIN_LOG_DEBUG_FUNCTION;
2267 PluginIdentifierChild* ident =
2268 static_cast<PluginIdentifierChild*>(aIdentifier);
2269 return ident->IsString();
2270 }
2272 NPIdentifier
2273 PluginModuleChild::NPN_GetIntIdentifier(int32_t aIntId)
2274 {
2275 PLUGIN_LOG_DEBUG_FUNCTION;
2276 AssertPluginThread();
2278 PluginModuleChild* self = PluginModuleChild::current();
2280 PluginIdentifierChildInt* ident = self->mIntIdentifiers.Get(aIntId);
2281 if (!ident) {
2282 nsCString voidString;
2283 voidString.SetIsVoid(true);
2285 ident = new PluginIdentifierChildInt(aIntId);
2286 self->SendPPluginIdentifierConstructor(ident, voidString, aIntId, false);
2287 }
2288 ident->MakePermanent();
2289 return ident;
2290 }
2292 NPUTF8*
2293 PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
2294 {
2295 PLUGIN_LOG_DEBUG_FUNCTION;
2297 if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
2298 return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
2299 }
2300 return nullptr;
2301 }
2303 int32_t
2304 PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
2305 {
2306 PLUGIN_LOG_DEBUG_FUNCTION;
2308 if (!static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
2309 return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
2310 }
2311 return INT32_MIN;
2312 }
2314 #ifdef OS_WIN
2315 void
2316 PluginModuleChild::EnteredCall()
2317 {
2318 mIncallPumpingStack.AppendElement();
2319 }
2321 void
2322 PluginModuleChild::ExitedCall()
2323 {
2324 NS_ASSERTION(mIncallPumpingStack.Length(), "mismatched entered/exited");
2325 uint32_t len = mIncallPumpingStack.Length();
2326 const IncallFrame& f = mIncallPumpingStack[len - 1];
2327 if (f._spinning)
2328 MessageLoop::current()->SetNestableTasksAllowed(f._savedNestableTasksAllowed);
2330 mIncallPumpingStack.TruncateLength(len - 1);
2331 }
2333 LRESULT CALLBACK
2334 PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
2335 {
2336 // Trap and reply to anything we recognize as the source of a
2337 // potential send message deadlock.
2338 if (nCode >= 0 &&
2339 (InSendMessageEx(nullptr)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
2340 CWPSTRUCT* pCwp = reinterpret_cast<CWPSTRUCT*>(lParam);
2341 if (pCwp->message == WM_KILLFOCUS) {
2342 // Fix for flash fullscreen window loosing focus. On single
2343 // core systems, sync killfocus events need to be handled
2344 // after the flash fullscreen window procedure processes this
2345 // message, otherwise fullscreen focus will not work correctly.
2346 wchar_t szClass[26];
2347 if (GetClassNameW(pCwp->hwnd, szClass,
2348 sizeof(szClass)/sizeof(char16_t)) &&
2349 !wcscmp(szClass, kFlashFullscreenClass)) {
2350 gDelayFlashFocusReplyUntilEval = true;
2351 }
2352 }
2353 }
2355 return CallNextHookEx(nullptr, nCode, wParam, lParam);
2356 }
2358 LRESULT CALLBACK
2359 PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
2360 {
2361 PluginModuleChild* self = current();
2362 uint32_t len = self->mIncallPumpingStack.Length();
2363 if (nCode >= 0 && len && !self->mIncallPumpingStack[len - 1]._spinning) {
2364 MessageLoop* loop = MessageLoop::current();
2365 self->SendProcessNativeEventsInInterruptCall();
2366 IncallFrame& f = self->mIncallPumpingStack[len - 1];
2367 f._spinning = true;
2368 f._savedNestableTasksAllowed = loop->NestableTasksAllowed();
2369 loop->SetNestableTasksAllowed(true);
2370 loop->set_os_modal_loop(true);
2371 }
2373 return CallNextHookEx(nullptr, nCode, wParam, lParam);
2374 }
2376 void
2377 PluginModuleChild::SetEventHooks()
2378 {
2379 NS_ASSERTION(!mNestedEventHook,
2380 "mNestedEventHook already setup in call to SetNestedInputEventHook?");
2381 NS_ASSERTION(!mGlobalCallWndProcHook,
2382 "mGlobalCallWndProcHook already setup in call to CallWindowProcHook?");
2384 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
2386 // WH_MSGFILTER event hook for detecting modal loops in the child.
2387 mNestedEventHook = SetWindowsHookEx(WH_MSGFILTER,
2388 NestedInputEventHook,
2389 nullptr,
2390 GetCurrentThreadId());
2392 // WH_CALLWNDPROC event hook for trapping sync messages sent from
2393 // parent that can cause deadlocks.
2394 mGlobalCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC,
2395 CallWindowProcHook,
2396 nullptr,
2397 GetCurrentThreadId());
2398 }
2400 void
2401 PluginModuleChild::ResetEventHooks()
2402 {
2403 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
2404 if (mNestedEventHook)
2405 UnhookWindowsHookEx(mNestedEventHook);
2406 mNestedEventHook = nullptr;
2407 if (mGlobalCallWndProcHook)
2408 UnhookWindowsHookEx(mGlobalCallWndProcHook);
2409 mGlobalCallWndProcHook = nullptr;
2410 }
2411 #endif
2413 bool
2414 PluginModuleChild::RecvProcessNativeEventsInInterruptCall()
2415 {
2416 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
2417 #if defined(OS_WIN)
2418 ProcessNativeEventsInInterruptCall();
2419 return true;
2420 #else
2421 NS_RUNTIMEABORT(
2422 "PluginModuleChild::RecvProcessNativeEventsInInterruptCall not implemented!");
2423 return false;
2424 #endif
2425 }
2427 #ifdef MOZ_WIDGET_COCOA
2428 void
2429 PluginModuleChild::ProcessNativeEvents() {
2430 CallProcessSomeEvents();
2431 }
2432 #endif
2434 bool
2435 PluginModuleChild::AnswerGeckoGetProfile(nsCString* aProfile) {
2436 char* profile = profiler_get_profile();
2437 if (profile != nullptr) {
2438 *aProfile = nsCString(profile, strlen(profile));
2439 free(profile);
2440 } else {
2441 *aProfile = nsCString("", 0);
2442 }
2443 return true;
2444 }