Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/plugins/PluginModuleParent.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 mozilla_plugins_PluginModuleParent_h
8
#define mozilla_plugins_PluginModuleParent_h
9
10
#include "base/process.h"
11
#include "mozilla/FileUtils.h"
12
#include "mozilla/HangAnnotations.h"
13
#include "mozilla/PluginLibrary.h"
14
#include "mozilla/plugins/PluginProcessParent.h"
15
#include "mozilla/plugins/PPluginModuleParent.h"
16
#include "mozilla/plugins/PluginMessageUtils.h"
17
#include "mozilla/plugins/PluginTypes.h"
18
#include "mozilla/ipc/TaskFactory.h"
19
#include "mozilla/TimeStamp.h"
20
#include "mozilla/Unused.h"
21
#include "npapi.h"
22
#include "npfunctions.h"
23
#include "nsExceptionHandler.h"
24
#include "nsDataHashtable.h"
25
#include "nsHashKeys.h"
26
#include "nsIObserver.h"
27
#ifdef XP_WIN
28
#include "nsWindowsHelpers.h"
29
#endif
30
31
class nsPluginTag;
32
33
namespace mozilla {
34
35
namespace ipc {
36
class CrashReporterHost;
37
} // namespace ipc
38
namespace layers {
39
class TextureClientRecycleAllocator;
40
} // namespace layers
41
42
namespace plugins {
43
//-----------------------------------------------------------------------------
44
45
class BrowserStreamParent;
46
class PluginInstanceParent;
47
48
#ifdef XP_WIN
49
class PluginHangUIParent;
50
class FunctionBrokerParent;
51
#endif
52
#ifdef MOZ_CRASHREPORTER_INJECTOR
53
class FinishInjectorInitTask;
54
#endif
55
56
/**
57
 * PluginModuleParent
58
 *
59
 * This class implements the NPP API from the perspective of the rest
60
 * of Gecko, forwarding NPP calls along to the child process that is
61
 * actually running the plugin.
62
 *
63
 * This class /also/ implements a version of the NPN API, because the
64
 * child process needs to make these calls back into Gecko proper.
65
 * This class is responsible for "actually" making those function calls.
66
 *
67
 * If a plugin is running, there will always be one PluginModuleParent for it in
68
 * the chrome process. In addition, any content process using the plugin will
69
 * have its own PluginModuleParent. The subclasses PluginModuleChromeParent and
70
 * PluginModuleContentParent implement functionality that is specific to one
71
 * case or the other.
72
 */
73
class PluginModuleParent
74
    : public PPluginModuleParent
75
    , public PluginLibrary
76
#ifdef MOZ_CRASHREPORTER_INJECTOR
77
    , public CrashReporter::InjectorCrashCallback
78
#endif
79
{
80
protected:
81
    typedef mozilla::PluginLibrary PluginLibrary;
82
83
    PPluginInstanceParent*
84
    AllocPPluginInstanceParent(const nsCString& aMimeType,
85
                               const InfallibleTArray<nsCString>& aNames,
86
                               const InfallibleTArray<nsCString>& aValues)
87
                               override;
88
89
    virtual bool
90
    DeallocPPluginInstanceParent(PPluginInstanceParent* aActor) override;
91
92
public:
93
    explicit PluginModuleParent(bool aIsChrome);
94
    virtual ~PluginModuleParent();
95
96
0
    bool IsChrome() const { return mIsChrome; }
97
98
    virtual void SetPlugin(nsNPAPIPlugin* plugin) override
99
0
    {
100
0
        mPlugin = plugin;
101
0
    }
102
103
    virtual void ActorDestroy(ActorDestroyReason why) override;
104
105
0
    const NPNetscapeFuncs* GetNetscapeFuncs() {
106
0
        return mNPNIface;
107
0
    }
108
109
0
    bool OkToCleanup() const {
110
0
        return !IsOnCxxStack();
111
0
    }
112
113
    void ProcessRemoteNativeEventsInInterruptCall() override;
114
115
    virtual nsresult GetRunID(uint32_t* aRunID) override;
116
0
    virtual void SetHasLocalInstance() override {
117
0
        mHadLocalInstance = true;
118
0
    }
119
120
0
    int GetQuirks() { return mQuirks; }
121
122
protected:
123
    virtual mozilla::ipc::RacyInterruptPolicy
124
    MediateInterruptRace(const MessageInfo& parent,
125
                         const MessageInfo& child) override
126
0
    {
127
0
        return MediateRace(parent, child);
128
0
    }
129
130
    virtual mozilla::ipc::IPCResult
131
    RecvBackUpXResources(const FileDescriptor& aXSocketFd) override;
132
133
    virtual mozilla::ipc::IPCResult AnswerProcessSomeEvents() override;
134
135
    virtual mozilla::ipc::IPCResult
136
    RecvProcessNativeEventsInInterruptCall() override;
137
138
    virtual mozilla::ipc::IPCResult
139
    RecvPluginShowWindow(const uint32_t& aWindowId, const bool& aModal,
140
                         const int32_t& aX, const int32_t& aY,
141
                         const size_t& aWidth, const size_t& aHeight) override;
142
143
    virtual mozilla::ipc::IPCResult
144
    RecvPluginHideWindow(const uint32_t& aWindowId) override;
145
146
    virtual mozilla::ipc::IPCResult
147
    RecvSetCursor(const NSCursorInfo& aCursorInfo) override;
148
149
    virtual mozilla::ipc::IPCResult
150
    RecvShowCursor(const bool& aShow) override;
151
152
    virtual mozilla::ipc::IPCResult
153
    RecvPushCursor(const NSCursorInfo& aCursorInfo) override;
154
155
    virtual mozilla::ipc::IPCResult
156
    RecvPopCursor() override;
157
158
    virtual mozilla::ipc::IPCResult
159
    RecvNPN_SetException(const nsCString& aMessage) override;
160
161
    virtual mozilla::ipc::IPCResult
162
    RecvNPN_ReloadPlugins(const bool& aReloadPages) override;
163
164
    static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
165
166
    virtual mozilla::ipc::IPCResult
167
    AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
168
                                        const bool& shouldRegister,
169
                                        NPError* result) override;
170
171
protected:
172
    void SetChildTimeout(const int32_t aChildTimeout);
173
    static void TimeoutChanged(const char* aPref, PluginModuleParent* aModule);
174
175
0
    virtual void UpdatePluginTimeout() {}
176
177
0
    virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override { return IPC_OK(); }
178
179
    virtual mozilla::ipc::IPCResult RecvReturnClearSiteData(const NPError& aRv,
180
                                                            const uint64_t& aCallbackId) override;
181
182
    virtual mozilla::ipc::IPCResult RecvReturnSitesWithData(nsTArray<nsCString>&& aSites,
183
                                                            const uint64_t& aCallbackId) override;
184
185
    void SetPluginFuncs(NPPluginFuncs* aFuncs);
186
187
    nsresult NPP_NewInternal(NPMIMEType pluginType, NPP instance,
188
                             InfallibleTArray<nsCString>& names,
189
                             InfallibleTArray<nsCString>& values,
190
                             NPSavedData* saved, NPError* error);
191
192
    // NPP-like API that Gecko calls are trampolined into.  These
193
    // messages then get forwarded along to the plugin instance,
194
    // and then eventually the child process.
195
196
    static NPError NPP_Destroy(NPP instance, NPSavedData** save);
197
198
    static NPError NPP_SetWindow(NPP instance, NPWindow* window);
199
    static NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
200
                                 NPBool seekable, uint16_t* stype);
201
    static NPError NPP_DestroyStream(NPP instance,
202
                                     NPStream* stream, NPReason reason);
203
    static int32_t NPP_WriteReady(NPP instance, NPStream* stream);
204
    static int32_t NPP_Write(NPP instance, NPStream* stream,
205
                             int32_t offset, int32_t len, void* buffer);
206
    static void NPP_Print(NPP instance, NPPrint* platformPrint);
207
    static int16_t NPP_HandleEvent(NPP instance, void* event);
208
    static void NPP_URLNotify(NPP instance, const char* url,
209
                              NPReason reason, void* notifyData);
210
    static NPError NPP_GetValue(NPP instance,
211
                                NPPVariable variable, void *ret_value);
212
    static NPError NPP_SetValue(NPP instance, NPNVariable variable,
213
                                void *value);
214
    static void NPP_URLRedirectNotify(NPP instance, const char* url,
215
                                      int32_t status, void* notifyData);
216
217
    virtual bool HasRequiredFunctions() override;
218
    virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) override;
