dom/plugins/ipc/PluginModuleChild.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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         &GTK_WIDGET_CLASS(gtk_plug_class)->scroll_event;
   536     if (!*scroll_event) {
   537         *scroll_event = gtk_plug_scroll_event;
   538     }
   540     GtkPlugEmbeddedFn* embedded = &GTK_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)
  1026     NS_ABORT_IF_FALSE(!!(aNPP->ndata), "nil instance");
  1027     return static_cast<PluginInstanceChild*>(aNPP->ndata);
  1030 namespace mozilla {
  1031 namespace plugins {
  1032 namespace child {
  1034 NPError
  1035 _requestread(NPStream* aStream,
  1036              NPByteRange* aRangeList)
  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);
  1047 NPError
  1048 _geturlnotify(NPP aNPP,
  1049               const char* aRelativeURL,
  1050               const char* aTarget,
  1051               void* aNotifyData)
  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);
  1072     return err;
  1075 NPError
  1076 _getvalue(NPP aNPP,
  1077           NPNVariable aVariable,
  1078           void* aValue)
  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;
  1104 #if (MOZ_WIDGET_GTK == 2)
  1105         case NPNVxDisplay: {
  1106             if (aNPP) {
  1107                 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
  1109             else {
  1110                 *(void **)aValue = xt_client_get_display();
  1112             return NPERR_NO_ERROR;
  1114         case NPNVxtAppContext:
  1115             return NPERR_GENERIC_ERROR;
  1116 #endif
  1117         default: {
  1118             if (aNPP) {
  1119                 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
  1122             NS_WARNING("Null NPP!");
  1123             return NPERR_INVALID_INSTANCE_ERROR;
  1127     NS_NOTREACHED("Shouldn't get here!");
  1128     return NPERR_GENERIC_ERROR;
  1131 NPError
  1132 _setvalue(NPP aNPP,
  1133           NPPVariable aVariable,
  1134           void* aValue)
  1136     PLUGIN_LOG_DEBUG_FUNCTION;
  1137     ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
  1138     return InstCast(aNPP)->NPN_SetValue(aVariable, aValue);
  1141 NPError
  1142 _geturl(NPP aNPP,
  1143         const char* aRelativeURL,
  1144         const char* aTarget)
  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;
  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)
  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);
  1184     return err;
  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)
  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;
  1207 NPError
  1208 _newstream(NPP aNPP,
  1209            NPMIMEType aMIMEType,
  1210            const char* aWindow,
  1211            NPStream** aStream)
  1213     PLUGIN_LOG_DEBUG_FUNCTION;
  1214     ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
  1215     return InstCast(aNPP)->NPN_NewStream(aMIMEType, aWindow, aStream);
  1218 int32_t
  1219 _write(NPP aNPP,
  1220        NPStream* aStream,
  1221        int32_t aLength,
  1222        void* aBuffer)
  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);
  1234 NPError
  1235 _destroystream(NPP aNPP,
  1236                NPStream* aStream,
  1237                NPError aReason)
  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);
  1249     else {
  1250         PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);
  1251         ps->EnsureCorrectInstance(p);
  1252         PPluginStreamChild::Call__delete__(ps, aReason, false);
  1254     return NPERR_NO_ERROR;
  1257 void
  1258 _status(NPP aNPP,
  1259         const char* aMessage)
  1261     PLUGIN_LOG_DEBUG_FUNCTION;
  1262     ENSURE_PLUGIN_THREAD_VOID();
  1263     NS_WARNING("Not yet implemented!");
  1266 void
  1267 _memfree(void* aPtr)
  1269     PLUGIN_LOG_DEBUG_FUNCTION;
  1270     // Only assert plugin thread here for consistency with in-process plugins.
  1271     AssertPluginThread();
  1272     NS_Free(aPtr);
  1275 uint32_t
  1276 _memflush(uint32_t aSize)
  1278     PLUGIN_LOG_DEBUG_FUNCTION;
  1279     // Only assert plugin thread here for consistency with in-process plugins.
  1280     AssertPluginThread();
  1281     return 0;
  1284 void
  1285 _reloadplugins(NPBool aReloadPages)
  1287     PLUGIN_LOG_DEBUG_FUNCTION;
  1288     ENSURE_PLUGIN_THREAD_VOID();
  1290     PluginModuleChild::current()->SendNPN_ReloadPlugins(!!aReloadPages);
  1293 void
  1294 _invalidaterect(NPP aNPP,
  1295                 NPRect* aInvalidRect)
  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);
  1305 void
  1306 _invalidateregion(NPP aNPP,
  1307                   NPRegion aInvalidRegion)
  1309     PLUGIN_LOG_DEBUG_FUNCTION;
  1310     ENSURE_PLUGIN_THREAD_VOID();
  1311     NS_WARNING("Not yet implemented!");
  1314 void
  1315 _forceredraw(NPP aNPP)
  1317     PLUGIN_LOG_DEBUG_FUNCTION;
  1318     ENSURE_PLUGIN_THREAD_VOID();
  1320     // We ignore calls to NPN_ForceRedraw. Such calls should
  1321     // never be necessary.
  1324 const char*
  1325 _useragent(NPP aNPP)
  1327     PLUGIN_LOG_DEBUG_FUNCTION;
  1328     ENSURE_PLUGIN_THREAD(nullptr);
  1329     return PluginModuleChild::current()->GetUserAgent();
  1332 void*
  1333 _memalloc(uint32_t aSize)
  1335     PLUGIN_LOG_DEBUG_FUNCTION;
  1336     // Only assert plugin thread here for consistency with in-process plugins.
  1337     AssertPluginThread();
  1338     return NS_Alloc(aSize);
  1341 // Deprecated entry points for the old Java plugin.
  1342 void* /* OJI type: JRIEnv* */
  1343 _getjavaenv(void)
  1345     PLUGIN_LOG_DEBUG_FUNCTION;
  1346     return 0;
  1349 void* /* OJI type: jref */
  1350 _getjavapeer(NPP aNPP)
  1352     PLUGIN_LOG_DEBUG_FUNCTION;
  1353     return 0;
  1356 bool
  1357 _invoke(NPP aNPP,
  1358         NPObject* aNPObj,
  1359         NPIdentifier aMethod,
  1360         const NPVariant* aArgs,
  1361         uint32_t aArgCount,
  1362         NPVariant* aResult)
  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);
  1373 bool
  1374 _invokedefault(NPP aNPP,
  1375                NPObject* aNPObj,
  1376                const NPVariant* aArgs,
  1377                uint32_t aArgCount,
  1378                NPVariant* aResult)
  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);
  1389 bool
  1390 _evaluate(NPP aNPP,
  1391           NPObject* aObject,
  1392           NPString* aScript,
  1393           NPVariant* aResult)
  1395     PLUGIN_LOG_DEBUG_FUNCTION;
  1396     ENSURE_PLUGIN_THREAD(false);
  1398     if (!(aNPP && aObject && aScript && aResult)) {
  1399         NS_ERROR("Bad arguments!");
  1400         return false;
  1403     PluginScriptableObjectChild* actor =
  1404       InstCast(aNPP)->GetActorForNPObject(aObject);
  1405     if (!actor) {
  1406         NS_ERROR("Failed to create actor?!");
  1407         return false;
  1410 #ifdef XP_WIN
  1411     if (gDelayFlashFocusReplyUntilEval) {
  1412         ReplyMessage(0);
  1413         gDelayFlashFocusReplyUntilEval = false;
  1415 #endif
  1417     return actor->Evaluate(aScript, aResult);
  1420 bool
  1421 _getproperty(NPP aNPP,
  1422              NPObject* aNPObj,
  1423              NPIdentifier aPropertyName,
  1424              NPVariant* aResult)
  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);
  1435 bool
  1436 _setproperty(NPP aNPP,
  1437              NPObject* aNPObj,
  1438              NPIdentifier aPropertyName,
  1439              const NPVariant* aValue)
  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);
  1450 bool
  1451 _removeproperty(NPP aNPP,
  1452                 NPObject* aNPObj,
  1453                 NPIdentifier aPropertyName)
  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);
  1464 bool
  1465 _hasproperty(NPP aNPP,
  1466              NPObject* aNPObj,
  1467              NPIdentifier aPropertyName)
  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);
  1478 bool
  1479 _hasmethod(NPP aNPP,
  1480            NPObject* aNPObj,
  1481            NPIdentifier aMethodName)
  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);
  1492 bool
  1493 _enumerate(NPP aNPP,
  1494            NPObject* aNPObj,
  1495            NPIdentifier** aIdentifiers,
  1496            uint32_t* aCount)
  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;
  1511     return aNPObj->_class->enumerate(aNPObj, aIdentifiers, aCount);
  1514 bool
  1515 _construct(NPP aNPP,
  1516            NPObject* aNPObj,
  1517            const NPVariant* aArgs,
  1518            uint32_t aArgCount,
  1519            NPVariant* aResult)
  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;
  1530     return aNPObj->_class->construct(aNPObj, aArgs, aArgCount, aResult);
  1533 void
  1534 _releasevariantvalue(NPVariant* aVariant)
  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));
  1544     else if (NPVARIANT_IS_OBJECT(*aVariant)) {
  1545         NPObject* object = NPVARIANT_TO_OBJECT(*aVariant);
  1546         if (object) {
  1547             PluginModuleChild::NPN_ReleaseObject(object);
  1550     VOID_TO_NPVARIANT(*aVariant);
  1553 void
  1554 _setexception(NPObject* aNPObj,
  1555               const NPUTF8* aMessage)
  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;
  1570     self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
  1571                                NullableString(aMessage));
  1574 void
  1575 _pushpopupsenabledstate(NPP aNPP,
  1576                         NPBool aEnabled)
  1578     PLUGIN_LOG_DEBUG_FUNCTION;
  1579     ENSURE_PLUGIN_THREAD_VOID();
  1581     InstCast(aNPP)->CallNPN_PushPopupsEnabledState(aEnabled ? true : false);
  1584 void
  1585 _poppopupsenabledstate(NPP aNPP)
  1587     PLUGIN_LOG_DEBUG_FUNCTION;
  1588     ENSURE_PLUGIN_THREAD_VOID();
  1590     InstCast(aNPP)->CallNPN_PopPopupsEnabledState();
  1593 void
  1594 _pluginthreadasynccall(NPP aNPP,
  1595                        PluginThreadCallback aFunc,
  1596                        void* aUserData)
  1598     PLUGIN_LOG_DEBUG_FUNCTION;
  1599     if (!aFunc)
  1600         return;
  1602     InstCast(aNPP)->AsyncCall(aFunc, aUserData);
  1605 NPError
  1606 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
  1607                 char **value, uint32_t *len)
  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();
  1629         return result;
  1632     return NPERR_INVALID_PARAM;
  1635 NPError
  1636 _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
  1637                 const char *value, uint32_t len)
  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;
  1658     return NPERR_INVALID_PARAM;
  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)
  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();
  1691     return result;
  1694 uint32_t
  1695 _scheduletimer(NPP npp, uint32_t interval, NPBool repeat,
  1696                void (*timerFunc)(NPP npp, uint32_t timerID))
  1698     PLUGIN_LOG_DEBUG_FUNCTION;
  1699     AssertPluginThread();
  1700     return InstCast(npp)->ScheduleTimer(interval, repeat, timerFunc);
  1703 void
  1704 _unscheduletimer(NPP npp, uint32_t timerID)
  1706     PLUGIN_LOG_DEBUG_FUNCTION;
  1707     AssertPluginThread();
  1708     InstCast(npp)->UnscheduleTimer(timerID);
  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();
  1721 #endif
  1723 NPError
  1724 _popupcontextmenu(NPP instance, NPMenu* menu)
  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;
  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;
  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;
  1768 #else
  1769     NS_WARNING("Not supported on this platform!");
  1770     return NPERR_GENERIC_ERROR;
  1771 #endif
  1774 NPBool
  1775 _convertpoint(NPP instance, 
  1776               double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
  1777               double *destX, double *destY, NPCoordinateSpace destSpace)
  1779     PLUGIN_LOG_DEBUG_FUNCTION;
  1780     if (!IsPluginThread()) {
  1781         NS_WARNING("Not running on the plugin's main thread!");
  1782         return false;
  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;
  1799     return result;
  1802 void
  1803 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
  1805     InstCast(instance)->NPN_URLRedirectResponse(notifyData, allow);
  1808 NPError
  1809 _initasyncsurface(NPP instance, NPSize *size,
  1810                   NPImageFormat format, void *initData,
  1811                   NPAsyncSurface *surface)
  1813     return InstCast(instance)->NPN_InitAsyncSurface(size, format, initData, surface);
  1816 NPError
  1817 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
  1819     return InstCast(instance)->NPN_FinalizeAsyncSurface(surface);
  1822 void
  1823 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
  1825     InstCast(instance)->NPN_SetCurrentAsyncSurface(surface, changed);
  1828 } /* namespace child */
  1829 } /* namespace plugins */
  1830 } /* namespace mozilla */
  1832 //-----------------------------------------------------------------------------
  1834 bool
  1835 PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
  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
  1850 bool
  1851 PluginModuleChild::AnswerNP_Initialize(const uint32_t& aFlags, NPError* _retval)
  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
  1880 PPluginIdentifierChild*
  1881 PluginModuleChild::AllocPPluginIdentifierChild(const nsCString& aString,
  1882                                                const int32_t& aInt,
  1883                                                const bool& aTemporary)
  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);
  1890     return new PluginIdentifierChildString(aString);
  1893 bool
  1894 PluginModuleChild::RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
  1895                                                     const nsCString& aString,
  1896                                                     const int32_t& aInt,
  1897                                                     const bool& aTemporary)
  1899     if (!aTemporary) {
  1900         static_cast<PluginIdentifierChild*>(actor)->MakePermanent();
  1902     return true;
  1905 bool
  1906 PluginModuleChild::DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor)
  1908     delete aActor;
  1909     return true;
  1912 #if defined(XP_WIN)
  1913 BOOL WINAPI
  1914 PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
  1916   if (!pwi)
  1917       return FALSE;
  1919   if (!sGetWindowInfoPtrStub) {
  1920      NS_ASSERTION(FALSE, "Something is horribly wrong in PMCGetWindowInfoHook!");
  1921      return FALSE;
  1924   if (!sBrowserHwnd) {
  1925       wchar_t szClass[20];
  1926       if (GetClassNameW(hWnd, szClass, ArrayLength(szClass)) &&
  1927           !wcscmp(szClass, kMozillaWindowClass)) {
  1928           sBrowserHwnd = hWnd;
  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;
  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)
  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);
  1961 #endif
  1963     return new PluginInstanceChild(&mFunctions);
  1966 void
  1967 PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
  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
  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;
  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;
  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;
  2008     if (FindInReadable(flash, aMimeType) ||
  2009         FindInReadable(quicktime, mPluginFilename)) {
  2010         mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
  2012 #endif
  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)
  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]));
  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;
  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;
  2076 #endif
  2078     return true;
  2081 bool
  2082 PluginModuleChild::DeallocPPluginInstanceChild(PPluginInstanceChild* aActor)
  2084     PLUGIN_LOG_DEBUG_METHOD;
  2085     AssertPluginThread();
  2087     delete aActor;
  2089     return true;
  2092 NPObject*
  2093 PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
  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;
  2104     NPObject* newObject;
  2105     if (aClass && aClass->allocate) {
  2106         newObject = aClass->allocate(aNPP, aClass);
  2108     else {
  2109         newObject = reinterpret_cast<NPObject*>(child::_memalloc(sizeof(NPObject)));
  2112     if (newObject) {
  2113         newObject->_class = aClass;
  2114         newObject->referenceCount = 1;
  2115         NS_LOG_ADDREF(newObject, 1, "NPObject", sizeof(NPObject));
  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;
  2126 NPObject*
  2127 PluginModuleChild::NPN_RetainObject(NPObject* aNPObj)
  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;
  2140 void
  2141 PluginModuleChild::NPN_ReleaseObject(NPObject* aNPObj)
  2143     AssertPluginThread();
  2145     NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
  2146     if (!d) {
  2147         NS_ERROR("Releasing object not in mObjectMap?");
  2148         return;
  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;
  2158         if (doe->mDeleted)
  2159             return;
  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;
  2170     return;
  2173 void
  2174 PluginModuleChild::DeallocNPObject(NPObject* aNPObj)
  2176     if (aNPObj->_class && aNPObj->_class->deallocate) {
  2177         aNPObj->_class->deallocate(aNPObj);
  2178     } else {
  2179         child::_memfree(aNPObj);
  2182     NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
  2183     if (d->actor)
  2184         d->actor->NPObjectDestroyed();
  2186     current()->mObjectMap.RemoveEntry(aNPObj);
  2189 void
  2190 PluginModuleChild::FindNPObjectsForInstance(PluginInstanceChild* instance)
  2192     NS_ASSERTION(instance->mDeletingHash, "filling null mDeletingHash?");
  2193     mObjectMap.EnumerateEntries(CollectForInstance, instance);
  2196 PLDHashOperator
  2197 PluginModuleChild::CollectForInstance(NPObjectData* d, void* userArg)
  2199     PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
  2200     if (d->instance == instance) {
  2201         NPObject* o = d->GetKey();
  2202         instance->mDeletingHash->PutEntry(o);
  2204     return PL_DHASH_NEXT;
  2207 NPIdentifier
  2208 PluginModuleChild::NPN_GetStringIdentifier(const NPUTF8* aName)
  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);
  2226     ident->MakePermanent();
  2227     return ident;
  2230 void
  2231 PluginModuleChild::NPN_GetStringIdentifiers(const NPUTF8** aNames,
  2232                                             int32_t aNameCount,
  2233                                             NPIdentifier* aIdentifiers)
  2235     PLUGIN_LOG_DEBUG_FUNCTION;
  2236     AssertPluginThread();
  2238     if (!(aNames && aNameCount > 0 && aIdentifiers)) {
  2239         NS_RUNTIMEABORT("Bad input! Headed for a crash!");
  2242     PluginModuleChild* self = PluginModuleChild::current();
  2244     for (int32_t index = 0; index < aNameCount; ++index) {
  2245         if (!aNames[index]) {
  2246             aIdentifiers[index] = 0;
  2247             continue;
  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);
  2257         ident->MakePermanent();
  2258         aIdentifiers[index] = ident;
  2262 bool
  2263 PluginModuleChild::NPN_IdentifierIsString(NPIdentifier aIdentifier)
  2265     PLUGIN_LOG_DEBUG_FUNCTION;
  2267     PluginIdentifierChild* ident =
  2268         static_cast<PluginIdentifierChild*>(aIdentifier);
  2269     return ident->IsString();
  2272 NPIdentifier
  2273 PluginModuleChild::NPN_GetIntIdentifier(int32_t aIntId)
  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);
  2288     ident->MakePermanent();
  2289     return ident;
  2292 NPUTF8*
  2293 PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
  2295     PLUGIN_LOG_DEBUG_FUNCTION;
  2297     if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
  2298       return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
  2300     return nullptr;
  2303 int32_t
  2304 PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
  2306     PLUGIN_LOG_DEBUG_FUNCTION;
  2308     if (!static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
  2309       return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
  2311     return INT32_MIN;
  2314 #ifdef OS_WIN
  2315 void
  2316 PluginModuleChild::EnteredCall()
  2318     mIncallPumpingStack.AppendElement();
  2321 void
  2322 PluginModuleChild::ExitedCall()
  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);
  2333 LRESULT CALLBACK
  2334 PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
  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;
  2355     return CallNextHookEx(nullptr, nCode, wParam, lParam);
  2358 LRESULT CALLBACK
  2359 PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
  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);
  2373     return CallNextHookEx(nullptr, nCode, wParam, lParam);
  2376 void
  2377 PluginModuleChild::SetEventHooks()
  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());
  2400 void
  2401 PluginModuleChild::ResetEventHooks()
  2403     PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  2404     if (mNestedEventHook)
  2405         UnhookWindowsHookEx(mNestedEventHook);
  2406     mNestedEventHook = nullptr;
  2407     if (mGlobalCallWndProcHook)
  2408         UnhookWindowsHookEx(mGlobalCallWndProcHook);
  2409     mGlobalCallWndProcHook = nullptr;
  2411 #endif
  2413 bool
  2414 PluginModuleChild::RecvProcessNativeEventsInInterruptCall()
  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
  2427 #ifdef MOZ_WIDGET_COCOA
  2428 void
  2429 PluginModuleChild::ProcessNativeEvents() {
  2430     CallProcessSomeEvents();    
  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);
  2443     return true;

mercurial