Line data Source code
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/. */
6 :
7 : #ifndef dom_plugins_PluginModuleChild_h
8 : #define dom_plugins_PluginModuleChild_h 1
9 :
10 : #include "mozilla/Attributes.h"
11 :
12 : #include <string>
13 : #include <vector>
14 :
15 : #include "base/basictypes.h"
16 :
17 : #include "prlink.h"
18 :
19 : #include "npapi.h"
20 : #include "npfunctions.h"
21 :
22 : #include "nsDataHashtable.h"
23 : #include "nsTHashtable.h"
24 : #include "nsHashKeys.h"
25 :
26 : #ifdef MOZ_WIDGET_COCOA
27 : #include "PluginInterposeOSX.h"
28 : #endif
29 :
30 : #include "mozilla/plugins/PPluginModuleChild.h"
31 : #include "mozilla/plugins/PluginInstanceChild.h"
32 : #include "mozilla/plugins/PluginMessageUtils.h"
33 : #include "mozilla/plugins/PluginQuirks.h"
34 :
35 : // NOTE: stolen from nsNPAPIPlugin.h
36 :
37 : #if defined(XP_WIN)
38 : #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
39 : #else
40 : #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
41 : #endif
42 :
43 : typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
44 : typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
45 : typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
46 : typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
47 :
48 : namespace mozilla {
49 :
50 : class ChildProfilerController;
51 :
52 : namespace plugins {
53 :
54 : class PluginInstanceChild;
55 :
56 : class PluginModuleChild : public PPluginModuleChild
57 : {
58 : protected:
59 : virtual mozilla::ipc::RacyInterruptPolicy
60 0 : MediateInterruptRace(const MessageInfo& parent,
61 : const MessageInfo& child) override
62 : {
63 0 : return MediateRace(parent, child);
64 : }
65 :
66 : virtual bool ShouldContinueFromReplyTimeout() override;
67 :
68 : virtual mozilla::ipc::IPCResult RecvSettingChanged(const PluginSettings& aSettings) override;
69 :
70 : // Implement the PPluginModuleChild interface
71 : virtual mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerChild>&& aEndpoint) override;
72 : virtual mozilla::ipc::IPCResult RecvDisableFlashProtectedMode() override;
73 : virtual mozilla::ipc::IPCResult AnswerNP_GetEntryPoints(NPError* rv) override;
74 : virtual mozilla::ipc::IPCResult AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv) override;
75 : virtual mozilla::ipc::IPCResult AnswerSyncNPP_New(PPluginInstanceChild* aActor, NPError* rv)
76 : override;
77 :
78 : virtual mozilla::ipc::IPCResult
79 : RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& endpoint) override;
80 :
81 : virtual PPluginInstanceChild*
82 : AllocPPluginInstanceChild(const nsCString& aMimeType,
83 : const InfallibleTArray<nsCString>& aNames,
84 : const InfallibleTArray<nsCString>& aValues)
85 : override;
86 :
87 : virtual bool
88 : DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) override;
89 :
90 : virtual mozilla::ipc::IPCResult
91 : RecvPPluginInstanceConstructor(PPluginInstanceChild* aActor,
92 : const nsCString& aMimeType,
93 : InfallibleTArray<nsCString>&& aNames,
94 : InfallibleTArray<nsCString>&& aValues)
95 : override;
96 : virtual mozilla::ipc::IPCResult
97 : AnswerNP_Shutdown(NPError *rv) override;
98 :
99 : virtual mozilla::ipc::IPCResult
100 : AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
101 : bool *aClearSiteData,
102 : bool *aGetSitesWithData) override;
103 :
104 : virtual mozilla::ipc::IPCResult
105 : RecvNPP_ClearSiteData(const nsCString& aSite,
106 : const uint64_t& aFlags,
107 : const uint64_t& aMaxAge,
108 : const uint64_t& aCallbackId) override;
109 :
110 : virtual mozilla::ipc::IPCResult
111 : RecvNPP_GetSitesWithData(const uint64_t& aCallbackId) override;
112 :
113 : virtual mozilla::ipc::IPCResult
114 : RecvSetAudioSessionData(const nsID& aId,
115 : const nsString& aDisplayName,
116 : const nsString& aIconPath) override;
117 :
118 : virtual mozilla::ipc::IPCResult
119 : RecvSetParentHangTimeout(const uint32_t& aSeconds) override;
120 :
121 : virtual mozilla::ipc::IPCResult
122 : AnswerInitCrashReporter(Shmem&& aShmem, mozilla::dom::NativeThreadId* aId) override;
123 :
124 : virtual void
125 : ActorDestroy(ActorDestroyReason why) override;
126 :
127 : virtual mozilla::ipc::IPCResult
128 : RecvProcessNativeEventsInInterruptCall() override;
129 :
130 : virtual mozilla::ipc::IPCResult
131 : AnswerModuleSupportsAsyncRender(bool* aResult) override;
132 : public:
133 : explicit PluginModuleChild(bool aIsChrome);
134 : virtual ~PluginModuleChild();
135 :
136 : void CommonInit();
137 :
138 : // aPluginFilename is UTF8, not native-charset!
139 : bool InitForChrome(const std::string& aPluginFilename,
140 : base::ProcessId aParentPid,
141 : MessageLoop* aIOLoop,
142 : IPC::Channel* aChannel);
143 :
144 : bool InitForContent(Endpoint<PPluginModuleChild>&& aEndpoint);
145 :
146 : static bool
147 : CreateForContentProcess(Endpoint<PPluginModuleChild>&& aEndpoint);
148 :
149 : void CleanUp();
150 :
151 : NPError NP_Shutdown();
152 :
153 : const char* GetUserAgent();
154 :
155 : static const NPNetscapeFuncs sBrowserFuncs;
156 :
157 : static PluginModuleChild* GetChrome();
158 :
159 : /**
160 : * The child implementation of NPN_CreateObject.
161 : */
162 : static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
163 : /**
164 : * The child implementation of NPN_RetainObject.
165 : */
166 : static NPObject* NPN_RetainObject(NPObject* aNPObj);
167 : /**
168 : * The child implementation of NPN_ReleaseObject.
169 : */
170 : static void NPN_ReleaseObject(NPObject* aNPObj);
171 :
172 : /**
173 : * The child implementations of NPIdentifier-related functions.
174 : */
175 : static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
176 : static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
177 : int32_t aNameCount,
178 : NPIdentifier* aIdentifiers);
179 : static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
180 : static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
181 : static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
182 : static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
183 :
184 : #ifdef MOZ_WIDGET_COCOA
185 : void ProcessNativeEvents();
186 :
187 : void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
188 : SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width, r.size.height);
189 : }
190 :
191 : void PluginHideWindow(uint32_t window_id) {
192 : SendPluginHideWindow(window_id);
193 : }
194 :
195 : void SetCursor(NSCursorInfo& cursorInfo) {
196 : SendSetCursor(cursorInfo);
197 : }
198 :
199 : void ShowCursor(bool show) {
200 : SendShowCursor(show);
201 : }
202 :
203 : void PushCursor(NSCursorInfo& cursorInfo) {
204 : SendPushCursor(cursorInfo);
205 : }
206 :
207 : void PopCursor() {
208 : SendPopCursor();
209 : }
210 :
211 : bool GetNativeCursorsSupported() {
212 : return Settings().nativeCursorsSupported();
213 : }
214 : #endif
215 :
216 0 : int GetQuirks() { return mQuirks; }
217 :
218 0 : const PluginSettings& Settings() const { return mCachedSettings; }
219 :
220 : NPError PluginRequiresAudioDeviceChanges(PluginInstanceChild* aInstance,
221 : NPBool aShouldRegister);
222 : mozilla::ipc::IPCResult RecvNPP_SetValue_NPNVaudioDeviceChangeDetails(
223 : const NPAudioDeviceChangeDetailsIPC& detailsIPC) override;
224 :
225 : private:
226 : NPError DoNP_Initialize(const PluginSettings& aSettings);
227 0 : void AddQuirk(PluginQuirks quirk) {
228 0 : if (mQuirks == QUIRKS_NOT_INITIALIZED)
229 0 : mQuirks = 0;
230 0 : mQuirks |= quirk;
231 0 : }
232 : void InitQuirksModes(const nsCString& aMimeType);
233 : bool InitGraphics();
234 : void DeinitGraphics();
235 :
236 : #if defined(OS_WIN)
237 : void HookProtectedMode();
238 : #endif
239 :
240 : #if defined(MOZ_WIDGET_GTK)
241 : static gboolean DetectNestedEventLoop(gpointer data);
242 : static gboolean ProcessBrowserEvents(gpointer data);
243 :
244 : virtual void EnteredCxxStack() override;
245 : virtual void ExitedCxxStack() override;
246 : #endif
247 :
248 : PRLibrary* mLibrary;
249 : nsCString mPluginFilename; // UTF8
250 : int mQuirks;
251 :
252 : bool mIsChrome;
253 : bool mHasShutdown; // true if NP_Shutdown has run
254 :
255 : #ifdef MOZ_GECKO_PROFILER
256 : RefPtr<ChildProfilerController> mProfilerController;
257 : #endif
258 :
259 : // we get this from the plugin
260 : NP_PLUGINSHUTDOWN mShutdownFunc;
261 : #if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
262 : NP_PLUGINUNIXINIT mInitializeFunc;
263 : #elif defined(OS_WIN) || defined(OS_MACOSX)
264 : NP_PLUGININIT mInitializeFunc;
265 : NP_GETENTRYPOINTS mGetEntryPointsFunc;
266 : #endif
267 :
268 : NPPluginFuncs mFunctions;
269 :
270 : PluginSettings mCachedSettings;
271 :
272 : #if defined(MOZ_WIDGET_GTK)
273 : // If a plugin spins a nested glib event loop in response to a
274 : // synchronous IPC message from the browser, the loop might break
275 : // only after the browser responds to a request sent by the
276 : // plugin. This can happen if a plugin uses gtk's synchronous
277 : // copy/paste, for example. But because the browser is blocked on
278 : // a condvar, it can't respond to the request. This situation
279 : // isn't technically a deadlock, but the symptoms are basically
280 : // the same from the user's perspective.
281 : //
282 : // We take two steps to prevent this
283 : //
284 : // (1) Detect nested event loops spun by the plugin. This is
285 : // done by scheduling a glib timer event in the plugin
286 : // process whenever the browser might block on the plugin.
287 : // If the plugin indeed spins a nested loop, this timer event
288 : // will fire "soon" thereafter.
289 : //
290 : // (2) When a nested loop is detected, deschedule the
291 : // nested-loop-detection timer and in its place, schedule
292 : // another timer that periodically calls back into the
293 : // browser and spins a mini event loop. This mini event loop
294 : // processes a handful of pending native events.
295 : //
296 : // Because only timer (1) or (2) (or neither) may be active at any
297 : // point in time, we use the same member variable
298 : // |mNestedLoopTimerId| to refer to both.
299 : //
300 : // When the browser no longer might be blocked on a plugin's IPC
301 : // response, we deschedule whichever of (1) or (2) is active.
302 : guint mNestedLoopTimerId;
303 : # ifdef DEBUG
304 : // Depth of the stack of calls to g_main_context_dispatch before any
305 : // nested loops are run. This is 1 when IPC calls are dispatched from
306 : // g_main_context_iteration, or 0 when dispatched directly from
307 : // MessagePumpForUI.
308 : int mTopLoopDepth;
309 : # endif
310 : #endif
311 :
312 : #if defined(XP_WIN)
313 : typedef nsTHashtable<nsPtrHashKey<PluginInstanceChild>> PluginInstanceSet;
314 : // Set of plugins that have registered to be notified when the audio device
315 : // changes.
316 : PluginInstanceSet mAudioNotificationSet;
317 : #endif
318 :
319 : public: // called by PluginInstanceChild
320 : /**
321 : * Dealloc an NPObject after last-release or when the associated instance
322 : * is destroyed. This function will remove the object from mObjectMap.
323 : */
324 : static void DeallocNPObject(NPObject* o);
325 :
326 0 : NPError NPP_Destroy(PluginInstanceChild* instance) {
327 0 : return mFunctions.destroy(instance->GetNPP(), 0);
328 : }
329 :
330 : private:
331 : #if defined(OS_WIN)
332 : virtual void EnteredCall() override;
333 : virtual void ExitedCall() override;
334 :
335 : // Entered/ExitedCall notifications keep track of whether the plugin has
336 : // entered a nested event loop within this interrupt call.
337 : struct IncallFrame
338 : {
339 : IncallFrame()
340 : : _spinning(false)
341 : , _savedNestableTasksAllowed(false)
342 : { }
343 :
344 : bool _spinning;
345 : bool _savedNestableTasksAllowed;
346 : };
347 :
348 : AutoTArray<IncallFrame, 8> mIncallPumpingStack;
349 :
350 : static LRESULT CALLBACK NestedInputEventHook(int code,
351 : WPARAM wParam,
352 : LPARAM lParam);
353 : static LRESULT CALLBACK CallWindowProcHook(int code,
354 : WPARAM wParam,
355 : LPARAM lParam);
356 : void SetEventHooks();
357 : void ResetEventHooks();
358 : HHOOK mNestedEventHook;
359 : HHOOK mGlobalCallWndProcHook;
360 : public:
361 : bool mAsyncRenderSupport;
362 : #endif
363 : };
364 :
365 : } /* namespace plugins */
366 : } /* namespace mozilla */
367 :
368 : #endif // ifndef dom_plugins_PluginModuleChild_h
|