219
    virtual nsresult GetImageContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
220
    virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) override;
221
    virtual void DidComposite(NPP aInstance) override;
222
0
    virtual bool IsOOP() override { return true; }
223
    virtual nsresult SetBackgroundUnknown(NPP instance) override;
224
    virtual nsresult BeginUpdateBackground(NPP instance,
225
                                           const nsIntRect& aRect,
226
                                           DrawTarget** aDrawTarget) override;
227
    virtual nsresult EndUpdateBackground(NPP instance,
228
                                         const nsIntRect& aRect) override;
229
230
#if defined(XP_WIN)
231
    virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
232
#endif
233
234
    virtual nsresult HandledWindowedPluginKeyEvent(
235
                       NPP aInstance,
236
                       const mozilla::NativeEventData& aNativeKeyData,
237
                       bool aIsConsumed) override;
238
239
#if defined(XP_UNIX) && !defined(XP_MACOSX)
240
    virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
241
#else
242
    virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
243
#endif
244
    virtual nsresult NP_Shutdown(NPError* error) override;
245
246
    virtual nsresult NP_GetMIMEDescription(const char** mimeDesc) override;
247
    virtual nsresult NP_GetValue(void *future, NPPVariable aVariable,
248
                                 void *aValue, NPError* error) override;
