summaryrefslogtreecommitdiffstats
path: root/dom/plugins/ipc/PluginModuleChild.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/plugins/ipc/PluginModuleChild.h')
-rw-r--r--dom/plugins/ipc/PluginModuleChild.h387
1 files changed, 387 insertions, 0 deletions
diff --git a/dom/plugins/ipc/PluginModuleChild.h b/dom/plugins/ipc/PluginModuleChild.h
new file mode 100644
index 000000000..233a95369
--- /dev/null
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -0,0 +1,387 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef dom_plugins_PluginModuleChild_h
+#define dom_plugins_PluginModuleChild_h 1
+
+#include "mozilla/Attributes.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+
+#include "prlink.h"
+
+#include "npapi.h"
+#include "npfunctions.h"
+
+#include "nsDataHashtable.h"
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
+
+#ifdef MOZ_WIDGET_COCOA
+#include "PluginInterposeOSX.h"
+#endif
+
+#include "mozilla/plugins/PPluginModuleChild.h"
+#include "mozilla/plugins/PluginInstanceChild.h"
+#include "mozilla/plugins/PluginMessageUtils.h"
+#include "mozilla/plugins/PluginQuirks.h"
+
+// NOTE: stolen from nsNPAPIPlugin.h
+
+#if defined(XP_WIN)
+#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
+#else
+#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
+#endif
+
+typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
+typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
+typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
+typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
+
+namespace mozilla {
+namespace dom {
+class PCrashReporterChild;
+} // namespace dom
+
+namespace plugins {
+
+class PluginInstanceChild;
+
+class PluginModuleChild : public PPluginModuleChild
+{
+ typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
+protected:
+ virtual mozilla::ipc::RacyInterruptPolicy
+ MediateInterruptRace(const MessageInfo& parent,
+ const MessageInfo& child) override
+ {
+ return MediateRace(parent, child);
+ }
+
+ virtual bool ShouldContinueFromReplyTimeout() override;
+
+ virtual bool RecvSettingChanged(const PluginSettings& aSettings) override;
+
+ // Implement the PPluginModuleChild interface
+ virtual bool RecvDisableFlashProtectedMode() override;
+ virtual bool AnswerNP_GetEntryPoints(NPError* rv) override;
+ virtual bool AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv) override;
+ virtual bool RecvAsyncNP_Initialize(const PluginSettings& aSettings) override;
+ virtual bool AnswerSyncNPP_New(PPluginInstanceChild* aActor, NPError* rv)
+ override;
+ virtual bool RecvAsyncNPP_New(PPluginInstanceChild* aActor) override;
+
+ virtual PPluginModuleChild*
+ AllocPPluginModuleChild(mozilla::ipc::Transport* aTransport,
+ base::ProcessId aOtherProcess) override;
+
+ virtual PPluginInstanceChild*
+ AllocPPluginInstanceChild(const nsCString& aMimeType,
+ const uint16_t& aMode,
+ const InfallibleTArray<nsCString>& aNames,
+ const InfallibleTArray<nsCString>& aValues)
+ override;
+
+ virtual bool
+ DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) override;
+
+ virtual bool
+ RecvPPluginInstanceConstructor(PPluginInstanceChild* aActor,
+ const nsCString& aMimeType,
+ const uint16_t& aMode,
+ InfallibleTArray<nsCString>&& aNames,
+ InfallibleTArray<nsCString>&& aValues)
+ override;
+ virtual bool
+ AnswerNP_Shutdown(NPError *rv) override;
+
+ virtual bool
+ AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
+ bool *aClearSiteData,
+ bool *aGetSitesWithData) override;
+
+ virtual bool
+ RecvNPP_ClearSiteData(const nsCString& aSite,
+ const uint64_t& aFlags,
+ const uint64_t& aMaxAge,
+ const uint64_t& aCallbackId) override;
+
+ virtual bool
+ RecvNPP_GetSitesWithData(const uint64_t& aCallbackId) override;
+
+ virtual bool
+ RecvSetAudioSessionData(const nsID& aId,
+ const nsString& aDisplayName,
+ const nsString& aIconPath) override;
+
+ virtual bool
+ RecvSetParentHangTimeout(const uint32_t& aSeconds) override;
+
+ virtual PCrashReporterChild*
+ AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
+ uint32_t* processType) override;
+ virtual bool
+ DeallocPCrashReporterChild(PCrashReporterChild* actor) override;
+ virtual bool
+ AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
+ mozilla::dom::NativeThreadId* id,
+ uint32_t* processType) override;
+
+ virtual void
+ ActorDestroy(ActorDestroyReason why) override;
+
+ virtual bool
+ RecvProcessNativeEventsInInterruptCall() override;
+
+ virtual bool RecvStartProfiler(const ProfilerInitParams& params) override;
+ virtual bool RecvStopProfiler() override;
+ virtual bool RecvGatherProfile() override;
+
+ virtual bool
+ AnswerModuleSupportsAsyncRender(bool* aResult) override;
+public:
+ explicit PluginModuleChild(bool aIsChrome);
+ virtual ~PluginModuleChild();
+
+ bool CommonInit(base::ProcessId aParentPid,
+ MessageLoop* aIOLoop,
+ IPC::Channel* aChannel);
+
+ // aPluginFilename is UTF8, not native-charset!
+ bool InitForChrome(const std::string& aPluginFilename,
+ base::ProcessId aParentPid,
+ MessageLoop* aIOLoop,
+ IPC::Channel* aChannel);
+
+ bool InitForContent(base::ProcessId aParentPid,
+ MessageLoop* aIOLoop,
+ IPC::Channel* aChannel);
+
+ static PluginModuleChild*
+ CreateForContentProcess(mozilla::ipc::Transport* aTransport,
+ base::ProcessId aOtherProcess);
+
+ void CleanUp();
+
+ NPError NP_Shutdown();
+
+ const char* GetUserAgent();
+
+ static const NPNetscapeFuncs sBrowserFuncs;
+
+ static PluginModuleChild* GetChrome();
+
+ /**
+ * The child implementation of NPN_CreateObject.
+ */
+ static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
+ /**
+ * The child implementation of NPN_RetainObject.
+ */
+ static NPObject* NPN_RetainObject(NPObject* aNPObj);
+ /**
+ * The child implementation of NPN_ReleaseObject.
+ */
+ static void NPN_ReleaseObject(NPObject* aNPObj);
+
+ /**
+ * The child implementations of NPIdentifier-related functions.
+ */
+ static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
+ static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
+ int32_t aNameCount,
+ NPIdentifier* aIdentifiers);
+ static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
+ static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
+ static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
+ static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
+
+#ifdef MOZ_WIDGET_COCOA
+ void ProcessNativeEvents();
+
+ void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
+ SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width, r.size.height);
+ }
+
+ void PluginHideWindow(uint32_t window_id) {
+ SendPluginHideWindow(window_id);
+ }
+
+ void SetCursor(NSCursorInfo& cursorInfo) {
+ SendSetCursor(cursorInfo);
+ }
+
+ void ShowCursor(bool show) {
+ SendShowCursor(show);
+ }
+
+ void PushCursor(NSCursorInfo& cursorInfo) {
+ SendPushCursor(cursorInfo);
+ }
+
+ void PopCursor() {
+ SendPopCursor();
+ }
+
+ bool GetNativeCursorsSupported() {
+ return Settings().nativeCursorsSupported();
+ }
+#endif
+
+ int GetQuirks() { return mQuirks; }
+
+ const PluginSettings& Settings() const { return mCachedSettings; }
+
+ NPError PluginRequiresAudioDeviceChanges(PluginInstanceChild* aInstance,
+ NPBool aShouldRegister);
+ bool RecvNPP_SetValue_NPNVaudioDeviceChangeDetails(
+ const NPAudioDeviceChangeDetailsIPC& detailsIPC) override;
+
+private:
+ NPError DoNP_Initialize(const PluginSettings& aSettings);
+ void AddQuirk(PluginQuirks quirk) {
+ if (mQuirks == QUIRKS_NOT_INITIALIZED)
+ mQuirks = 0;
+ mQuirks |= quirk;
+ }
+ void InitQuirksModes(const nsCString& aMimeType);
+ bool InitGraphics();
+ void DeinitGraphics();
+
+#if defined(OS_WIN)
+ void HookProtectedMode();
+#endif
+
+#if defined(MOZ_WIDGET_GTK)
+ static gboolean DetectNestedEventLoop(gpointer data);
+ static gboolean ProcessBrowserEvents(gpointer data);
+
+ virtual void EnteredCxxStack() override;
+ virtual void ExitedCxxStack() override;
+#endif
+
+ PRLibrary* mLibrary;
+ nsCString mPluginFilename; // UTF8
+ int mQuirks;
+
+ bool mIsChrome;
+ bool mHasShutdown; // true if NP_Shutdown has run
+ Transport* mTransport;
+
+ // we get this from the plugin
+ NP_PLUGINSHUTDOWN mShutdownFunc;
+#if defined(OS_LINUX) || defined(OS_BSD)
+ NP_PLUGINUNIXINIT mInitializeFunc;
+#elif defined(OS_WIN) || defined(OS_MACOSX)
+ NP_PLUGININIT mInitializeFunc;
+ NP_GETENTRYPOINTS mGetEntryPointsFunc;
+#endif
+
+ NPPluginFuncs mFunctions;
+
+ PluginSettings mCachedSettings;
+
+#if defined(MOZ_WIDGET_GTK)
+ // If a plugin spins a nested glib event loop in response to a
+ // synchronous IPC message from the browser, the loop might break
+ // only after the browser responds to a request sent by the
+ // plugin. This can happen if a plugin uses gtk's synchronous
+ // copy/paste, for example. But because the browser is blocked on
+ // a condvar, it can't respond to the request. This situation
+ // isn't technically a deadlock, but the symptoms are basically
+ // the same from the user's perspective.
+ //
+ // We take two steps to prevent this
+ //
+ // (1) Detect nested event loops spun by the plugin. This is
+ // done by scheduling a glib timer event in the plugin
+ // process whenever the browser might block on the plugin.
+ // If the plugin indeed spins a nested loop, this timer event
+ // will fire "soon" thereafter.
+ //
+ // (2) When a nested loop is detected, deschedule the
+ // nested-loop-detection timer and in its place, schedule
+ // another timer that periodically calls back into the
+ // browser and spins a mini event loop. This mini event loop
+ // processes a handful of pending native events.
+ //
+ // Because only timer (1) or (2) (or neither) may be active at any
+ // point in time, we use the same member variable
+ // |mNestedLoopTimerId| to refer to both.
+ //
+ // When the browser no longer might be blocked on a plugin's IPC
+ // response, we deschedule whichever of (1) or (2) is active.
+ guint mNestedLoopTimerId;
+# ifdef DEBUG
+ // Depth of the stack of calls to g_main_context_dispatch before any
+ // nested loops are run. This is 1 when IPC calls are dispatched from
+ // g_main_context_iteration, or 0 when dispatched directly from
+ // MessagePumpForUI.
+ int mTopLoopDepth;
+# endif
+#endif
+
+#if defined(XP_WIN)
+ typedef nsTHashtable<nsPtrHashKey<PluginInstanceChild>> PluginInstanceSet;
+ // Set of plugins that have registered to be notified when the audio device
+ // changes.
+ PluginInstanceSet mAudioNotificationSet;
+#endif
+
+public: // called by PluginInstanceChild
+ /**
+ * Dealloc an NPObject after last-release or when the associated instance
+ * is destroyed. This function will remove the object from mObjectMap.
+ */
+ static void DeallocNPObject(NPObject* o);
+
+ NPError NPP_Destroy(PluginInstanceChild* instance) {
+ return mFunctions.destroy(instance->GetNPP(), 0);
+ }
+
+private:
+#if defined(OS_WIN)
+ virtual void EnteredCall() override;
+ virtual void ExitedCall() override;
+
+ // Entered/ExitedCall notifications keep track of whether the plugin has
+ // entered a nested event loop within this interrupt call.
+ struct IncallFrame
+ {
+ IncallFrame()
+ : _spinning(false)
+ , _savedNestableTasksAllowed(false)
+ { }
+
+ bool _spinning;
+ bool _savedNestableTasksAllowed;
+ };
+
+ AutoTArray<IncallFrame, 8> mIncallPumpingStack;
+
+ static LRESULT CALLBACK NestedInputEventHook(int code,
+ WPARAM wParam,
+ LPARAM lParam);
+ static LRESULT CALLBACK CallWindowProcHook(int code,
+ WPARAM wParam,
+ LPARAM lParam);
+ void SetEventHooks();
+ void ResetEventHooks();
+ HHOOK mNestedEventHook;
+ HHOOK mGlobalCallWndProcHook;
+public:
+ bool mAsyncRenderSupport;
+#endif
+};
+
+} /* namespace plugins */
+} /* namespace mozilla */
+
+#endif // ifndef dom_plugins_PluginModuleChild_h