dom/plugins/ipc/PluginModuleChild.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: sw=4 ts=4 et :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef dom_plugins_PluginModuleChild_h
michael@0 8 #define dom_plugins_PluginModuleChild_h 1
michael@0 9
michael@0 10 #include "mozilla/Attributes.h"
michael@0 11
michael@0 12 #include <string>
michael@0 13 #include <vector>
michael@0 14
michael@0 15 #include "base/basictypes.h"
michael@0 16
michael@0 17 #include "prlink.h"
michael@0 18
michael@0 19 #include "npapi.h"
michael@0 20 #include "npfunctions.h"
michael@0 21
michael@0 22 #include "nsAutoPtr.h"
michael@0 23 #include "nsDataHashtable.h"
michael@0 24 #include "nsTHashtable.h"
michael@0 25 #include "nsHashKeys.h"
michael@0 26
michael@0 27 #ifdef MOZ_WIDGET_COCOA
michael@0 28 #include "PluginInterposeOSX.h"
michael@0 29 #endif
michael@0 30
michael@0 31 #include "mozilla/plugins/PPluginModuleChild.h"
michael@0 32 #include "mozilla/plugins/PluginInstanceChild.h"
michael@0 33 #include "mozilla/plugins/PluginIdentifierChild.h"
michael@0 34 #include "mozilla/plugins/PluginMessageUtils.h"
michael@0 35
michael@0 36 // NOTE: stolen from nsNPAPIPlugin.h
michael@0 37
michael@0 38 #if defined(XP_WIN)
michael@0 39 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
michael@0 40 #else
michael@0 41 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
michael@0 42 #endif
michael@0 43
michael@0 44 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
michael@0 45 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
michael@0 46 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
michael@0 47 typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
michael@0 48
michael@0 49 namespace mozilla {
michael@0 50 namespace dom {
michael@0 51 class PCrashReporterChild;
michael@0 52 }
michael@0 53
michael@0 54 namespace plugins {
michael@0 55
michael@0 56 #ifdef MOZ_WIDGET_QT
michael@0 57 class NestedLoopTimer;
michael@0 58 static const int kNestedLoopDetectorIntervalMs = 90;
michael@0 59 #endif
michael@0 60
michael@0 61 class PluginScriptableObjectChild;
michael@0 62 class PluginInstanceChild;
michael@0 63
michael@0 64 class PluginModuleChild : public PPluginModuleChild
michael@0 65 {
michael@0 66 typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
michael@0 67 protected:
michael@0 68 virtual mozilla::ipc::RacyInterruptPolicy
michael@0 69 MediateInterruptRace(const Message& parent, const Message& child) MOZ_OVERRIDE
michael@0 70 {
michael@0 71 return MediateRace(parent, child);
michael@0 72 }
michael@0 73
michael@0 74 virtual bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
michael@0 75
michael@0 76 // Implement the PPluginModuleChild interface
michael@0 77 virtual bool AnswerNP_GetEntryPoints(NPError* rv) MOZ_OVERRIDE;
michael@0 78 virtual bool AnswerNP_Initialize(const uint32_t& aFlags, NPError* rv) MOZ_OVERRIDE;
michael@0 79
michael@0 80 virtual PPluginIdentifierChild*
michael@0 81 AllocPPluginIdentifierChild(const nsCString& aString,
michael@0 82 const int32_t& aInt,
michael@0 83 const bool& aTemporary) MOZ_OVERRIDE;
michael@0 84
michael@0 85 virtual bool
michael@0 86 RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
michael@0 87 const nsCString& aString,
michael@0 88 const int32_t& aInt,
michael@0 89 const bool& aTemporary) MOZ_OVERRIDE;
michael@0 90
michael@0 91 virtual bool
michael@0 92 DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor) MOZ_OVERRIDE;
michael@0 93
michael@0 94 virtual PPluginInstanceChild*
michael@0 95 AllocPPluginInstanceChild(const nsCString& aMimeType,
michael@0 96 const uint16_t& aMode,
michael@0 97 const InfallibleTArray<nsCString>& aNames,
michael@0 98 const InfallibleTArray<nsCString>& aValues,
michael@0 99 NPError* rv) MOZ_OVERRIDE;
michael@0 100
michael@0 101 virtual bool
michael@0 102 DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) MOZ_OVERRIDE;
michael@0 103
michael@0 104 virtual bool
michael@0 105 AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
michael@0 106 const nsCString& aMimeType,
michael@0 107 const uint16_t& aMode,
michael@0 108 const InfallibleTArray<nsCString>& aNames,
michael@0 109 const InfallibleTArray<nsCString>& aValues,
michael@0 110 NPError* rv) MOZ_OVERRIDE;
michael@0 111 virtual bool
michael@0 112 AnswerNP_Shutdown(NPError *rv) MOZ_OVERRIDE;
michael@0 113
michael@0 114 virtual bool
michael@0 115 AnswerOptionalFunctionsSupported(bool *aURLRedirectNotify,
michael@0 116 bool *aClearSiteData,
michael@0 117 bool *aGetSitesWithData) MOZ_OVERRIDE;
michael@0 118
michael@0 119 virtual bool
michael@0 120 AnswerNPP_ClearSiteData(const nsCString& aSite,
michael@0 121 const uint64_t& aFlags,
michael@0 122 const uint64_t& aMaxAge,
michael@0 123 NPError* aResult) MOZ_OVERRIDE;
michael@0 124
michael@0 125 virtual bool
michael@0 126 AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult) MOZ_OVERRIDE;
michael@0 127
michael@0 128 virtual bool
michael@0 129 RecvSetAudioSessionData(const nsID& aId,
michael@0 130 const nsString& aDisplayName,
michael@0 131 const nsString& aIconPath) MOZ_OVERRIDE;
michael@0 132
michael@0 133 virtual bool
michael@0 134 RecvSetParentHangTimeout(const uint32_t& aSeconds) MOZ_OVERRIDE;
michael@0 135
michael@0 136 virtual PCrashReporterChild*
michael@0 137 AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
michael@0 138 uint32_t* processType) MOZ_OVERRIDE;
michael@0 139 virtual bool
michael@0 140 DeallocPCrashReporterChild(PCrashReporterChild* actor) MOZ_OVERRIDE;
michael@0 141 virtual bool
michael@0 142 AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
michael@0 143 mozilla::dom::NativeThreadId* id,
michael@0 144 uint32_t* processType) MOZ_OVERRIDE;
michael@0 145
michael@0 146 virtual void
michael@0 147 ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
michael@0 148
michael@0 149 MOZ_NORETURN void QuickExit();
michael@0 150
michael@0 151 virtual bool
michael@0 152 RecvProcessNativeEventsInInterruptCall() MOZ_OVERRIDE;
michael@0 153
michael@0 154 virtual bool
michael@0 155 AnswerGeckoGetProfile(nsCString* aProfile) MOZ_OVERRIDE;
michael@0 156
michael@0 157 public:
michael@0 158 PluginModuleChild();
michael@0 159 virtual ~PluginModuleChild();
michael@0 160
michael@0 161 // aPluginFilename is UTF8, not native-charset!
michael@0 162 bool Init(const std::string& aPluginFilename,
michael@0 163 base::ProcessHandle aParentProcessHandle,
michael@0 164 MessageLoop* aIOLoop,
michael@0 165 IPC::Channel* aChannel);
michael@0 166
michael@0 167 void CleanUp();
michael@0 168
michael@0 169 const char* GetUserAgent();
michael@0 170
michael@0 171 static const NPNetscapeFuncs sBrowserFuncs;
michael@0 172
michael@0 173 static PluginModuleChild* current();
michael@0 174
michael@0 175 bool RegisterActorForNPObject(NPObject* aObject,
michael@0 176 PluginScriptableObjectChild* aActor);
michael@0 177
michael@0 178 void UnregisterActorForNPObject(NPObject* aObject);
michael@0 179
michael@0 180 PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
michael@0 181
michael@0 182 #ifdef DEBUG
michael@0 183 bool NPObjectIsRegistered(NPObject* aObject);
michael@0 184 #endif
michael@0 185
michael@0 186 bool AsyncDrawingAllowed() { return mAsyncDrawingAllowed; }
michael@0 187
michael@0 188 /**
michael@0 189 * The child implementation of NPN_CreateObject.
michael@0 190 */
michael@0 191 static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
michael@0 192 /**
michael@0 193 * The child implementation of NPN_RetainObject.
michael@0 194 */
michael@0 195 static NPObject* NPN_RetainObject(NPObject* aNPObj);
michael@0 196 /**
michael@0 197 * The child implementation of NPN_ReleaseObject.
michael@0 198 */
michael@0 199 static void NPN_ReleaseObject(NPObject* aNPObj);
michael@0 200
michael@0 201 /**
michael@0 202 * The child implementations of NPIdentifier-related functions.
michael@0 203 */
michael@0 204 static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
michael@0 205 static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
michael@0 206 int32_t aNameCount,
michael@0 207 NPIdentifier* aIdentifiers);
michael@0 208 static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
michael@0 209 static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
michael@0 210 static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
michael@0 211 static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
michael@0 212
michael@0 213 #ifdef MOZ_WIDGET_COCOA
michael@0 214 void ProcessNativeEvents();
michael@0 215
michael@0 216 void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
michael@0 217 SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width, r.size.height);
michael@0 218 }
michael@0 219
michael@0 220 void PluginHideWindow(uint32_t window_id) {
michael@0 221 SendPluginHideWindow(window_id);
michael@0 222 }
michael@0 223
michael@0 224 void SetCursor(NSCursorInfo& cursorInfo) {
michael@0 225 SendSetCursor(cursorInfo);
michael@0 226 }
michael@0 227
michael@0 228 void ShowCursor(bool show) {
michael@0 229 SendShowCursor(show);
michael@0 230 }
michael@0 231
michael@0 232 void PushCursor(NSCursorInfo& cursorInfo) {
michael@0 233 SendPushCursor(cursorInfo);
michael@0 234 }
michael@0 235
michael@0 236 void PopCursor() {
michael@0 237 SendPopCursor();
michael@0 238 }
michael@0 239
michael@0 240 bool GetNativeCursorsSupported() {
michael@0 241 bool supported = false;
michael@0 242 SendGetNativeCursorsSupported(&supported);
michael@0 243 return supported;
michael@0 244 }
michael@0 245 #endif
michael@0 246
michael@0 247 // Quirks mode support for various plugin mime types
michael@0 248 enum PluginQuirks {
michael@0 249 QUIRKS_NOT_INITIALIZED = 0,
michael@0 250 // Silverlight assumes it is transparent in windowless mode. This quirk
michael@0 251 // matches the logic in nsNPAPIPluginInstance::SetWindowless.
michael@0 252 QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT = 1 << 0,
michael@0 253 // Win32: Hook TrackPopupMenu api so that we can swap out parent
michael@0 254 // hwnds. The api will fail with parents not associated with our
michael@0 255 // child ui thread. See WinlessHandleEvent for details.
michael@0 256 QUIRK_WINLESS_TRACKPOPUP_HOOK = 1 << 1,
michael@0 257 // Win32: Throttle flash WM_USER+1 heart beat messages to prevent
michael@0 258 // flooding chromium's dispatch loop, which can cause ipc traffic
michael@0 259 // processing lag.
michael@0 260 QUIRK_FLASH_THROTTLE_WMUSER_EVENTS = 1 << 2,
michael@0 261 // Win32: Catch resets on our subclass by hooking SetWindowLong.
michael@0 262 QUIRK_FLASH_HOOK_SETLONGPTR = 1 << 3,
michael@0 263 // X11: Work around a bug in Flash up to 10.1 d51 at least, where
michael@0 264 // expose event top left coordinates within the plugin-rect and
michael@0 265 // not at the drawable origin are misinterpreted.
michael@0 266 QUIRK_FLASH_EXPOSE_COORD_TRANSLATION = 1 << 4,
michael@0 267 // Win32: Catch get window info calls on the browser and tweak the
michael@0 268 // results so mouse input works when flash is displaying it's settings
michael@0 269 // window.
michael@0 270 QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5,
michael@0 271 // Win: Addresses a flash bug with mouse capture and full screen
michael@0 272 // windows.
michael@0 273 QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 6,
michael@0 274 // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
michael@0 275 // Avoid calling SetWindow in that case.
michael@0 276 QUIRK_QUICKTIME_AVOID_SETWINDOW = 1 << 7,
michael@0 277 // Win: Check to make sure the parent window has focus before calling
michael@0 278 // set focus on the child. Addresses a full screen dialog prompt
michael@0 279 // problem in Silverlight.
michael@0 280 QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT = 1 << 8,
michael@0 281 // Mac: Allow the plugin to use offline renderer mode.
michael@0 282 // Use this only if the plugin is certified the support the offline renderer.
michael@0 283 QUIRK_ALLOW_OFFLINE_RENDERER = 1 << 9,
michael@0 284 // Mac: Work around a Flash bug that can cause plugin process crashes
michael@0 285 // in CoreGraphics mode: The Flash plugin sometimes accesses the
michael@0 286 // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect)
michael@0 287 // outside of that call. See bug 804606.
michael@0 288 QUIRK_FLASH_AVOID_CGMODE_CRASHES = 1 << 10,
michael@0 289 };
michael@0 290
michael@0 291 int GetQuirks() { return mQuirks; }
michael@0 292
michael@0 293 private:
michael@0 294 void AddQuirk(PluginQuirks quirk) {
michael@0 295 if (mQuirks == QUIRKS_NOT_INITIALIZED)
michael@0 296 mQuirks = 0;
michael@0 297 mQuirks |= quirk;
michael@0 298 }
michael@0 299 void InitQuirksModes(const nsCString& aMimeType);
michael@0 300 bool InitGraphics();
michael@0 301 void DeinitGraphics();
michael@0 302 #if defined(MOZ_WIDGET_GTK)
michael@0 303 static gboolean DetectNestedEventLoop(gpointer data);
michael@0 304 static gboolean ProcessBrowserEvents(gpointer data);
michael@0 305
michael@0 306 virtual void EnteredCxxStack() MOZ_OVERRIDE;
michael@0 307 virtual void ExitedCxxStack() MOZ_OVERRIDE;
michael@0 308 #elif defined(MOZ_WIDGET_QT)
michael@0 309
michael@0 310 virtual void EnteredCxxStack() MOZ_OVERRIDE;
michael@0 311 virtual void ExitedCxxStack() MOZ_OVERRIDE;
michael@0 312 #endif
michael@0 313
michael@0 314 PRLibrary* mLibrary;
michael@0 315 nsCString mPluginFilename; // UTF8
michael@0 316 nsCString mUserAgent;
michael@0 317 int mQuirks;
michael@0 318 bool mAsyncDrawingAllowed;
michael@0 319
michael@0 320 // we get this from the plugin
michael@0 321 NP_PLUGINSHUTDOWN mShutdownFunc;
michael@0 322 #if defined(OS_LINUX) || defined(OS_BSD)
michael@0 323 NP_PLUGINUNIXINIT mInitializeFunc;
michael@0 324 #elif defined(OS_WIN) || defined(OS_MACOSX)
michael@0 325 NP_PLUGININIT mInitializeFunc;
michael@0 326 NP_GETENTRYPOINTS mGetEntryPointsFunc;
michael@0 327 #endif
michael@0 328
michael@0 329 NPPluginFuncs mFunctions;
michael@0 330 NPSavedData mSavedData;
michael@0 331
michael@0 332 #if defined(MOZ_WIDGET_GTK)
michael@0 333 // If a plugin spins a nested glib event loop in response to a
michael@0 334 // synchronous IPC message from the browser, the loop might break
michael@0 335 // only after the browser responds to a request sent by the
michael@0 336 // plugin. This can happen if a plugin uses gtk's synchronous
michael@0 337 // copy/paste, for example. But because the browser is blocked on
michael@0 338 // a condvar, it can't respond to the request. This situation
michael@0 339 // isn't technically a deadlock, but the symptoms are basically
michael@0 340 // the same from the user's perspective.
michael@0 341 //
michael@0 342 // We take two steps to prevent this
michael@0 343 //
michael@0 344 // (1) Detect nested event loops spun by the plugin. This is
michael@0 345 // done by scheduling a glib timer event in the plugin
michael@0 346 // process whenever the browser might block on the plugin.
michael@0 347 // If the plugin indeed spins a nested loop, this timer event
michael@0 348 // will fire "soon" thereafter.
michael@0 349 //
michael@0 350 // (2) When a nested loop is detected, deschedule the
michael@0 351 // nested-loop-detection timer and in its place, schedule
michael@0 352 // another timer that periodically calls back into the
michael@0 353 // browser and spins a mini event loop. This mini event loop
michael@0 354 // processes a handful of pending native events.
michael@0 355 //
michael@0 356 // Because only timer (1) or (2) (or neither) may be active at any
michael@0 357 // point in time, we use the same member variable
michael@0 358 // |mNestedLoopTimerId| to refer to both.
michael@0 359 //
michael@0 360 // When the browser no longer might be blocked on a plugin's IPC
michael@0 361 // response, we deschedule whichever of (1) or (2) is active.
michael@0 362 guint mNestedLoopTimerId;
michael@0 363 # ifdef DEBUG
michael@0 364 // Depth of the stack of calls to g_main_context_dispatch before any
michael@0 365 // nested loops are run. This is 1 when IPC calls are dispatched from
michael@0 366 // g_main_context_iteration, or 0 when dispatched directly from
michael@0 367 // MessagePumpForUI.
michael@0 368 int mTopLoopDepth;
michael@0 369 # endif
michael@0 370 #elif defined (MOZ_WIDGET_QT)
michael@0 371 NestedLoopTimer *mNestedLoopTimerObject;
michael@0 372 #endif
michael@0 373
michael@0 374 struct NPObjectData : public nsPtrHashKey<NPObject>
michael@0 375 {
michael@0 376 NPObjectData(const NPObject* key)
michael@0 377 : nsPtrHashKey<NPObject>(key)
michael@0 378 , instance(nullptr)
michael@0 379 , actor(nullptr)
michael@0 380 { }
michael@0 381
michael@0 382 // never nullptr
michael@0 383 PluginInstanceChild* instance;
michael@0 384
michael@0 385 // sometimes nullptr (no actor associated with an NPObject)
michael@0 386 PluginScriptableObjectChild* actor;
michael@0 387 };
michael@0 388 /**
michael@0 389 * mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
michael@0 390 * final release/dealloc, whether or not an actor is currently associated with the object.
michael@0 391 */
michael@0 392 nsTHashtable<NPObjectData> mObjectMap;
michael@0 393
michael@0 394 friend class PluginIdentifierChild;
michael@0 395 friend class PluginIdentifierChildString;
michael@0 396 friend class PluginIdentifierChildInt;
michael@0 397 nsDataHashtable<nsCStringHashKey, PluginIdentifierChildString*> mStringIdentifiers;
michael@0 398 nsDataHashtable<nsUint32HashKey, PluginIdentifierChildInt*> mIntIdentifiers;
michael@0 399
michael@0 400 public: // called by PluginInstanceChild
michael@0 401 /**
michael@0 402 * Dealloc an NPObject after last-release or when the associated instance
michael@0 403 * is destroyed. This function will remove the object from mObjectMap.
michael@0 404 */
michael@0 405 static void DeallocNPObject(NPObject* o);
michael@0 406
michael@0 407 NPError NPP_Destroy(PluginInstanceChild* instance) {
michael@0 408 return mFunctions.destroy(instance->GetNPP(), 0);
michael@0 409 }
michael@0 410
michael@0 411 /**
michael@0 412 * Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
michael@0 413 * associated with that instance.
michael@0 414 */
michael@0 415 void FindNPObjectsForInstance(PluginInstanceChild* instance);
michael@0 416
michael@0 417 private:
michael@0 418 static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
michael@0 419
michael@0 420 #if defined(OS_WIN)
michael@0 421 virtual void EnteredCall() MOZ_OVERRIDE;
michael@0 422 virtual void ExitedCall() MOZ_OVERRIDE;
michael@0 423
michael@0 424 // Entered/ExitedCall notifications keep track of whether the plugin has
michael@0 425 // entered a nested event loop within this interrupt call.
michael@0 426 struct IncallFrame
michael@0 427 {
michael@0 428 IncallFrame()
michael@0 429 : _spinning(false)
michael@0 430 , _savedNestableTasksAllowed(false)
michael@0 431 { }
michael@0 432
michael@0 433 bool _spinning;
michael@0 434 bool _savedNestableTasksAllowed;
michael@0 435 };
michael@0 436
michael@0 437 nsAutoTArray<IncallFrame, 8> mIncallPumpingStack;
michael@0 438
michael@0 439 static LRESULT CALLBACK NestedInputEventHook(int code,
michael@0 440 WPARAM wParam,
michael@0 441 LPARAM lParam);
michael@0 442 static LRESULT CALLBACK CallWindowProcHook(int code,
michael@0 443 WPARAM wParam,
michael@0 444 LPARAM lParam);
michael@0 445 void SetEventHooks();
michael@0 446 void ResetEventHooks();
michael@0 447 HHOOK mNestedEventHook;
michael@0 448 HHOOK mGlobalCallWndProcHook;
michael@0 449 #endif
michael@0 450 };
michael@0 451
michael@0 452 } /* namespace plugins */
michael@0 453 } /* namespace mozilla */
michael@0 454
michael@0 455 #endif // ifndef dom_plugins_PluginModuleChild_h

mercurial