Bug 604303 - Trap GetWindowInfo calls in flash and return browser window metrics similar to what we returned prior to the landing of bug 130078. r=bent, a=betaN.
authorJim Mathies <jmathies@mozilla.com>
Mon, 06 Dec 2010 18:50:56 -0600
changeset 58736 fb8ad78374dfbac4438a05249b4f767160adcf9f
parent 58735 038591612c97ce8fe812a807a180097e1435f1f7
child 58737 07e02bc22afb8bd9c74200a1badf7a8e460e44fc
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersbent, betaN
bugs604303, 130078
milestone2.0b8pre
Bug 604303 - Trap GetWindowInfo calls in flash and return browser window metrics similar to what we returned prior to the landing of bug 130078. r=bent, a=betaN.
dom/plugins/PluginModuleChild.cpp
dom/plugins/PluginModuleChild.h
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -65,42 +65,49 @@
 #include "mozilla/plugins/BrowserStreamChild.h"
 #include "mozilla/plugins/PluginStreamChild.h"
 #include "PluginIdentifierChild.h"
 
 #include "nsNPAPIPlugin.h"
 
 #ifdef XP_WIN
 #include "COMMessageFilter.h"
+#include "nsWindowsDllInterceptor.h"
 #endif
 
 #ifdef OS_MACOSX
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
 #endif
 
 using namespace mozilla::plugins;
 
 #if defined(XP_WIN)
 const PRUnichar * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
+const PRUnichar * kMozillaWindowClass = L"MozillaWindowClass";
 #endif
 
 namespace {
 PluginModuleChild* gInstance = nsnull;
 }
 
 #ifdef MOZ_WIDGET_QT
 typedef void (*_gtk_init_fn)(int argc, char **argv);
 static _gtk_init_fn s_gtk_init = nsnull;
 static PRLibrary *sGtkLib = nsnull;
 #endif
 
 #ifdef XP_WIN
 // Used with fix for flash fullscreen window loosing focus.
 static bool gDelayFlashFocusReplyUntilEval = false;
+// Used to fix GetWindowInfo problems with internal flash settings dialogs
+static WindowsDllInterceptor sUser32Intercept;
+typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
+static GetWindowInfoPtr sGetWindowInfoPtrStub = NULL;
+static HWND sBrowserHwnd = NULL;
 #endif
 
 PluginModuleChild::PluginModuleChild() :
     mLibrary(0),
     mShutdownFunc(0),
     mInitializeFunc(0),
     mQuirks(QUIRKS_NOT_INITIALIZED)
 #if defined(OS_WIN) || defined(OS_MACOSX)
@@ -1705,28 +1712,66 @@ PluginModuleChild::AllocPPluginIdentifie
 
 bool
 PluginModuleChild::DeallocPPluginIdentifier(PPluginIdentifierChild* aActor)
 {
     delete aActor;
     return true;
 }
 
+#if defined(XP_WIN)
+BOOL WINAPI
+PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
+{
+  if (!pwi)
+      return FALSE;
+
+  if (!sGetWindowInfoPtrStub) {
+     NS_ASSERTION(FALSE, "Something is horribly wrong in PMCGetWindowInfoHook!");
+     return FALSE;
+  }
+
+  if (!sBrowserHwnd) {
+      PRUnichar szClass[20];
+      if (GetClassNameW(hWnd, szClass, NS_ARRAY_LENGTH(szClass)) && 
+          !wcscmp(szClass, kMozillaWindowClass)) {
+          sBrowserHwnd = hWnd;
+      }
+  }
+  // Oddity: flash does strange rect comparisons for mouse input destined for
+  // it's internal settings window. Post removing sub widgets for tabs, touch
+  // this up so they get the rect they expect.
+  // XXX potentially tie this to a specific major version?
+  BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
+  if (sBrowserHwnd && sBrowserHwnd == hWnd)
+      pwi->rcWindow = pwi->rcClient;
+  return result;
+}
+#endif
+
 PPluginInstanceChild*
 PluginModuleChild::AllocPPluginInstance(const nsCString& aMimeType,
                                         const uint16_t& aMode,
                                         const InfallibleTArray<nsCString>& aNames,
                                         const InfallibleTArray<nsCString>& aValues,
                                         NPError* rv)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
     InitQuirksModes(aMimeType);
 
+#ifdef XP_WIN
+    if (mQuirks & QUIRK_FLASH_HOOK_GETWINDOINFO) {
+        sUser32Intercept.Init("user32.dll");
+        sUser32Intercept.AddHook("GetWindowInfo", PMCGetWindowInfoHook,
+                                 (void**) &sGetWindowInfoPtrStub);
+    }
+#endif
+
     nsAutoPtr<PluginInstanceChild> childInstance(
         new PluginInstanceChild(&mFunctions));
     if (!childInstance->Initialize()) {
         *rv = NPERR_GENERIC_ERROR;
         return 0;
     }
     return childInstance.forget();
 }
@@ -1749,16 +1794,17 @@ PluginModuleChild::InitQuirksModes(const
 
 #ifdef OS_WIN
     // application/x-shockwave-flash
     NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
     if (FindInReadable(flash, aMimeType)) {
         mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
         mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS; 
         mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
+        mQuirks |= QUIRK_FLASH_HOOK_GETWINDOINFO;
     }
 #endif
 }
 
 bool
 PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
                                                     const nsCString& aMimeType,
                                                     const uint16_t& aMode,
--- a/dom/plugins/PluginModuleChild.h
+++ b/dom/plugins/PluginModuleChild.h
@@ -220,16 +220,20 @@ public:
         // 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_GETWINDOINFO                   = 1 << 5,
     };
 
     int GetQuirks() { return mQuirks; }
     void AddQuirk(PluginQuirks quirk) {
       if (mQuirks == QUIRKS_NOT_INITIALIZED)
         mQuirks = 0;
       mQuirks |= quirk;
     }