Bug 542337 - '[OOPP] hang in test_plugin_clipping2.xhtml' r=jimm.
authorBen Turner <bent.mozilla@gmail.com>
Thu, 28 Jan 2010 11:27:08 -0800
changeset 46630 b3f9b762cab489e69dd7cda8716fd9280136f595
parent 46629 6fdd222191f6141dc048bf73751212060b814a4d
child 46631 2e5f92d640fe1e9201117fba2aef245984dc360e
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjimm
bugs542337
milestone1.9.3a1pre
Bug 542337 - '[OOPP] hang in test_plugin_clipping2.xhtml' r=jimm.
modules/plugin/base/src/nsPluginNativeWindowWin.cpp
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/windows/nsWindowGfx.cpp
--- a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
+++ b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
@@ -540,17 +540,24 @@ nsresult nsPluginNativeWindowWin::Subcla
     return NS_ERROR_FAILURE;
 
   // check if we need to re-subclass
   WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
   if (PluginWndProc == currentWndProc)
     return NS_OK;
 
   LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
+#ifdef MOZ_IPC
+  // Out of process plugins must not have the WS_CLIPCHILDREN style set on their
+  // parent windows or else synchronous paints (via UpdateWindow() and others)
+  // will cause deadlocks.
+  style &= ~WS_CLIPCHILDREN;
+#else
   style |= WS_CLIPCHILDREN;
+#endif
   SetWindowLongPtr(hWnd, GWL_STYLE, style);
 
   mPluginWinProc = SubclassWindow(hWnd, (LONG_PTR)PluginWndProc);
   if (!mPluginWinProc)
     return NS_ERROR_FAILURE;
 
   nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
   NS_ASSERTION(!win || (win == this), "plugin window already has property and this is not us");
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -101,18 +101,16 @@
  **
  ** Include headers.
  **
  **************************************************************
  **************************************************************/
 
 #ifdef MOZ_IPC
 #include "mozilla/ipc/SyncChannel.h"
-#include "mozilla/plugins/PluginInstanceParent.h"
-using mozilla::plugins::PluginInstanceParent;
 #endif
 
 #include "nsWindow.h"
 
 #include <windows.h>
 #include <process.h>
 #include <commctrl.h>
 #include <unknwn.h>