249
#if defined(XP_WIN) || defined(XP_MACOSX)
250
    virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) override;
251
#endif
252
    virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance,
253
                             int16_t argc, char* argn[],
254
                             char* argv[], NPSavedData* saved,
255
                             NPError* error) override;
256
    virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge,
257
                                       nsCOMPtr<nsIClearSiteDataCallback> callback) override;
258
    virtual nsresult NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback) override;
259
260
private:
261
    std::map<uint64_t, nsCOMPtr<nsIClearSiteDataCallback>> mClearSiteDataCallbacks;
262
    std::map<uint64_t, nsCOMPtr<nsIGetSitesWithDataCallback>> mSitesWithDataCallbacks;
263
264
    nsCString mPluginFilename;
265
    int mQuirks;
266
    void InitQuirksModes(const nsCString& aMimeType);
267
268
public:
269
270
#if defined(XP_MACOSX)
271
    virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) override;
272
#endif
273
#if defined(XP_MACOSX) || defined(XP_WIN)
274
    virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) override;
275
#endif
276
277
    layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDirectBitmap();
278
    layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDXGISurface();
279
280
protected:
281
    void NotifyFlashHang();
282
    void NotifyPluginCrashed();
283
    void OnInitFailure();
284
    bool DoShutdown(NPError* error);
285
286
    bool GetSetting(NPNVariable aVariable);
287
    void GetSettings(PluginSettings* aSettings);
288
289
    bool mIsChrome;
290
    bool mShutdown;
291
    bool mHadLocalInstance;
292
    bool mClearSiteDataSupported;
293
    bool mGetSitesWithDataSupported;
294
    NPNetscapeFuncs* mNPNIface;
295
    NPPluginFuncs* mNPPIface;
296
    nsNPAPIPlugin* mPlugin;
297
    ipc::TaskFactory<PluginModuleParent> mTaskFactory;
298
    nsString mHangID;
299
    nsCString mPluginName;
300
    nsCString mPluginVersion;
301
    int32_t mSandboxLevel;
302
    bool mIsFlashPlugin;
303
304
#ifdef MOZ_X11
305
    // Dup of plugin's X socket, used to scope its resources to this
306
    // object instead of the plugin process's lifetime
307
    ScopedClose mPluginXSocketFdDup;
308
#endif
309
310
    bool
311
    GetPluginDetails();
312
313
    uint32_t          mRunID;
314
315
    RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDirectBitmap;
316
    RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface;
317
318
    /**
319
     * This mutex protects the crash reporter when the Plugin Hang UI event
320
     * handler is executing off main thread. It is intended to protect both
321
     * the mCrashReporter variable in addition to the CrashReporterHost object
322
     * that mCrashReporter refers to.
323
     */
324
    mozilla::Mutex mCrashReporterMutex;
