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