@@ -2104,17 +2102,17 @@ NS_METHOD nsWindow::Invalidate(PRBool aI
     // We need to keep track of our own invalidated region for Windows CE
     RECT r;
     GetClientRect(mWnd, &r);
     AddRECTToRegion(r, mInvalidatedRegion);
 #endif
     VERIFY(::InvalidateRect(mWnd, NULL, FALSE));
 
     if (aIsSynchronous) {
-      UpdateWindowInternal(mWnd);
+      VERIFY(::UpdateWindow(mWnd));
     }
   }
   return NS_OK;
 }
 
 // Invalidate this component visible area
 NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, PRBool aIsSynchronous)
 {
@@ -2138,17 +2136,17 @@ NS_METHOD nsWindow::Invalidate(const nsI
 
 #ifdef WINCE_WINDOWS_MOBILE
     // We need to keep track of our own invalidated region for Windows CE
     AddRECTToRegion(rect, mInvalidatedRegion);
 #endif
     VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
 
     if (aIsSynchronous) {
-      UpdateWindowInternal(mWnd);
+      VERIFY(::UpdateWindow(mWnd));
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::MakeFullScreen(PRBool aFullScreen)
 {
@@ -2182,17 +2180,17 @@ nsWindow::MakeFullScreen(PRBool aFullScr
 
 NS_IMETHODIMP nsWindow::Update()
 {
   nsresult rv = NS_OK;
 
   // updates can come through for windows no longer holding an mWnd during
   // deletes triggered by JavaScript in buttons with mouse feedback
   if (mWnd)
-    UpdateWindowInternal(mWnd);
+    VERIFY(::UpdateWindow(mWnd));
 
   return rv;
 }
 
 /**************************************************************
  *
  * SECTION: nsIWidget::Scroll
  *
@@ -3142,24 +3140,18 @@ PRBool nsWindow::DispatchCommandEvent(PR
 // descendants with invalidated rectangles.
 BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg)
 {
   LONG_PTR proc = ::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
   if (proc == (LONG_PTR)&nsWindow::WindowProc) {
     // its one of our windows so check to see if it has a
     // invalidated rect. If it does. Dispatch a synchronous
     // paint.
-    if (GetUpdateRect(aWnd, NULL, FALSE)) {
-      nsWindow* win = GetNSWindowPtr(aWnd);
-      if (win)
-        win->UpdateWindowInternal(aWnd);
-      else
-        // Bad, this could hang a plugin process. Is this possible?
-        VERIFY(::UpdateWindow(aWnd));
-    }
+    if (GetUpdateRect(aWnd, NULL, FALSE))
+      VERIFY(::UpdateWindow(aWnd));
   }
   return TRUE;
 }
 
 // Check for pending paints and dispatch any pending paint
 // messages for any nsIWidget which is a descendant of the
 // top-level window that *this* window is embedded within.
 //
@@ -7112,41 +7104,16 @@ LPARAM nsWindow::lParamToClient(LPARAM l
 {
   POINT pt;
   pt.x = GET_X_LPARAM(lParam);
   pt.y = GET_Y_LPARAM(lParam);
   ::ScreenToClient(mWnd, &pt);
   return MAKELPARAM(pt.x, pt.y);
 }
 
-// If this window hosts a plugin window from another process then we cannot use
-// the windows UpdateWindow function to update it. Doing so sends a synchronous
-// WM_PAINT message to the plugin process which may call back to this process
-// in response. As this process is waiting for the UpdateWindow call to return
-// we deadlock. To work around this we issue an IPC call to the plugin process
-// to force the redraw since the IPC call handles reentrancy properly.
-void nsWindow::UpdateWindowInternal(HWND aWnd)
-{
-  if (aWnd) {
-#ifdef MOZ_IPC
-    if (mWindowType == eWindowType_plugin) {
-      PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>(
-        ::GetPropW(aWnd, L"PluginInstanceParentProperty"));
-      if (instance) {
-        if (!instance->CallUpdateWindow())
-          NS_ERROR("Failed to send message!");
-        ValidateRect(aWnd, NULL);
-        return;
-      }
-    }
-#endif
-    VERIFY(::UpdateWindow(aWnd));
-  }
-}
-
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: ChildWindow impl.
  **
  ** Child window overrides.
  **
  **************************************************************
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -398,18 +398,16 @@ protected:
                                            PAINTSTRUCT ps, HDC aDC);
 #if !defined(WINCE)
   static void             ActivateOtherWindowHelper(HWND aWnd);
 #endif
 #ifdef ACCESSIBILITY
   static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
 #endif // ACCESSIBILITY
 
-  void                    UpdateWindowInternal(HWND aWnd);
-
 protected:
   nsIntSize             mLastSize;
   nsIntPoint            mLastPoint;
   HWND                  mWnd;
   WNDPROC               mPrevWndProc;
   HBRUSH                mBrush;
   PRPackedBool          mIsTopWidgetWindow;
   PRPackedBool          mHas3DBorder;
--- a/widget/src/windows/nsWindowGfx.cpp
+++ b/widget/src/windows/nsWindowGfx.cpp
@@ -48,16 +48,21 @@
  **
  ** BLOCK: Includes
  **
  ** Include headers.
  **
  **************************************************************
  **************************************************************/
 
+#ifdef MOZ_IPC
+#include "mozilla/plugins/PluginInstanceParent.h"
+using mozilla::plugins::PluginInstanceParent;
+#endif
+
 #include "nsWindowGfx.h"
 #include <windows.h>
 #include "nsIRegion.h"
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
 #include "nsGfxCIID.h"
 #include "gfxContext.h"
@@ -317,16 +322,29 @@ EnsureSharedSurfaceSize(gfxIntSize size)
     sSharedSurfaceData = (PRUint8 *)malloc(WORDSSIZE(sSharedSurfaceSize) * 4);
   }
 
   return (sSharedSurfaceData != nsnull);
 }
 
 PRBool nsWindow::OnPaint(HDC aDC)
 {
+#ifdef MOZ_IPC
+  if (mWindowType == eWindowType_plugin) {
+    PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>(
+      ::GetPropW(mWnd, L"PluginInstanceParentProperty"));
+    if (instance) {
+      if (!instance->CallUpdateWindow())
+        NS_ERROR("Failed to send message!");
+      ValidateRect(mWnd, NULL);
+      return PR_TRUE;
+    }
+  }
+#endif
+
   nsPaintEvent willPaintEvent(PR_TRUE, NS_WILL_PAINT, this);
   DispatchWindowEvent(&willPaintEvent);
 
 #ifdef CAIRO_HAS_DDRAW_SURFACE
   if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) {
     return OnPaintImageDDraw16();
   }
 #endif