dom/plugins/ipc/PluginModuleChild.h

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: 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 #ifndef dom_plugins_PluginModuleChild_h
     8 #define dom_plugins_PluginModuleChild_h 1
    10 #include "mozilla/Attributes.h"
    12 #include <string>
    13 #include <vector>
    15 #include "base/basictypes.h"
    17 #include "prlink.h"
    19 #include "npapi.h"
    20 #include "npfunctions.h"
    22 #include "nsAutoPtr.h"
    23 #include "nsDataHashtable.h"
    24 #include "nsTHashtable.h"
    25 #include "nsHashKeys.h"
    27 #ifdef MOZ_WIDGET_COCOA
    28 #include "PluginInterposeOSX.h"
    29 #endif
    31 #include "mozilla/plugins/PPluginModuleChild.h"
    32 #include "mozilla/plugins/PluginInstanceChild.h"
    33 #include "mozilla/plugins/PluginIdentifierChild.h"
    34 #include "mozilla/plugins/PluginMessageUtils.h"
    36 // NOTE: stolen from nsNPAPIPlugin.h
    38 #if defined(XP_WIN)
    39 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
    40 #else
    41 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
    42 #endif
    44 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
    45 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
    46 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
    47 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
    49 namespace mozilla {
    50 namespace dom {
    51 class PCrashReporterChild;
    52 }
    54 namespace plugins {
    56 #ifdef MOZ_WIDGET_QT
    57 class NestedLoopTimer;
    58 static const int kNestedLoopDetectorIntervalMs = 90;
    59 #endif
    61 class PluginScriptableObjectChild;
    62 class PluginInstanceChild;
    64 class PluginModuleChild : public PPluginModuleChild
    65 {
    66     typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
    67 protected:
    68     virtual mozilla::ipc::RacyInterruptPolicy
    69     MediateInterruptRace(const Message& parent, const Message& child) MOZ_OVERRIDE
    70     {
    71         return MediateRace(parent, child);
    72     }
    74     virtual bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
    76     // Implement the PPluginModuleChild interface
    77     virtual bool AnswerNP_GetEntryPoints(NPError* rv) MOZ_OVERRIDE;
    78     virtual bool AnswerNP_Initialize(const uint32_t& aFlags, NPError* rv) MOZ_OVERRIDE;
    80     virtual PPluginIdentifierChild*
    81     AllocPPluginIdentifierChild(const nsCString& aString,
    82                                 const int32_t& aInt,
    83                                 const bool& aTemporary) MOZ_OVERRIDE;
    85     virtual bool
    86     RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
    87                                      const nsCString& aString,
    88                                      const int32_t& aInt,
    89                                      const bool& aTemporary) MOZ_OVERRIDE;
    91     virtual bool
    92     DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor) MOZ_OVERRIDE;
    94     virtual PPluginInstanceChild*
    95     AllocPPluginInstanceChild(const nsCString& aMimeType,
    96                               const uint16_t& aMode,
    97                               const InfallibleTArray<nsCString>& aNames,
    98                               const InfallibleTArray<nsCString>& aValues,
    99                               NPError* rv) MOZ_OVERRIDE;
   101     virtual bool
   102     DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) MOZ_OVERRIDE;
   104     virtual bool
   105     AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
   106                                      const nsCString& aMimeType,
   107                                      const uint16_t& aMode,
   108                                      const InfallibleTArray<nsCString>& aNames,
   109                                      const InfallibleTArray<nsCString>& aValues,
   110                                      NPError* rv) MOZ_OVERRIDE;
   111     virtual bool
   112     AnswerNP_Shutdown(NPError *rv) MOZ_OVERRIDE;
   114     virtual bool
   115     AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
   116                                      bool *aClearSiteData,
   117                                      bool *aGetSitesWithData) MOZ_OVERRIDE;
   119     virtual bool
   120     AnswerNPP_ClearSiteData(const nsCString& aSite,
   121                             const uint64_t& aFlags,
   122                             const uint64_t& aMaxAge,
   123                             NPError* aResult) MOZ_OVERRIDE;
   125     virtual bool
   126     AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult) MOZ_OVERRIDE;
   128     virtual bool
   129     RecvSetAudioSessionData(const nsID& aId,
   130                             const nsString& aDisplayName,
   131                             const nsString& aIconPath) MOZ_OVERRIDE;
   133     virtual bool
   134     RecvSetParentHangTimeout(const uint32_t& aSeconds) MOZ_OVERRIDE;
   136     virtual PCrashReporterChild*
   137     AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
   138                              uint32_t* processType) MOZ_OVERRIDE;
   139     virtual bool
   140     DeallocPCrashReporterChild(PCrashReporterChild* actor) MOZ_OVERRIDE;
   141     virtual bool
   142     AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
   143                                     mozilla::dom::NativeThreadId* id,
   144                                     uint32_t* processType) MOZ_OVERRIDE;
   146     virtual void
   147     ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
   149     MOZ_NORETURN void QuickExit();
   151     virtual bool
   152     RecvProcessNativeEventsInInterruptCall() MOZ_OVERRIDE;
   154     virtual bool
   155     AnswerGeckoGetProfile(nsCString* aProfile) MOZ_OVERRIDE;
   157 public:
   158     PluginModuleChild();
   159     virtual ~PluginModuleChild();
   161     // aPluginFilename is UTF8, not native-charset!
   162     bool Init(const std::string& aPluginFilename,
   163               base::ProcessHandle aParentProcessHandle,
   164               MessageLoop* aIOLoop,
   165               IPC::Channel* aChannel);
   167     void CleanUp();
   169     const char* GetUserAgent();
   171     static const NPNetscapeFuncs sBrowserFuncs;
   173     static PluginModuleChild* current();
   175     bool RegisterActorForNPObject(NPObject* aObject,
   176                                   PluginScriptableObjectChild* aActor);
   178     void UnregisterActorForNPObject(NPObject* aObject);
   180     PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
   182 #ifdef DEBUG
   183     bool NPObjectIsRegistered(NPObject* aObject);
   184 #endif
   186     bool AsyncDrawingAllowed() { return mAsyncDrawingAllowed; }
   188     /**
   189      * The child implementation of NPN_CreateObject.
   190      */
   191     static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
   192     /**
   193      * The child implementation of NPN_RetainObject.
   194      */
   195     static NPObject* NPN_RetainObject(NPObject* aNPObj);
   196     /**
   197      * The child implementation of NPN_ReleaseObject.
   198      */
   199     static void NPN_ReleaseObject(NPObject* aNPObj);
   201     /**
   202      * The child implementations of NPIdentifier-related functions.
   203      */
   204     static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
   205     static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
   206                                                      int32_t aNameCount,
   207                                                      NPIdentifier* aIdentifiers);
   208     static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
   209     static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
   210     static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
   211     static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
   213 #ifdef MOZ_WIDGET_COCOA
   214     void ProcessNativeEvents();
   216     void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
   217         SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width, r.size.height);
   218     }
   220     void PluginHideWindow(uint32_t window_id) {
   221         SendPluginHideWindow(window_id);
   222     }
   224     void SetCursor(NSCursorInfo& cursorInfo) {
   225         SendSetCursor(cursorInfo);
   226     }
   228     void ShowCursor(bool show) {
   229         SendShowCursor(show);
   230     }
   232     void PushCursor(NSCursorInfo& cursorInfo) {
   233         SendPushCursor(cursorInfo);
   234     }
   236     void PopCursor() {
   237         SendPopCursor();
   238     }
   240     bool GetNativeCursorsSupported() {
   241         bool supported = false;
   242         SendGetNativeCursorsSupported(&supported);
   243         return supported;
   244     }
   245 #endif
   247     // Quirks mode support for various plugin mime types
   248     enum PluginQuirks {
   249         QUIRKS_NOT_INITIALIZED                          = 0,
   250         // Silverlight assumes it is transparent in windowless mode. This quirk
   251         // matches the logic in nsNPAPIPluginInstance::SetWindowless.
   252         QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT           = 1 << 0,
   253         // Win32: Hook TrackPopupMenu api so that we can swap out parent
   254         // hwnds. The api will fail with parents not associated with our
   255         // child ui thread. See WinlessHandleEvent for details.
   256         QUIRK_WINLESS_TRACKPOPUP_HOOK                   = 1 << 1,
   257         // Win32: Throttle flash WM_USER+1 heart beat messages to prevent
   258         // flooding chromium's dispatch loop, which can cause ipc traffic
   259         // processing lag.
   260         QUIRK_FLASH_THROTTLE_WMUSER_EVENTS              = 1 << 2,
   261         // Win32: Catch resets on our subclass by hooking SetWindowLong.
   262         QUIRK_FLASH_HOOK_SETLONGPTR                     = 1 << 3,
   263         // X11: Work around a bug in Flash up to 10.1 d51 at least, where
   264         // expose event top left coordinates within the plugin-rect and
   265         // not at the drawable origin are misinterpreted.
   266         QUIRK_FLASH_EXPOSE_COORD_TRANSLATION            = 1 << 4,
   267         // Win32: Catch get window info calls on the browser and tweak the
   268         // results so mouse input works when flash is displaying it's settings
   269         // window.
   270         QUIRK_FLASH_HOOK_GETWINDOWINFO                  = 1 << 5,
   271         // Win: Addresses a flash bug with mouse capture and full screen
   272         // windows.
   273         QUIRK_FLASH_FIXUP_MOUSE_CAPTURE                 = 1 << 6,
   274         // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
   275         // Avoid calling SetWindow in that case.
   276         QUIRK_QUICKTIME_AVOID_SETWINDOW                 = 1 << 7,
   277         // Win: Check to make sure the parent window has focus before calling
   278         // set focus on the child. Addresses a full screen dialog prompt
   279         // problem in Silverlight.
   280         QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT            = 1 << 8,
   281         // Mac: Allow the plugin to use offline renderer mode.
   282         // Use this only if the plugin is certified the support the offline renderer.
   283         QUIRK_ALLOW_OFFLINE_RENDERER                    = 1 << 9,
   284         // Mac: Work around a Flash bug that can cause plugin process crashes
   285         // in CoreGraphics mode:  The Flash plugin sometimes accesses the
   286         // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect)
   287         // outside of that call.  See bug 804606.
   288         QUIRK_FLASH_AVOID_CGMODE_CRASHES                = 1 << 10,
   289     };
   291     int GetQuirks() { return mQuirks; }
   293 private:
   294     void AddQuirk(PluginQuirks quirk) {
   295       if (mQuirks == QUIRKS_NOT_INITIALIZED)
   296         mQuirks = 0;
   297       mQuirks |= quirk;
   298     }
   299     void InitQuirksModes(const nsCString& aMimeType);
   300     bool InitGraphics();
   301     void DeinitGraphics();
   302 #if defined(MOZ_WIDGET_GTK)
   303     static gboolean DetectNestedEventLoop(gpointer data);
   304     static gboolean ProcessBrowserEvents(gpointer data);
   306     virtual void EnteredCxxStack() MOZ_OVERRIDE;
   307     virtual void ExitedCxxStack() MOZ_OVERRIDE;
   308 #elif defined(MOZ_WIDGET_QT)
   310     virtual void EnteredCxxStack() MOZ_OVERRIDE;
   311     virtual void ExitedCxxStack() MOZ_OVERRIDE;
   312 #endif
   314     PRLibrary* mLibrary;
   315     nsCString mPluginFilename; // UTF8
   316     nsCString mUserAgent;
   317     int mQuirks;
   318     bool mAsyncDrawingAllowed;
   320     // we get this from the plugin
   321     NP_PLUGINSHUTDOWN mShutdownFunc;
   322 #if defined(OS_LINUX) || defined(OS_BSD)
   323     NP_PLUGINUNIXINIT mInitializeFunc;
   324 #elif defined(OS_WIN) || defined(OS_MACOSX)
   325     NP_PLUGININIT mInitializeFunc;
   326     NP_GETENTRYPOINTS mGetEntryPointsFunc;
   327 #endif
   329     NPPluginFuncs mFunctions;
   330     NPSavedData mSavedData;
   332 #if defined(MOZ_WIDGET_GTK)
   333     // If a plugin spins a nested glib event loop in response to a
   334     // synchronous IPC message from the browser, the loop might break
   335     // only after the browser responds to a request sent by the
   336     // plugin.  This can happen if a plugin uses gtk's synchronous
   337     // copy/paste, for example.  But because the browser is blocked on
   338     // a condvar, it can't respond to the request.  This situation
   339     // isn't technically a deadlock, but the symptoms are basically
   340     // the same from the user's perspective.
   341     //
   342     // We take two steps to prevent this
   343     //
   344     //  (1) Detect nested event loops spun by the plugin.  This is
   345     //      done by scheduling a glib timer event in the plugin
   346     //      process whenever the browser might block on the plugin.
   347     //      If the plugin indeed spins a nested loop, this timer event
   348     //      will fire "soon" thereafter.
   349     //
   350     //  (2) When a nested loop is detected, deschedule the
   351     //      nested-loop-detection timer and in its place, schedule
   352     //      another timer that periodically calls back into the
   353     //      browser and spins a mini event loop.  This mini event loop
   354     //      processes a handful of pending native events.
   355     //
   356     // Because only timer (1) or (2) (or neither) may be active at any
   357     // point in time, we use the same member variable
   358     // |mNestedLoopTimerId| to refer to both.
   359     //
   360     // When the browser no longer might be blocked on a plugin's IPC
   361     // response, we deschedule whichever of (1) or (2) is active.
   362     guint mNestedLoopTimerId;
   363 #  ifdef DEBUG
   364     // Depth of the stack of calls to g_main_context_dispatch before any
   365     // nested loops are run.  This is 1 when IPC calls are dispatched from
   366     // g_main_context_iteration, or 0 when dispatched directly from
   367     // MessagePumpForUI.
   368     int mTopLoopDepth;
   369 #  endif
   370 #elif defined (MOZ_WIDGET_QT)
   371     NestedLoopTimer *mNestedLoopTimerObject;
   372 #endif
   374     struct NPObjectData : public nsPtrHashKey<NPObject>
   375     {
   376         NPObjectData(const NPObject* key)
   377             : nsPtrHashKey<NPObject>(key)
   378             , instance(nullptr)
   379             , actor(nullptr)
   380         { }
   382         // never nullptr
   383         PluginInstanceChild* instance;
   385         // sometimes nullptr (no actor associated with an NPObject)
   386         PluginScriptableObjectChild* actor;
   387     };
   388     /**
   389      * mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
   390      * final release/dealloc, whether or not an actor is currently associated with the object.
   391      */
   392     nsTHashtable<NPObjectData> mObjectMap;
   394     friend class PluginIdentifierChild;
   395     friend class PluginIdentifierChildString;
   396     friend class PluginIdentifierChildInt;
   397     nsDataHashtable<nsCStringHashKey, PluginIdentifierChildString*> mStringIdentifiers;
   398     nsDataHashtable<nsUint32HashKey, PluginIdentifierChildInt*> mIntIdentifiers;
   400 public: // called by PluginInstanceChild
   401     /**
   402      * Dealloc an NPObject after last-release or when the associated instance
   403      * is destroyed. This function will remove the object from mObjectMap.
   404      */
   405     static void DeallocNPObject(NPObject* o);
   407     NPError NPP_Destroy(PluginInstanceChild* instance) {
   408         return mFunctions.destroy(instance->GetNPP(), 0);
   409     }
   411     /**
   412      * Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
   413      * associated with that instance.
   414      */
   415     void FindNPObjectsForInstance(PluginInstanceChild* instance);
   417 private:
   418     static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
   420 #if defined(OS_WIN)
   421     virtual void EnteredCall() MOZ_OVERRIDE;
   422     virtual void ExitedCall() MOZ_OVERRIDE;
   424     // Entered/ExitedCall notifications keep track of whether the plugin has
   425     // entered a nested event loop within this interrupt call.
   426     struct IncallFrame
   427     {
   428         IncallFrame()
   429             : _spinning(false)
   430             , _savedNestableTasksAllowed(false)
   431         { }
   433         bool _spinning;
   434         bool _savedNestableTasksAllowed;
   435     };
   437     nsAutoTArray<IncallFrame, 8> mIncallPumpingStack;
   439     static LRESULT CALLBACK NestedInputEventHook(int code,
   440                                                  WPARAM wParam,
   441                                                  LPARAM lParam);
   442     static LRESULT CALLBACK CallWindowProcHook(int code,
   443                                                WPARAM wParam,
   444                                                LPARAM lParam);
   445     void SetEventHooks();
   446     void ResetEventHooks();
   447     HHOOK mNestedEventHook;
   448     HHOOK mGlobalCallWndProcHook;
   449 #endif
   450 };
   452 } /* namespace plugins */
   453 } /* namespace mozilla */
   455 #endif  // ifndef dom_plugins_PluginModuleChild_h

mercurial