dom/plugins/ipc/PluginModuleChild.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/plugins/ipc/PluginModuleChild.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,455 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: sw=4 ts=4 et :
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef dom_plugins_PluginModuleChild_h
    1.11 +#define dom_plugins_PluginModuleChild_h 1
    1.12 +
    1.13 +#include "mozilla/Attributes.h"
    1.14 +
    1.15 +#include <string>
    1.16 +#include <vector>
    1.17 +
    1.18 +#include "base/basictypes.h"
    1.19 +
    1.20 +#include "prlink.h"
    1.21 +
    1.22 +#include "npapi.h"
    1.23 +#include "npfunctions.h"
    1.24 +
    1.25 +#include "nsAutoPtr.h"
    1.26 +#include "nsDataHashtable.h"
    1.27 +#include "nsTHashtable.h"
    1.28 +#include "nsHashKeys.h"
    1.29 +
    1.30 +#ifdef MOZ_WIDGET_COCOA
    1.31 +#include "PluginInterposeOSX.h"
    1.32 +#endif
    1.33 +
    1.34 +#include "mozilla/plugins/PPluginModuleChild.h"
    1.35 +#include "mozilla/plugins/PluginInstanceChild.h"
    1.36 +#include "mozilla/plugins/PluginIdentifierChild.h"
    1.37 +#include "mozilla/plugins/PluginMessageUtils.h"
    1.38 +
    1.39 +// NOTE: stolen from nsNPAPIPlugin.h
    1.40 +
    1.41 +#if defined(XP_WIN)
    1.42 +#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
    1.43 +#else
    1.44 +#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
    1.45 +#endif
    1.46 +
    1.47 +typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
    1.48 +typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
    1.49 +typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
    1.50 +typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
    1.51 +
    1.52 +namespace mozilla {
    1.53 +namespace dom {
    1.54 +class PCrashReporterChild;
    1.55 +}
    1.56 +
    1.57 +namespace plugins {
    1.58 +
    1.59 +#ifdef MOZ_WIDGET_QT
    1.60 +class NestedLoopTimer;
    1.61 +static const int kNestedLoopDetectorIntervalMs = 90;
    1.62 +#endif
    1.63 +
    1.64 +class PluginScriptableObjectChild;
    1.65 +class PluginInstanceChild;
    1.66 +
    1.67 +class PluginModuleChild : public PPluginModuleChild
    1.68 +{
    1.69 +    typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
    1.70 +protected:
    1.71 +    virtual mozilla::ipc::RacyInterruptPolicy
    1.72 +    MediateInterruptRace(const Message& parent, const Message& child) MOZ_OVERRIDE
    1.73 +    {
    1.74 +        return MediateRace(parent, child);
    1.75 +    }
    1.76 +
    1.77 +    virtual bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
    1.78 +
    1.79 +    // Implement the PPluginModuleChild interface
    1.80 +    virtual bool AnswerNP_GetEntryPoints(NPError* rv) MOZ_OVERRIDE;
    1.81 +    virtual bool AnswerNP_Initialize(const uint32_t& aFlags, NPError* rv) MOZ_OVERRIDE;
    1.82 +
    1.83 +    virtual PPluginIdentifierChild*
    1.84 +    AllocPPluginIdentifierChild(const nsCString& aString,
    1.85 +                                const int32_t& aInt,
    1.86 +                                const bool& aTemporary) MOZ_OVERRIDE;
    1.87 +
    1.88 +    virtual bool
    1.89 +    RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
    1.90 +                                     const nsCString& aString,
    1.91 +                                     const int32_t& aInt,
    1.92 +                                     const bool& aTemporary) MOZ_OVERRIDE;
    1.93 +
    1.94 +    virtual bool
    1.95 +    DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor) MOZ_OVERRIDE;
    1.96 +
    1.97 +    virtual PPluginInstanceChild*
    1.98 +    AllocPPluginInstanceChild(const nsCString& aMimeType,
    1.99 +                              const uint16_t& aMode,
   1.100 +                              const InfallibleTArray<nsCString>& aNames,
   1.101 +                              const InfallibleTArray<nsCString>& aValues,
   1.102 +                              NPError* rv) MOZ_OVERRIDE;
   1.103 +
   1.104 +    virtual bool
   1.105 +    DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) MOZ_OVERRIDE;
   1.106 +
   1.107 +    virtual bool
   1.108 +    AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
   1.109 +                                     const nsCString& aMimeType,
   1.110 +                                     const uint16_t& aMode,
   1.111 +                                     const InfallibleTArray<nsCString>& aNames,
   1.112 +                                     const InfallibleTArray<nsCString>& aValues,
   1.113 +                                     NPError* rv) MOZ_OVERRIDE;
   1.114 +    virtual bool
   1.115 +    AnswerNP_Shutdown(NPError *rv) MOZ_OVERRIDE;
   1.116 +
   1.117 +    virtual bool
   1.118 +    AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
   1.119 +                                     bool *aClearSiteData,
   1.120 +                                     bool *aGetSitesWithData) MOZ_OVERRIDE;
   1.121 +
   1.122 +    virtual bool
   1.123 +    AnswerNPP_ClearSiteData(const nsCString& aSite,
   1.124 +                            const uint64_t& aFlags,
   1.125 +                            const uint64_t& aMaxAge,
   1.126 +                            NPError* aResult) MOZ_OVERRIDE;
   1.127 +
   1.128 +    virtual bool
   1.129 +    AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult) MOZ_OVERRIDE;
   1.130 +
   1.131 +    virtual bool
   1.132 +    RecvSetAudioSessionData(const nsID& aId,
   1.133 +                            const nsString& aDisplayName,
   1.134 +                            const nsString& aIconPath) MOZ_OVERRIDE;
   1.135 +
   1.136 +    virtual bool
   1.137 +    RecvSetParentHangTimeout(const uint32_t& aSeconds) MOZ_OVERRIDE;
   1.138 +
   1.139 +    virtual PCrashReporterChild*
   1.140 +    AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
   1.141 +                             uint32_t* processType) MOZ_OVERRIDE;
   1.142 +    virtual bool
   1.143 +    DeallocPCrashReporterChild(PCrashReporterChild* actor) MOZ_OVERRIDE;
   1.144 +    virtual bool
   1.145 +    AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
   1.146 +                                    mozilla::dom::NativeThreadId* id,
   1.147 +                                    uint32_t* processType) MOZ_OVERRIDE;
   1.148 +
   1.149 +    virtual void
   1.150 +    ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
   1.151 +
   1.152 +    MOZ_NORETURN void QuickExit();
   1.153 +
   1.154 +    virtual bool
   1.155 +    RecvProcessNativeEventsInInterruptCall() MOZ_OVERRIDE;
   1.156 +
   1.157 +    virtual bool
   1.158 +    AnswerGeckoGetProfile(nsCString* aProfile) MOZ_OVERRIDE;
   1.159 +
   1.160 +public:
   1.161 +    PluginModuleChild();
   1.162 +    virtual ~PluginModuleChild();
   1.163 +
   1.164 +    // aPluginFilename is UTF8, not native-charset!
   1.165 +    bool Init(const std::string& aPluginFilename,
   1.166 +              base::ProcessHandle aParentProcessHandle,
   1.167 +              MessageLoop* aIOLoop,
   1.168 +              IPC::Channel* aChannel);
   1.169 +
   1.170 +    void CleanUp();
   1.171 +
   1.172 +    const char* GetUserAgent();
   1.173 +
   1.174 +    static const NPNetscapeFuncs sBrowserFuncs;
   1.175 +
   1.176 +    static PluginModuleChild* current();
   1.177 +
   1.178 +    bool RegisterActorForNPObject(NPObject* aObject,
   1.179 +                                  PluginScriptableObjectChild* aActor);
   1.180 +
   1.181 +    void UnregisterActorForNPObject(NPObject* aObject);
   1.182 +
   1.183 +    PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
   1.184 +
   1.185 +#ifdef DEBUG
   1.186 +    bool NPObjectIsRegistered(NPObject* aObject);
   1.187 +#endif
   1.188 +
   1.189 +    bool AsyncDrawingAllowed() { return mAsyncDrawingAllowed; }
   1.190 +
   1.191 +    /**
   1.192 +     * The child implementation of NPN_CreateObject.
   1.193 +     */
   1.194 +    static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
   1.195 +    /**
   1.196 +     * The child implementation of NPN_RetainObject.
   1.197 +     */
   1.198 +    static NPObject* NPN_RetainObject(NPObject* aNPObj);
   1.199 +    /**
   1.200 +     * The child implementation of NPN_ReleaseObject.
   1.201 +     */
   1.202 +    static void NPN_ReleaseObject(NPObject* aNPObj);
   1.203 +
   1.204 +    /**
   1.205 +     * The child implementations of NPIdentifier-related functions.
   1.206 +     */
   1.207 +    static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
   1.208 +    static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
   1.209 +                                                     int32_t aNameCount,
   1.210 +                                                     NPIdentifier* aIdentifiers);
   1.211 +    static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
   1.212 +    static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
   1.213 +    static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
   1.214 +    static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
   1.215 +
   1.216 +#ifdef MOZ_WIDGET_COCOA
   1.217 +    void ProcessNativeEvents();
   1.218 +    
   1.219 +    void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
   1.220 +        SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width, r.size.height);
   1.221 +    }
   1.222 +
   1.223 +    void PluginHideWindow(uint32_t window_id) {
   1.224 +        SendPluginHideWindow(window_id);
   1.225 +    }
   1.226 +
   1.227 +    void SetCursor(NSCursorInfo& cursorInfo) {
   1.228 +        SendSetCursor(cursorInfo);
   1.229 +    }
   1.230 +
   1.231 +    void ShowCursor(bool show) {
   1.232 +        SendShowCursor(show);
   1.233 +    }
   1.234 +
   1.235 +    void PushCursor(NSCursorInfo& cursorInfo) {
   1.236 +        SendPushCursor(cursorInfo);
   1.237 +    }
   1.238 +
   1.239 +    void PopCursor() {
   1.240 +        SendPopCursor();
   1.241 +    }
   1.242 +
   1.243 +    bool GetNativeCursorsSupported() {
   1.244 +        bool supported = false;
   1.245 +        SendGetNativeCursorsSupported(&supported);
   1.246 +        return supported;
   1.247 +    }
   1.248 +#endif
   1.249 +
   1.250 +    // Quirks mode support for various plugin mime types
   1.251 +    enum PluginQuirks {
   1.252 +        QUIRKS_NOT_INITIALIZED                          = 0,
   1.253 +        // Silverlight assumes it is transparent in windowless mode. This quirk
   1.254 +        // matches the logic in nsNPAPIPluginInstance::SetWindowless.
   1.255 +        QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT           = 1 << 0,
   1.256 +        // Win32: Hook TrackPopupMenu api so that we can swap out parent
   1.257 +        // hwnds. The api will fail with parents not associated with our
   1.258 +        // child ui thread. See WinlessHandleEvent for details.
   1.259 +        QUIRK_WINLESS_TRACKPOPUP_HOOK                   = 1 << 1,
   1.260 +        // Win32: Throttle flash WM_USER+1 heart beat messages to prevent
   1.261 +        // flooding chromium's dispatch loop, which can cause ipc traffic
   1.262 +        // processing lag.
   1.263 +        QUIRK_FLASH_THROTTLE_WMUSER_EVENTS              = 1 << 2,
   1.264 +        // Win32: Catch resets on our subclass by hooking SetWindowLong.
   1.265 +        QUIRK_FLASH_HOOK_SETLONGPTR                     = 1 << 3,
   1.266 +        // X11: Work around a bug in Flash up to 10.1 d51 at least, where
   1.267 +        // expose event top left coordinates within the plugin-rect and
   1.268 +        // not at the drawable origin are misinterpreted.
   1.269 +        QUIRK_FLASH_EXPOSE_COORD_TRANSLATION            = 1 << 4,
   1.270 +        // Win32: Catch get window info calls on the browser and tweak the
   1.271 +        // results so mouse input works when flash is displaying it's settings
   1.272 +        // window.
   1.273 +        QUIRK_FLASH_HOOK_GETWINDOWINFO                  = 1 << 5,
   1.274 +        // Win: Addresses a flash bug with mouse capture and full screen
   1.275 +        // windows.
   1.276 +        QUIRK_FLASH_FIXUP_MOUSE_CAPTURE                 = 1 << 6,
   1.277 +        // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
   1.278 +        // Avoid calling SetWindow in that case.
   1.279 +        QUIRK_QUICKTIME_AVOID_SETWINDOW                 = 1 << 7,
   1.280 +        // Win: Check to make sure the parent window has focus before calling
   1.281 +        // set focus on the child. Addresses a full screen dialog prompt
   1.282 +        // problem in Silverlight.
   1.283 +        QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT            = 1 << 8,
   1.284 +        // Mac: Allow the plugin to use offline renderer mode.
   1.285 +        // Use this only if the plugin is certified the support the offline renderer.
   1.286 +        QUIRK_ALLOW_OFFLINE_RENDERER                    = 1 << 9,
   1.287 +        // Mac: Work around a Flash bug that can cause plugin process crashes
   1.288 +        // in CoreGraphics mode:  The Flash plugin sometimes accesses the
   1.289 +        // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect)
   1.290 +        // outside of that call.  See bug 804606.
   1.291 +        QUIRK_FLASH_AVOID_CGMODE_CRASHES                = 1 << 10,
   1.292 +    };
   1.293 +
   1.294 +    int GetQuirks() { return mQuirks; }
   1.295 +
   1.296 +private:
   1.297 +    void AddQuirk(PluginQuirks quirk) {
   1.298 +      if (mQuirks == QUIRKS_NOT_INITIALIZED)
   1.299 +        mQuirks = 0;
   1.300 +      mQuirks |= quirk;
   1.301 +    }
   1.302 +    void InitQuirksModes(const nsCString& aMimeType);
   1.303 +    bool InitGraphics();
   1.304 +    void DeinitGraphics();
   1.305 +#if defined(MOZ_WIDGET_GTK)
   1.306 +    static gboolean DetectNestedEventLoop(gpointer data);
   1.307 +    static gboolean ProcessBrowserEvents(gpointer data);
   1.308 +
   1.309 +    virtual void EnteredCxxStack() MOZ_OVERRIDE;
   1.310 +    virtual void ExitedCxxStack() MOZ_OVERRIDE;
   1.311 +#elif defined(MOZ_WIDGET_QT)
   1.312 +
   1.313 +    virtual void EnteredCxxStack() MOZ_OVERRIDE;
   1.314 +    virtual void ExitedCxxStack() MOZ_OVERRIDE;
   1.315 +#endif
   1.316 +
   1.317 +    PRLibrary* mLibrary;
   1.318 +    nsCString mPluginFilename; // UTF8
   1.319 +    nsCString mUserAgent;
   1.320 +    int mQuirks;
   1.321 +    bool mAsyncDrawingAllowed;
   1.322 +
   1.323 +    // we get this from the plugin
   1.324 +    NP_PLUGINSHUTDOWN mShutdownFunc;
   1.325 +#if defined(OS_LINUX) || defined(OS_BSD)
   1.326 +    NP_PLUGINUNIXINIT mInitializeFunc;
   1.327 +#elif defined(OS_WIN) || defined(OS_MACOSX)
   1.328 +    NP_PLUGININIT mInitializeFunc;
   1.329 +    NP_GETENTRYPOINTS mGetEntryPointsFunc;
   1.330 +#endif
   1.331 +
   1.332 +    NPPluginFuncs mFunctions;
   1.333 +    NPSavedData mSavedData;
   1.334 +
   1.335 +#if defined(MOZ_WIDGET_GTK)
   1.336 +    // If a plugin spins a nested glib event loop in response to a
   1.337 +    // synchronous IPC message from the browser, the loop might break
   1.338 +    // only after the browser responds to a request sent by the
   1.339 +    // plugin.  This can happen if a plugin uses gtk's synchronous
   1.340 +    // copy/paste, for example.  But because the browser is blocked on
   1.341 +    // a condvar, it can't respond to the request.  This situation
   1.342 +    // isn't technically a deadlock, but the symptoms are basically
   1.343 +    // the same from the user's perspective.
   1.344 +    //
   1.345 +    // We take two steps to prevent this
   1.346 +    //
   1.347 +    //  (1) Detect nested event loops spun by the plugin.  This is
   1.348 +    //      done by scheduling a glib timer event in the plugin
   1.349 +    //      process whenever the browser might block on the plugin.
   1.350 +    //      If the plugin indeed spins a nested loop, this timer event
   1.351 +    //      will fire "soon" thereafter.
   1.352 +    //
   1.353 +    //  (2) When a nested loop is detected, deschedule the
   1.354 +    //      nested-loop-detection timer and in its place, schedule
   1.355 +    //      another timer that periodically calls back into the
   1.356 +    //      browser and spins a mini event loop.  This mini event loop
   1.357 +    //      processes a handful of pending native events.
   1.358 +    //
   1.359 +    // Because only timer (1) or (2) (or neither) may be active at any
   1.360 +    // point in time, we use the same member variable
   1.361 +    // |mNestedLoopTimerId| to refer to both.
   1.362 +    //
   1.363 +    // When the browser no longer might be blocked on a plugin's IPC
   1.364 +    // response, we deschedule whichever of (1) or (2) is active.
   1.365 +    guint mNestedLoopTimerId;
   1.366 +#  ifdef DEBUG
   1.367 +    // Depth of the stack of calls to g_main_context_dispatch before any
   1.368 +    // nested loops are run.  This is 1 when IPC calls are dispatched from
   1.369 +    // g_main_context_iteration, or 0 when dispatched directly from
   1.370 +    // MessagePumpForUI.
   1.371 +    int mTopLoopDepth;
   1.372 +#  endif
   1.373 +#elif defined (MOZ_WIDGET_QT)
   1.374 +    NestedLoopTimer *mNestedLoopTimerObject;
   1.375 +#endif
   1.376 +
   1.377 +    struct NPObjectData : public nsPtrHashKey<NPObject>
   1.378 +    {
   1.379 +        NPObjectData(const NPObject* key)
   1.380 +            : nsPtrHashKey<NPObject>(key)
   1.381 +            , instance(nullptr)
   1.382 +            , actor(nullptr)
   1.383 +        { }
   1.384 +
   1.385 +        // never nullptr
   1.386 +        PluginInstanceChild* instance;
   1.387 +
   1.388 +        // sometimes nullptr (no actor associated with an NPObject)
   1.389 +        PluginScriptableObjectChild* actor;
   1.390 +    };
   1.391 +    /**
   1.392 +     * mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
   1.393 +     * final release/dealloc, whether or not an actor is currently associated with the object.
   1.394 +     */
   1.395 +    nsTHashtable<NPObjectData> mObjectMap;
   1.396 +
   1.397 +    friend class PluginIdentifierChild;
   1.398 +    friend class PluginIdentifierChildString;
   1.399 +    friend class PluginIdentifierChildInt;
   1.400 +    nsDataHashtable<nsCStringHashKey, PluginIdentifierChildString*> mStringIdentifiers;
   1.401 +    nsDataHashtable<nsUint32HashKey, PluginIdentifierChildInt*> mIntIdentifiers;
   1.402 +
   1.403 +public: // called by PluginInstanceChild
   1.404 +    /**
   1.405 +     * Dealloc an NPObject after last-release or when the associated instance
   1.406 +     * is destroyed. This function will remove the object from mObjectMap.
   1.407 +     */
   1.408 +    static void DeallocNPObject(NPObject* o);
   1.409 +
   1.410 +    NPError NPP_Destroy(PluginInstanceChild* instance) {
   1.411 +        return mFunctions.destroy(instance->GetNPP(), 0);
   1.412 +    }
   1.413 +
   1.414 +    /**
   1.415 +     * Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
   1.416 +     * associated with that instance.
   1.417 +     */
   1.418 +    void FindNPObjectsForInstance(PluginInstanceChild* instance);
   1.419 +
   1.420 +private:
   1.421 +    static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
   1.422 +
   1.423 +#if defined(OS_WIN)
   1.424 +    virtual void EnteredCall() MOZ_OVERRIDE;
   1.425 +    virtual void ExitedCall() MOZ_OVERRIDE;
   1.426 +
   1.427 +    // Entered/ExitedCall notifications keep track of whether the plugin has
   1.428 +    // entered a nested event loop within this interrupt call.
   1.429 +    struct IncallFrame
   1.430 +    {
   1.431 +        IncallFrame()
   1.432 +            : _spinning(false)
   1.433 +            , _savedNestableTasksAllowed(false)
   1.434 +        { }
   1.435 +
   1.436 +        bool _spinning;
   1.437 +        bool _savedNestableTasksAllowed;
   1.438 +    };
   1.439 +
   1.440 +    nsAutoTArray<IncallFrame, 8> mIncallPumpingStack;
   1.441 +
   1.442 +    static LRESULT CALLBACK NestedInputEventHook(int code,
   1.443 +                                                 WPARAM wParam,
   1.444 +                                                 LPARAM lParam);
   1.445 +    static LRESULT CALLBACK CallWindowProcHook(int code,
   1.446 +                                               WPARAM wParam,
   1.447 +                                               LPARAM lParam);
   1.448 +    void SetEventHooks();
   1.449 +    void ResetEventHooks();
   1.450 +    HHOOK mNestedEventHook;
   1.451 +    HHOOK mGlobalCallWndProcHook;
   1.452 +#endif
   1.453 +};
   1.454 +
   1.455 +} /* namespace plugins */
   1.456 +} /* namespace mozilla */
   1.457 +
   1.458 +#endif  // ifndef dom_plugins_PluginModuleChild_h

mercurial