Bug 775965 - Store root pres context used to register plugins on nsObjectFrame. r=roc
authorChris Pearce <cpearce@mozilla.com>
Fri, 17 Aug 2012 16:25:19 +1200
changeset 108081 6f2c8195793c4b87b8457e3ffaa91f211f9ae4ab
parent 108080 0cfcc4e860c52a5dc328a34613cbfafd15f9fc51
child 108082 2d036225c7ba68772acaf9b6bb7e03da81b649e4
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs775965
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 775965 - Store root pres context used to register plugins on nsObjectFrame. r=roc
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -425,18 +425,17 @@ nsObjectFrame::PrepForDrawing(nsIWidget 
     // On Mac, we need to invalidate ourselves since even windowed
     // plugins are painted through Thebes and we need to ensure
     // the Thebes layer containing the plugin is updated.
     if (parentWidget == GetNearestWidget()) {
       Invalidate(GetContentRectRelativeToSelf());
     }
 #endif
 
-    rpc->RegisterPluginForGeometryUpdates(mContent);
-    rpc->RequestUpdatePluginGeometry(this);
+    RegisterPluginForGeometryUpdates();
 
     // Here we set the background color for this widget because some plugins will use 
     // the child window background color when painting. If it's not set, it may default to gray
     // Sometimes, a frame doesn't have a background color or is transparent. In this
     // case, walk up the frame tree until we do find a frame with a background color
     for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
       nscolor bgcolor =
         frame->GetVisitedDependentColor(eCSSProperty_background_color);
@@ -445,18 +444,17 @@ nsObjectFrame::PrepForDrawing(nsIWidget 
         break;
       }
     }
   } else {
     // Changing to windowless mode changes the NPWindow geometry.
     FixupWindow(GetContentRectRelativeToSelf().Size());
 
 #ifndef XP_MACOSX
-    rpc->RegisterPluginForGeometryUpdates(mContent);
-    rpc->RequestUpdatePluginGeometry(this);
+    RegisterPluginForGeometryUpdates();
 #endif
   }
 
   if (!IsHidden()) {
     viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
   }
 
 #ifdef ACCESSIBILITY
@@ -730,26 +728,54 @@ nsObjectFrame::CallSetWindow(bool aCheck
   }
 
   instanceOwnerRef->ReleasePluginPort(window->window);
 
   return rv;
 }
 
 void
+nsObjectFrame::RegisterPluginForGeometryUpdates()
+{
+  nsRootPresContext* rpc = PresContext()->GetRootPresContext();
+  NS_ASSERTION(rpc, "We should have a root pres context!");
+  if (mRootPresContextRegisteredWith == rpc || !rpc) {
+    // Already registered with current root pres context,
+    // or null root pres context...
+    return;
+  }
+  if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
+    // Registered to some other root pres context. Unregister, and
+    // re-register with our current one...
+    UnregisterPluginForGeometryUpdates();
+  }
+  mRootPresContextRegisteredWith = rpc;
+  mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
+  mRootPresContextRegisteredWith->RequestUpdatePluginGeometry(this);
+}
+
+void
+nsObjectFrame::UnregisterPluginForGeometryUpdates()
+{
+  if (!mRootPresContextRegisteredWith) {
+    // Not registered...
+    return;
+  }
+  mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
+  mRootPresContextRegisteredWith = nullptr;
+}
+
+void
 nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
 {
   mInstanceOwner = aOwner;
   if (mInstanceOwner) {
     return;
   }
-  nsRootPresContext* rpc = PresContext()->GetRootPresContext();
-  if (rpc) {
-    rpc->UnregisterPluginForGeometryUpdates(mContent);
-  }
+  UnregisterPluginForGeometryUpdates();
   if (mWidget && mInnerView) {
     mInnerView->DetachWidgetEventHandler(mWidget);
     // Make sure the plugin is hidden in case an update of plugin geometry
     // hasn't happened since this plugin became hidden.
     nsIWidget* parent = mWidget->GetParent();
     if (parent) {
       nsTArray<nsIWidget::Configuration> configurations;
       this->GetEmptyClipConfiguration(&configurations);
@@ -2208,19 +2234,17 @@ nsObjectFrame::BeginSwapDocShells(nsICon
   // to filter out the nsObjectFrames and ignore the rest.
   nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
   if (!obj)
     return;
 
   nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
   NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
                "Plugin windows must not be toplevel");
-  nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
-  NS_ASSERTION(rootPC, "unable to unregister the plugin frame");
-  rootPC->UnregisterPluginForGeometryUpdates(aContent);
+  objectFrame->UnregisterPluginForGeometryUpdates();
 }
 
 /*static*/ void
 nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*)
 {
   NS_PRECONDITION(aContent, "");
 
   // This function is called from a document content enumerator so we need
@@ -2236,18 +2260,17 @@ nsObjectFrame::EndSwapDocShells(nsIConte
   if (widget) {
     // Reparent the widget.
     nsIWidget* parent =
       rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
     widget->SetParent(parent);
     objectFrame->CallSetWindow();
 
     // Register for geometry updates and make a request.
-    rootPC->RegisterPluginForGeometryUpdates(aContent);
-    rootPC->RequestUpdatePluginGeometry(objectFrame);
+    objectFrame->RegisterPluginForGeometryUpdates();
   }
 }
 
 nsIFrame*
 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsObjectFrame(aContext);
 }
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -16,16 +16,17 @@
 #include "nsIReflowCallback.h"
 
 #ifdef ACCESSIBILITY
 class nsIAccessible;
 #endif
 
 class nsPluginHost;
 class nsPresContext;
+class nsRootPresContext;
 class nsDisplayPlugin;
 class nsIOSurface;
 class PluginBackgroundSink;
 
 namespace mozilla {
 namespace layers {
 class ImageContainer;
 class Layer;
@@ -227,17 +228,26 @@ protected:
 
   void NotifyPluginReflowObservers();
 
   friend class nsPluginInstanceOwner;
   friend class nsDisplayPlugin;
   friend class PluginBackgroundSink;
 
 private:
-  
+  // Registers the plugin for a geometry update, and requests a geometry
+  // update. This caches the root pres context in
+  // mRootPresContextRegisteredWith, so that we can be sure we unregister
+  // from the right root prest context in UnregisterPluginForGeometryUpdates.
+  void RegisterPluginForGeometryUpdates();
+
+  // Unregisters the plugin for geometry updated with the root pres context
+  // stored in mRootPresContextRegisteredWith.
+  void UnregisterPluginForGeometryUpdates();
+
   class PluginEventNotifier : public nsRunnable {
   public:
     PluginEventNotifier(const nsString &aEventType) : 
       mEventType(aEventType) {}
     
     NS_IMETHOD Run();
   private:
     nsString mEventType;
@@ -253,16 +263,22 @@ private:
    */
   PluginBackgroundSink*           mBackgroundSink;
 
   bool mReflowCallbackPosted;
 
   // A reference to the ImageContainer which contains the current frame
   // of plugin to display.
   nsRefPtr<ImageContainer> mImageContainer;
+
+  // We keep this reference to ensure we can always unregister the
+  // plugins we register on the root PresContext.
+  // This is only non-null while we have a plugin registered for geometry
+  // updates.
+  nsRefPtr<nsRootPresContext> mRootPresContextRegisteredWith;
 };
 
 class nsDisplayPlugin : public nsDisplayItem {
 public:
   nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
   {
     MOZ_COUNT_CTOR(nsDisplayPlugin);