Bug 1182411 - Part 1: Make plugin quirks available to the Parent as well as the Child. r=jimm, a=ritu
authorBob Owen <bobowencode@gmail.com>
Wed, 12 Aug 2015 16:00:25 +0100
changeset 288744 224c22ef69a4867255372a50885215463491d569
parent 288743 700a1000830032fd8f324b68200d9cb786ddefb0
child 288745 beac25d81d5627f6d3827f162c911706de03b947
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, ritu
bugs1182411
milestone42.0a2
Bug 1182411 - Part 1: Make plugin quirks available to the Parent as well as the Child. r=jimm, a=ritu
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleChild.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
dom/plugins/ipc/PluginQuirks.cpp
dom/plugins/ipc/PluginQuirks.h
dom/plugins/ipc/moz.build
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -192,27 +192,27 @@ PluginInstanceChild::PluginInstanceChild
     mWsInfo.display = DefaultXDisplay();
 #endif
 #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
 #if defined(OS_WIN)
     memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
 #endif // OS_WIN
 #if defined(OS_WIN)
     InitPopupMenuHook();
-    if (GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) {
+    if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) {
         SetUnityHooks();
     }
 #endif // OS_WIN
 }
 
 PluginInstanceChild::~PluginInstanceChild()
 {
 #if defined(OS_WIN)
     NS_ASSERTION(!mPluginWindowHWND, "Destroying PluginInstanceChild without NPP_Destroy?");
-    if (GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) {
+    if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) {
         ClearUnityHooks();
     }
 #endif
 #if defined(MOZ_WIDGET_COCOA)
     if (mShColorSpace) {
         ::CGColorSpaceRelease(mShColorSpace);
     }
     if (mShContext) {
@@ -400,17 +400,17 @@ PluginInstanceChild::NPN_GetValue(NPNVar
     case NPNVdocumentOrigin: {
         nsCString v;
         NPError result;
         if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) {
             return NPERR_GENERIC_ERROR;
         }
         if (result == NPERR_NO_ERROR ||
             (GetQuirks() &
-                PluginModuleChild::QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) {
+                QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) {
             *static_cast<char**>(aValue) = ToNewCString(v);
         }
         return result;
     }
 
     case NPNVWindowNPObject: // Intentional fall-through
     case NPNVPluginElementNPObject: {
         NPObject* object;
@@ -1023,17 +1023,17 @@ PluginInstanceChild::AnswerNPP_HandleEve
                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
                                   "provide CALayer."));
                 *handled = false;
                 return false;
             }
 
             mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height,
                             mContentsScaleFactor,
-                            GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ?
+                            GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
                             ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
 
             // Flash needs to have the window set again after this step
             if (mPluginIface->setwindow)
                 (void) mPluginIface->setwindow(&mData, &mWindow);
         }
     } else {
         PLUGIN_LOG_DEBUG(("Invalid event type for "
@@ -1249,17 +1249,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
 
     if (mPluginIface->setwindow)
         (void) mPluginIface->setwindow(&mData, &mWindow);
 
 #elif defined(OS_WIN)
     switch (aWindow.type) {
       case NPWindowTypeWindow:
       {
-          if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) &&
+          if ((GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) &&
               aWindow.width == 0 &&
               aWindow.height == 0) {
             // Skip SetWindow call for hidden QuickTime plugins
             return true;
           }
 
           MOZ_ASSERT(mPluginWindowHWND,
                      "Child plugin window must exist before call to SetWindow");
@@ -1293,19 +1293,19 @@ PluginInstanceChild::AnswerNPP_SetWindow
               RemoveProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty);
               HookSetWindowLongPtr();
           }
       }
       break;
 
       case NPWindowTypeDrawable:
           mWindow.type = aWindow.type;
-          if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK)
+          if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)
               CreateWinlessPopupSurrogate();
-          if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
+          if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
               SetupFlashMsgThrottle();
           return SharedSurfaceSetWindow(aWindow);
       break;
 
       default:
           NS_NOTREACHED("Bad plugin window type.");
           return false;
       break;
