Coverage Report

Created: 2018-09-25 14:53

/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