325
    UniquePtr<ipc::CrashReporterHost> mCrashReporter;
326
};
327
328
class PluginModuleContentParent : public PluginModuleParent
329
{
330
  public:
331
    explicit PluginModuleContentParent();
332
333
    static PluginLibrary* LoadModule(uint32_t aPluginId, nsPluginTag* aPluginTag);
334
335
    virtual ~PluginModuleContentParent();
336
337
#if defined(XP_WIN) || defined(XP_MACOSX)
338
    nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
339
#endif
340
341
  private:
342
    static void Initialize(Endpoint<PPluginModuleParent>&& aEndpoint);
343
344
    virtual bool ShouldContinueFromReplyTimeout() override;
345
    virtual void OnExitedSyncSend() override;
346
347
#ifdef MOZ_CRASHREPORTER_INJECTOR
348
    void OnCrash(DWORD processID) override {}
349
#endif
350
351
    static PluginModuleContentParent* sSavedModuleParent;
352
353
    uint32_t mPluginId;
354
};
355
356
class PluginModuleChromeParent
357
    : public PluginModuleParent
358
    , public mozilla::BackgroundHangAnnotator
359
{
360
    friend class mozilla::ipc::CrashReporterHost;
361
  public:
362
    /**
363
     * LoadModule
364
     *
365
     * This may or may not launch a plugin child process,
366
     * and may or may not be very expensive.
367
     */
368
    static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId,
369
                                     nsPluginTag* aPluginTag);
370
371
    virtual ~PluginModuleChromeParent();
372
373
    /*
374
     * Takes a full multi-process dump including the plugin process and the
375
     * content process. If aBrowserDumpId is not empty then the browser dump
376
     * associated with it will be paired to the resulting minidump.
377
     * Takes ownership of the file associated with aBrowserDumpId.
378
     *
379
     * @param aContentPid PID of the e10s content process from which a hang was
380
     *   reported. May be kInvalidProcessId if not applicable.
381
     * @param aBrowserDumpId (optional) previously taken browser dump id. If
382
     *   provided TakeFullMinidump will use this dump file instead of
383
     *   generating a new one. If not provided a browser dump will be taken at
384
     *   the time of this call.
385
     * @param aDumpId Returns the ID of the newly generated crash dump. Left
386
     *   untouched upon failure.
387
     */
388
    void TakeFullMinidump(base::ProcessId aContentPid,
389
                          const nsAString& aBrowserDumpId,
390
                          nsString& aDumpId);
391
392
    /*
393
     * Terminates the plugin process associated with this plugin module. Also
394
     * generates appropriate crash reports unless an existing one is provided.
395
     * Takes ownership of the file associated with aDumpId on success.
396
     *
397
     * @param aMsgLoop the main message pump associated with the module
398
     *   protocol.
399
     * @param aContentPid PID of the e10s content process from which a hang was
400
     *   reported. May be kInvalidProcessId if not applicable.
401
     * @param aMonitorDescription a string describing the hang monitor that
402
     *   is making this call. This string is added to the crash reporter
403
     *   annotations for the plugin process.
404
     * @param aDumpId (optional) previously taken dump id. If provided
405
     *   TerminateChildProcess will use this dump file instead of generating a
406
     *   multi-process crash report. If not provided a multi-process dump will
407
     *   be taken at the time of this call.
408
     */
409
    void TerminateChildProcess(MessageLoop* aMsgLoop,
410
                               base::ProcessId aContentPid,
411
                               const nsCString& aMonitorDescription,
412
                               const nsAString& aDumpId);
413
414
#ifdef XP_WIN
415
    /**
416
     * Called by Plugin Hang UI to notify that the user has clicked continue.
417
     * Used for chrome hang annotations.
418
     */
419
    void
420
    OnHangUIContinue();
421
422
    void
423
    EvaluateHangUIState(const bool aReset);
424
#endif // XP_WIN
425
426
    void CachedSettingChanged();
427
428
private:
429
    virtual void
430
    EnteredCxxStack() override;
431
432
    void
433
    ExitedCxxStack() override;
434
435
    mozilla::ipc::IProtocol* GetInvokingProtocol();
436
    PluginInstanceParent* GetManagingInstance(mozilla::ipc::IProtocol* aProtocol);
437
438
    virtual void