@@ -1549,34 +1549,34 @@ PluginInstanceChild::PluginWindowProcInt
         }
     }
 
     if (message == WM_KILLFOCUS) {
       self->CallPluginFocusChange(false);
     }
 
     if (message == WM_USER+1 &&
-        (self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) {
+        (self->GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) {
         self->FlashThrottleMessage(hWnd, message, wParam, lParam, true);
         return 0;
     }
 
     NS_ASSERTION(self->mPluginWndProc != PluginWindowProc,
       "Self-referential windowproc happened inside our hook proc. "
       "Infinite recursion will happen soon.");
 
     LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
                                  lParam);
 
     // Make sure capture is released by the child on mouse events. Fixes a
     // problem with flash full screen mode mouse input. Appears to be
     // caused by a bug in flash, since we are not setting the capture
     // on the window.
     if (message == WM_LBUTTONDOWN &&
-        self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) {
+        self->GetQuirks() & QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) {
       wchar_t szClass[26];
       HWND hwnd = GetForegroundWindow();
       if (hwnd && GetClassNameW(hwnd, szClass,
                                 sizeof(szClass)/sizeof(char16_t)) &&
           !wcscmp(szClass, kFlashFullscreenClass)) {
         ReleaseCapture();
         SetFocus(hwnd);
       }
@@ -1727,17 +1727,17 @@ PluginInstanceChild::SetWindowLongWHook(
         NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
     }
     return proc;
 }
 
 void
 PluginInstanceChild::HookSetWindowLongPtr()
 {
-    if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_SETLONGPTR))
+    if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR))
         return;
 
     sUser32Intercept.Init("user32.dll");
 #ifdef _WIN64
     if (!sUser32SetWindowLongAHookStub)
         sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
                                  (void**) &sUser32SetWindowLongAHookStub);
     if (!sUser32SetWindowLongWHookStub)
