diff options
Diffstat (limited to 'dom/plugins/ipc/PluginModuleChild.h')
-rw-r--r-- | dom/plugins/ipc/PluginModuleChild.h | 387 |
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 |