439
    AnnotateHang(mozilla::BackgroundHangAnnotations& aAnnotations) override;
440
441
    virtual bool ShouldContinueFromReplyTimeout() override;
442
443
    void ProcessFirstMinidump();
444
    void WriteExtraDataForMinidump();
445
446
0
    PluginProcessParent* Process() const { return mSubprocess; }
447
0
    base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
448
449
#if defined(XP_UNIX) && !defined(XP_MACOSX)
450
    virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
451
#else
452
    virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
453
#endif
454
455
#if defined(XP_WIN) || defined(XP_MACOSX)
456
    virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) override;
457
#endif
458
459
    virtual void ActorDestroy(ActorDestroyReason why) override;
460
461
    // aFilePath is UTF8, not native!
462
    explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId,
463
                                      int32_t aSandboxLevel);
464
465
    void CleanupFromTimeout(const bool aByHangUI);
466
467
    virtual void UpdatePluginTimeout() override;
468
469
    void RegisterSettingsCallbacks();
470
    void UnregisterSettingsCallbacks();
471
472
    bool InitCrashReporter();
473
474
    virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override;
475
476
    static void CachedSettingChanged(const char* aPref, PluginModuleChromeParent* aModule);
477
478
    virtual mozilla::ipc::IPCResult
479
    AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
480
                                        const bool& shouldRegister,
481
                                        NPError* result) override;
482
483
    PluginProcessParent* mSubprocess;
484
    uint32_t mPluginId;
485
486
    ipc::TaskFactory<PluginModuleChromeParent> mChromeTaskFactory;
487
488
    enum HangAnnotationFlags
489
    {
490
        kInPluginCall = (1u << 0),
491
        kHangUIShown = (1u << 1),
492
        kHangUIContinued = (1u << 2),
493
        kHangUIDontShow = (1u << 3)
494
    };
495
    Atomic<uint32_t> mHangAnnotationFlags;
496
#ifdef XP_WIN
497
    InfallibleTArray<float> mPluginCpuUsageOnHang;
498
    PluginHangUIParent *mHangUIParent;
499
    bool mHangUIEnabled;
500
    bool mIsTimerReset;
501
502
    /**
503
     * Launches the Plugin Hang UI.
504
     *
505
     * @return true if plugin-hang-ui.exe has been successfully launched.
506
     *         false if the Plugin Hang UI is disabled, already showing,
507
     *               or the launch failed.
508
     */
509
    bool
510
    LaunchHangUI();
511
512
    /**
513
     * Finishes the Plugin Hang UI and cancels if it is being shown to the user.
514
     */
515
    void
516
    FinishHangUI();
517
518
    FunctionBrokerParent* mBrokerParent;
519
#endif
520
521
#ifdef MOZ_CRASHREPORTER_INJECTOR
522
    friend class mozilla::plugins::FinishInjectorInitTask;
523
524
    void InitializeInjector();
525
    void DoInjection(const nsAutoHandle& aSnapshot);
526
    static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext);
527
528
    void OnCrash(DWORD processID) override;
529
530
    DWORD mFlashProcess1;
531
    DWORD mFlashProcess2;
532
    RefPtr<mozilla::plugins::FinishInjectorInitTask> mFinishInitTask;
533
#endif
534
535
    void OnProcessLaunched(const bool aSucceeded);
536
537
    class LaunchedTask : public LaunchCompleteTask
538
    {
539
    public:
540
        explicit LaunchedTask(PluginModuleChromeParent* aModule)
541
            : mModule(aModule)
542
0
        {
543
0
            MOZ_ASSERT(aModule);
544
0
        }
545
546
        NS_IMETHOD Run() override
547
0
        {
548
0
            mModule->OnProcessLaunched(mLaunchSucceeded);
549
0
            return NS_OK;
550
0
        }
551
552
    private:
553
        PluginModuleChromeParent* mModule;
554
    };
555
556
    friend class LaunchedTask;
557
558
    nsCOMPtr<nsIObserver> mPluginOfflineObserver;
559
    bool mIsBlocklisted;
560
    bool mIsCleaningFromTimeout;
561
};
562
563
} // namespace plugins
564
} // namespace mozilla
565
566
#endif // mozilla_plugins_PluginModuleParent_h