@@ -1814,17 +1814,17 @@ PluginInstanceChild::SetCaptureHook(HWND
         sSetCaptureHookData = new SetCaptureHookData(aHwnd);
     }
     return sUser32SetCaptureHookStub(aHwnd);
 }
 
 void
 PluginInstanceChild::SetUnityHooks()
 {
-    if (!(GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE)) {
+    if (!(GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE)) {
         return;
     }
 
     sUser32Intercept.Init("user32.dll");
     if (!sUser32SetCaptureHookStub) {
         sUser32Intercept.AddHook("SetCapture",
                                  reinterpret_cast<intptr_t>(SetCaptureHook),
                                  (void**) &sUser32SetCaptureHookStub);
@@ -1941,17 +1941,17 @@ PluginInstanceChild::TrackPopupHookProc(
   }
 
   return res;
 }
 
 void
 PluginInstanceChild::InitPopupMenuHook()
 {
-    if (!(GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) ||
+    if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) ||
         sUser32TrackPopupMenuStub)
         return;
 
     // Note, once WindowsDllInterceptor is initialized for a module,
     // it remains initialized for that particular module for it's
     // lifetime. Additional instances are needed if other modules need
     // to be hooked.
     if (!sUser32TrackPopupMenuStub) {
@@ -2003,17 +2003,17 @@ PluginInstanceChild::WinlessHandleEvent(
     // special handling during delivery.
     int16_t handled;
     
     HWND focusHwnd = nullptr;
 
     // TrackPopupMenu will fail if the parent window is not associated with
     // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
     // parent created in the child process.
-    if ((GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default?
+    if ((GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default?
           (event.event == WM_RBUTTONDOWN || // flash
            event.event == WM_RBUTTONUP)) {  // silverlight
       sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND;
       
       // A little trick scrounged from chromium's code - set the focus
       // to our surrogate parent so keyboard nav events go to the menu. 
       focusHwnd = SetFocus(mWinlessPopupSurrogateHWND);
     }
@@ -2395,17 +2395,17 @@ PluginInstanceChild::AnswerSetPluginFocu
 
 #if defined(OS_WIN)
     // Parent is letting us know the dom set focus to the plugin. Note,
     // focus can change during transit in certain edge cases, for example
     // when a button click brings up a full screen window. Since we send
     // this in response to a WM_SETFOCUS event on our parent, the parent
     // should have focus when we receive this. If not, ignore the call.
     if (::GetFocus() == mPluginWindowHWND ||
-        ((GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) &&
+        ((GetQuirks() & QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) &&
          (::GetFocus() != mPluginParentHWND)))
         return true;
     ::SetFocus(mPluginWindowHWND);
     return true;
 #else
     NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!");
     return false;
 #endif
@@ -2820,27 +2820,27 @@ PluginInstanceChild::DoAsyncSetWindow(co
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
 #ifdef XP_MACOSX
     mContentsScaleFactor = aWindow.contentsScaleFactor;
 #endif
 
-    if (GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT)
+    if (GetQuirks() & QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT)
         mIsTransparent = true;
 
     mLayersRendering = true;
     mSurfaceType = aSurfaceType;
     UpdateWindowAttributes(true);
 
 #ifdef XP_WIN
-    if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK)
+    if (GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)
         CreateWinlessPopupSurrogate();
-    if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
+    if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
         SetupFlashMsgThrottle();
 #endif
 
     if (!mAccumulatedInvalidRect.IsEmpty()) {
         AsyncShowPluginFrame();
     }
 }
 
@@ -3022,17 +3022,17 @@ PluginInstanceChild::EnsureCurrentBuffer
     return true;
 #elif defined(XP_MACOSX)
 
     if (!mDoubleBufferCARenderer.HasCALayer()) {
         void *caLayer = nullptr;
         if (mDrawingModel == NPDrawingModelCoreGraphics) {
             if (!mCGLayer) {
                 bool avoidCGCrashes = !nsCocoaFeatures::OnMountainLionOrLater() &&
-                  (GetQuirks() & PluginModuleChild::QUIRK_FLASH_AVOID_CGMODE_CRASHES);
+                  (GetQuirks() & QUIRK_FLASH_AVOID_CGMODE_CRASHES);
                 caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw, this,
                                                                        avoidCGCrashes,
                                                                        mContentsScaleFactor);
 
                 if (!caLayer) {
                     PLUGIN_LOG_DEBUG(("GetCGLayer failed."));
                     return false;
                 }
@@ -3056,17 +3056,17 @@ PluginInstanceChild::EnsureCurrentBuffer
          mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height ||
          mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) {
         mDoubleBufferCARenderer.ClearFrontSurface();
     }
 
     if (!mDoubleBufferCARenderer.HasFrontSurface()) {
         bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface(
                                 mWindow.width, mWindow.height, mContentsScaleFactor,
-                                GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ?
+                                GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ?
                                 ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
         if (!allocSurface) {
             PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface"));
             return false;
         }
 
         if (mPluginIface->setwindow)
             (void) mPluginIface->setwindow(&mData, &mWindow);
@@ -3229,17 +3229,17 @@ void
 PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
                                         gfxASurface* aSurface,
                                         const gfxRGBA& aColor)
 {
     // Render using temporary X surface, with copy to image surface
     nsIntRect plPaintRect(aRect);
     nsRefPtr<gfxASurface> renderSurface = aSurface;
 #ifdef MOZ_X11
-    if (mIsTransparent && (GetQuirks() & PluginModuleChild::QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) {
+    if (mIsTransparent && (GetQuirks() & QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) {
         // Work around a bug in Flash up to 10.1 d51 at least, where expose event
         // top left coordinates within the plugin-rect and not at the drawable
         // origin are misinterpreted.  (We can move the top left coordinate
         // provided it is within the clipRect.), see bug 574583
         plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost());
     }
     if (mHelperSurface) {
         // On X11 we can paint to non Xlib surface only with HelperSurface
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -2106,65 +2106,21 @@ PluginModuleChild::AllocPPluginInstanceC
 
     return new PluginInstanceChild(&mFunctions, aMimeType, aMode, aNames,
                                    aValues);
 }
 
 void
 PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
 {
-    if (mQuirks != QUIRKS_NOT_INITIALIZED)
+    if (mQuirks != QUIRKS_NOT_INITIALIZED) {
       return;
-    mQuirks = 0;
-
-    nsPluginHost::SpecialType specialType = nsPluginHost::GetSpecialType(aMimeType);
-
-    if (specialType == nsPluginHost::eSpecialType_Silverlight) {
-        mQuirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT;
-#ifdef OS_WIN
-        mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
-        mQuirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT;
-#endif
-    }
-
-    if (specialType == nsPluginHost::eSpecialType_Flash) {
-        mQuirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN;
-#ifdef OS_WIN
-        mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
-        mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
-        mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
-        mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
-        mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
-#endif
     }
 
-#ifdef OS_WIN
-    // QuickTime plugin usually loaded with audio/mpeg mimetype
-    NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin");
-    if (FindInReadable(quicktime, mPluginFilename)) {
-        mQuirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
-    }
-#endif
-
-#ifdef XP_MACOSX
-    // Whitelist Flash and Quicktime to support offline renderer
-    NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin");
-    if (specialType == nsPluginHost::eSpecialType_Flash) {
-        mQuirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES;
-        mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
-    } else if (FindInReadable(quicktime, mPluginFilename)) {
-        mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
-    }
-#endif
-
-#ifdef OS_WIN
-    if (specialType == nsPluginHost::eSpecialType_Unity) {
-        mQuirks |= QUIRK_UNITY_FIXUP_MOUSE_CAPTURE;
-    }
-#endif
+    mQuirks = GetQuirksFromMimeTypeAndFilename(aMimeType, mPluginFilename);
 }
 
 bool
 PluginModuleChild::RecvPPluginInstanceConstructor(PPluginInstanceChild* aActor,
                                                   const nsCString& aMimeType,
                                                   const uint16_t& aMode,
                                                   InfallibleTArray<nsCString>&& aNames,
                                                   InfallibleTArray<nsCString>&& aValues)
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -26,16 +26,17 @@
 
 #ifdef MOZ_WIDGET_COCOA
 #include "PluginInterposeOSX.h"
 #endif
 
 #include "mozilla/plugins/PPluginModuleChild.h"
 #include "mozilla/plugins/PluginInstanceChild.h"
 #include "mozilla/plugins/PluginMessageUtils.h"
+#include "mozilla/plugins/PluginQuirks.h"
 
 // NOTE: stolen from nsNPAPIPlugin.h
 
 #if defined(XP_WIN)
 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
 #else
 #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
 #endif
@@ -237,66 +238,16 @@ public:
         SendPopCursor();
     }
 
     bool GetNativeCursorsSupported() {
         return Settings().nativeCursorsSupported();
     }
 #endif
 
-    // Quirks mode support for various plugin mime types
-    enum PluginQuirks {
-        QUIRKS_NOT_INITIALIZED                          = 0,
-        // Silverlight assumes it is transparent in windowless mode. This quirk
-        // matches the logic in nsNPAPIPluginInstance::SetWindowless.
-        QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT           = 1 << 0,
-        // Win32: Hook TrackPopupMenu api so that we can swap out parent
-        // hwnds. The api will fail with parents not associated with our
-        // child ui thread. See WinlessHandleEvent for details.
-        QUIRK_WINLESS_TRACKPOPUP_HOOK                   = 1 << 1,
-        // Win32: Throttle flash WM_USER+1 heart beat messages to prevent
-        // flooding chromium's dispatch loop, which can cause ipc traffic
-        // processing lag.
-        QUIRK_FLASH_THROTTLE_WMUSER_EVENTS              = 1 << 2,
-        // Win32: Catch resets on our subclass by hooking SetWindowLong.
-        QUIRK_FLASH_HOOK_SETLONGPTR                     = 1 << 3,
-        // X11: Work around a bug in Flash up to 10.1 d51 at least, where
-        // expose event top left coordinates within the plugin-rect and
-        // not at the drawable origin are misinterpreted.
-        QUIRK_FLASH_EXPOSE_COORD_TRANSLATION            = 1 << 4,
-        // Win32: Catch get window info calls on the browser and tweak the
-        // results so mouse input works when flash is displaying it's settings
-        // window.
-        QUIRK_FLASH_HOOK_GETWINDOWINFO                  = 1 << 5,
-        // Win: Addresses a flash bug with mouse capture and full screen
-        // windows.
-        QUIRK_FLASH_FIXUP_MOUSE_CAPTURE                 = 1 << 6,
-        // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
-        // Avoid calling SetWindow in that case.
-        QUIRK_QUICKTIME_AVOID_SETWINDOW                 = 1 << 7,
-        // Win: Check to make sure the parent window has focus before calling
-        // set focus on the child. Addresses a full screen dialog prompt
-        // problem in Silverlight.
-        QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT            = 1 << 8,
-        // Mac: Allow the plugin to use offline renderer mode.
-        // Use this only if the plugin is certified the support the offline renderer.
-        QUIRK_ALLOW_OFFLINE_RENDERER                    = 1 << 9,
-        // Mac: Work around a Flash bug that can cause plugin process crashes
-        // in CoreGraphics mode:  The Flash plugin sometimes accesses the
-        // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect)
-        // outside of that call.  See bug 804606.
-        QUIRK_FLASH_AVOID_CGMODE_CRASHES                = 1 << 10,
-        // Work around a Flash bug where it fails to check the error code of a
-        // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference
-        // its char* output.
-        QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN        = 1 << 11,
-        // Win: Addresses a Unity bug with mouse capture.
-        QUIRK_UNITY_FIXUP_MOUSE_CAPTURE                 = 1 << 12,
-    };
-
     int GetQuirks() { return mQuirks; }
 
     const PluginSettings& Settings() const { return mCachedSettings; }
 
 private:
     NPError DoNP_Initialize(const PluginSettings& aSettings);
     void AddQuirk(PluginQuirks quirk) {
       if (mQuirks == QUIRKS_NOT_INITIALIZED)
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/unused.h"
 #include "nsAutoPtr.h"
 #include "nsCRT.h"
 #include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsNPAPIPlugin.h"
 #include "nsPrintfCString.h"
 #include "prsystem.h"
+#include "PluginQuirks.h"
 #include "GeckoProfiler.h"
 #include "nsPluginTags.h"
 #include "nsUnicharUtils.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PluginSurfaceParent.h"
 #include "mozilla/widget/AudioSession.h"
 #include "PluginHangUIParent.h"
@@ -620,17 +621,18 @@ PluginModuleChromeParent::WaitForIPCConn
     process->SetCallRunnableImmediately(true);
     if (!process->WaitUntilConnected()) {
         return false;
     }
     return true;
 }
 
 PluginModuleParent::PluginModuleParent(bool aIsChrome)
-    : mIsChrome(aIsChrome)
+    : mQuirks(QUIRKS_NOT_INITIALIZED)
+    , mIsChrome(aIsChrome)
     , mShutdown(false)
     , mHadLocalInstance(false)
     , mClearSiteDataSupported(false)
     , mGetSitesWithDataSupported(false)
     , mNPNIface(nullptr)
     , mNPPIface(nullptr)
     , mPlugin(nullptr)
     , mTaskFactory(this)
@@ -1338,20 +1340,31 @@ PluginModuleParent::GetPluginDetails()
         return false;
     }
     nsPluginTag* pluginTag = host->TagForPlugin(mPlugin);
     if (!pluginTag) {
         return false;
     }
     mPluginName = pluginTag->Name();
     mPluginVersion = pluginTag->Version();
+    mPluginFilename = pluginTag->FileName();
     mIsFlashPlugin = pluginTag->mIsFlashPlugin;
     return true;
 }
 
+void
+PluginModuleParent::InitQuirksModes(const nsCString& aMimeType)
+{
+    if (mQuirks != QUIRKS_NOT_INITIALIZED) {
+      return;
+    }
+
+    mQuirks = GetQuirksFromMimeTypeAndFilename(aMimeType, mPluginFilename);
+}
+
 #ifdef XP_WIN
 void
 PluginModuleChromeParent::EvaluateHangUIState(const bool aReset)
 {
     int32_t minDispSecs = Preferences::GetInt(kHangUIMinDisplayPref, 10);
     int32_t autoStopSecs = Preferences::GetInt(kChildTimeoutPref, 0);
     int32_t timeoutSecs = 0;
     if (autoStopSecs > 0 && autoStopSecs < minDispSecs) {
@@ -2534,16 +2547,17 @@ PluginModuleParent::NPP_New(NPMIMEType p
             mSurrogateInstances.AppendElement(surrogate);
             *error = NPERR_NO_ERROR;
             return NS_PLUGIN_INIT_PENDING;
         }
     }
 
     if (mPluginName.IsEmpty()) {
         GetPluginDetails();
+        InitQuirksModes(nsDependentCString(pluginType));
         /** mTimeBlocked measures the time that the main thread has been blocked
          *  on plugin module initialization. As implemented, this is the sum of
          *  plugin-container launch + toolhelp32 snapshot + NP_Initialize.
          *  We don't accumulate its value until here because the plugin info
          *  is not available until *after* NP_Initialize.
          */
         Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
                               GetHistogramKey(),
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -132,16 +132,18 @@ public:
         return mPluginName + mPluginVersion;
     }
 
     virtual nsresult GetRunID(uint32_t* aRunID) override;
     virtual void SetHasLocalInstance() override {
         mHadLocalInstance = true;
     }
 
+    int GetQuirks() { return mQuirks; }
+
 protected:
     virtual mozilla::ipc::RacyInterruptPolicy
     MediateInterruptRace(const Message& parent, const Message& child) override
     {
         return MediateRace(parent, child);
     }
 
     virtual bool
@@ -273,16 +275,20 @@ protected:
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge,
                                        nsCOMPtr<nsIClearSiteDataCallback> callback) override;
     virtual nsresult NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback) override;
 
 private:
     std::map<uint64_t, nsCOMPtr<nsIClearSiteDataCallback>> mClearSiteDataCallbacks;
     std::map<uint64_t, nsCOMPtr<nsIGetSitesWithDataCallback>> mSitesWithDataCallbacks;
 
+    nsCString mPluginFilename;
+    int mQuirks;
+    void InitQuirksModes(const nsCString& aMimeType);
+
 public:
 
 #if defined(XP_MACOSX)
     virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) override;
     virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) override;
 #endif
 
     void InitAsyncSurrogates();
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginQuirks.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PluginQuirks.h"
+
+#include "nsPluginHost.h"
+
+namespace mozilla {
+namespace plugins {
+
+int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType,
+                                     const nsCString& aPluginFilename)
+{
+    int quirks = 0;
+
+    nsPluginHost::SpecialType specialType = nsPluginHost::GetSpecialType(aMimeType);
+
+    if (specialType == nsPluginHost::eSpecialType_Silverlight) {
+        quirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT;
+#ifdef OS_WIN
+        quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
+        quirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT;
+#endif
+    }
+
+    if (specialType == nsPluginHost::eSpecialType_Flash) {
+        quirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN;
+#ifdef OS_WIN
+        quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
+        quirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
+        quirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
+        quirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
+        quirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
+#endif
+    }
+
+#ifdef OS_WIN
+    // QuickTime plugin usually loaded with audio/mpeg mimetype
+    NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin");
+    if (FindInReadable(quicktime, aPluginFilename)) {
+        quirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW;
+    }
+#endif
+
+#ifdef XP_MACOSX
+    // Whitelist Flash and Quicktime to support offline renderer
+    NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin");
+    if (specialType == nsPluginHost::eSpecialType_Flash) {
+        quirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES;
+        quirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
+    } else if (FindInReadable(quicktime, aPluginFilename)) {
+        quirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
+    }
+#endif
+
+#ifdef OS_WIN
+    if (specialType == nsPluginHost::eSpecialType_Unity) {
+        quirks |= QUIRK_UNITY_FIXUP_MOUSE_CAPTURE;
+    }
+#endif
+
+    return quirks;
+}
+
+} /* namespace plugins */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginQuirks.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef dom_plugins_PluginQuirks_h
+#define dom_plugins_PluginQuirks_h
+
+namespace mozilla {
+namespace plugins {
+
+// Quirks mode support for various plugin mime types
+enum PluginQuirks {
+  QUIRKS_NOT_INITIALIZED                          = 0,
+  // Silverlight assumes it is transparent in windowless mode. This quirk
+  // matches the logic in nsNPAPIPluginInstance::SetWindowless.
+  QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT           = 1 << 0,
+  // Win32: Hook TrackPopupMenu api so that we can swap out parent
+  // hwnds. The api will fail with parents not associated with our
+  // child ui thread. See WinlessHandleEvent for details.
+  QUIRK_WINLESS_TRACKPOPUP_HOOK                   = 1 << 1,
+  // Win32: Throttle flash WM_USER+1 heart beat messages to prevent
+  // flooding chromium's dispatch loop, which can cause ipc traffic
+  // processing lag.
+  QUIRK_FLASH_THROTTLE_WMUSER_EVENTS              = 1 << 2,
+  // Win32: Catch resets on our subclass by hooking SetWindowLong.
+  QUIRK_FLASH_HOOK_SETLONGPTR                     = 1 << 3,
+  // X11: Work around a bug in Flash up to 10.1 d51 at least, where
+  // expose event top left coordinates within the plugin-rect and
+  // not at the drawable origin are misinterpreted.
+  QUIRK_FLASH_EXPOSE_COORD_TRANSLATION            = 1 << 4,
+  // Win32: Catch get window info calls on the browser and tweak the
+  // results so mouse input works when flash is displaying it's settings
+  // window.
+  QUIRK_FLASH_HOOK_GETWINDOWINFO                  = 1 << 5,
+  // Win: Addresses a flash bug with mouse capture and full screen
+  // windows.
+  QUIRK_FLASH_FIXUP_MOUSE_CAPTURE                 = 1 << 6,
+  // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
+  // Avoid calling SetWindow in that case.
+  QUIRK_QUICKTIME_AVOID_SETWINDOW                 = 1 << 7,
+  // Win: Check to make sure the parent window has focus before calling
+  // set focus on the child. Addresses a full screen dialog prompt
+  // problem in Silverlight.
+  QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT            = 1 << 8,
+  // Mac: Allow the plugin to use offline renderer mode.
+  // Use this only if the plugin is certified the support the offline renderer.
+  QUIRK_ALLOW_OFFLINE_RENDERER                    = 1 << 9,
+  // Mac: Work around a Flash bug that can cause plugin process crashes
+  // in CoreGraphics mode:  The Flash plugin sometimes accesses the
+  // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect)
+  // outside of that call.  See bug 804606.
+  QUIRK_FLASH_AVOID_CGMODE_CRASHES                = 1 << 10,
+  // Work around a Flash bug where it fails to check the error code of a
+  // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference
+  // its char* output.
+  QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN        = 1 << 11,
+  // Win: Addresses a Unity bug with mouse capture.
+  QUIRK_UNITY_FIXUP_MOUSE_CAPTURE                 = 1 << 12,
+};
+
+int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType,
+                                     const nsCString& aPluginFilename);
+
+} /* namespace plugins */
+} /* namespace mozilla */
+
+#endif  // ifndef dom_plugins_PluginQuirks_h
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -26,16 +26,17 @@ EXPORTS.mozilla.plugins += [
     'PluginDataResolver.h',
     'PluginInstanceChild.h',
     'PluginInstanceParent.h',
     'PluginMessageUtils.h',
     'PluginModuleChild.h',
     'PluginModuleParent.h',
     'PluginProcessChild.h',
     'PluginProcessParent.h',
+    'PluginQuirks.h',
     'PluginScriptableObjectChild.h',
     'PluginScriptableObjectParent.h',
     'PluginScriptableObjectUtils-inl.h',
     'PluginScriptableObjectUtils.h',
     'PluginStreamChild.h',
     'PluginStreamParent.h',
     'PluginUtilsOSX.h',
     'PluginWidgetChild.h',
@@ -81,16 +82,17 @@ UNIFIED_SOURCES += [
     'ChildTimer.cpp',
     'PluginAsyncSurrogate.cpp',
     'PluginBackgroundDestroyer.cpp',
     'PluginInstanceParent.cpp',
     'PluginMessageUtils.cpp',
     'PluginModuleParent.cpp',
     'PluginProcessChild.cpp',
     'PluginProcessParent.cpp',
+    'PluginQuirks.cpp',
     'PluginScriptableObjectChild.cpp',
     'PluginScriptableObjectParent.cpp',
     'PluginStreamChild.cpp',
     'PluginStreamParent.cpp',
 ]
 
 SOURCES += [
     'PluginInstanceChild.cpp', # 'PluginThreadCallback' : ambiguous symbol