Bug 621228 - Make plugins listening presShell SetActive calls. r=jst
authorOleg Romashin <romaxa@gmail.com>
Thu, 18 Aug 2011 22:08:38 +0200
changeset 75506 c51feb247cc4127b01b62a331bd6f370d85fe638
parent 75505 ec4956f17090631ec826f27e3da5ac6956717083
child 75507 e204fcdf504974372f450422ab851b41af959cfb
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersjst
bugs621228
milestone9.0a1
Bug 621228 - Make plugins listening presShell SetActive calls. r=jst
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
layout/base/nsPresShell.cpp
layout/generic/nsIObjectFrame.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -300,16 +300,17 @@ nsPluginInstanceOwner::nsPluginInstanceO
   mInCGPaintLevel = 0;
   mSentInitialTopLevelWindowEvent = PR_FALSE;
   mColorProfile = nsnull;
   mPluginPortChanged = PR_FALSE;
 #endif
   mContentFocused = PR_FALSE;
   mWidgetVisible = PR_TRUE;
   mPluginWindowVisible = PR_FALSE;
+  mPluginDocumentActiveState = PR_TRUE;
   mNumCachedAttrs = 0;
   mNumCachedParams = 0;
   mCachedAttrParamNames = nsnull;
   mCachedAttrParamValues = nsnull;
   mDestroyWidget = PR_FALSE;
 
 #ifdef XP_MACOSX
 #ifndef NP_NO_QUICKDRAW
@@ -3236,17 +3237,17 @@ void nsPluginInstanceOwner::UpdateWindow
   nsIntPoint origin = mObjectFrame->GetWindowOriginInPixels(windowless);
 
   mPluginWindow->x = origin.x;
   mPluginWindow->y = origin.y;
 
   mPluginWindow->clipRect.left = 0;
   mPluginWindow->clipRect.top = 0;
 
-  if (mPluginWindowVisible) {
+  if (mPluginWindowVisible && mPluginDocumentActiveState) {
     mPluginWindow->clipRect.right = mPluginWindow->width;
     mPluginWindow->clipRect.bottom = mPluginWindow->height;
   } else {
     mPluginWindow->clipRect.right = 0;
     mPluginWindow->clipRect.bottom = 0;
   }
 
   if (!aSetWindow)
@@ -3264,16 +3265,22 @@ void nsPluginInstanceOwner::UpdateWindow
 
 void
 nsPluginInstanceOwner::UpdateWindowVisibility(PRBool aVisible)
 {
   mPluginWindowVisible = aVisible;
   UpdateWindowPositionAndClipRect(PR_TRUE);
 }
 
+void
+nsPluginInstanceOwner::UpdateDocumentActiveState(PRBool aIsActive)
+{
+  mPluginDocumentActiveState = aIsActive;
+  UpdateWindowPositionAndClipRect(PR_TRUE);
+}
 #endif // XP_MACOSX
 
 void
 nsPluginInstanceOwner::CallSetWindow()
 {
   if (!mInstance)
     return;
 
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -197,16 +197,17 @@ public:
   // FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
   // been called from nsObjectFrame::PaintPlugin() when we're using the
   // CoreGraphics drawing model).
   void BeginCGPaint();
   void EndCGPaint();
 #else // XP_MACOSX
   void UpdateWindowPositionAndClipRect(PRBool aSetWindow);
   void UpdateWindowVisibility(PRBool aVisible);
+  void UpdateDocumentActiveState(PRBool aIsActive);
 #endif // XP_MACOSX
   void CallSetWindow();
   
   void SetOwner(nsObjectFrame *aOwner)
   {
     mObjectFrame = aOwner;
   }
   nsObjectFrame* GetOwner() {
@@ -338,16 +339,17 @@ private:
 #ifdef XP_MACOSX
   PRPackedBool                mPluginPortChanged;
 #endif
 #ifdef MOZ_X11
   // Used with windowless plugins only, initialized in CreateWidget().
   PRPackedBool                mFlash10Quirks;
 #endif
   PRPackedBool                mPluginWindowVisible;
+  PRPackedBool                mPluginDocumentActiveState;
   
   // If true, destroy the widget on destruction. Used when plugin stop
   // is being delayed to a safer point in time.
   PRPackedBool                mDestroyWidget;
   PRUint16          mNumCachedAttrs;
   PRUint16          mNumCachedParams;
   char              **mCachedAttrParamNames;
   char              **mCachedAttrParamValues;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -9406,31 +9406,43 @@ SetExternalResourceIsActive(nsIDocument*
 {
   nsIPresShell* shell = aDocument->GetShell();
   if (shell) {
     shell->SetIsActive(*static_cast<PRBool*>(aClosure));
   }
   return PR_TRUE;
 }
 
+static void
+SetPluginIsActive(nsIContent* aContent, void* aClosure)
+{
+  nsIFrame *frame = aContent->GetPrimaryFrame();
+  nsIObjectFrame *objectFrame = do_QueryFrame(frame);
+  if (objectFrame) {
+    objectFrame->SetIsDocumentActive(*static_cast<PRBool*>(aClosure));
+  }
+}
+
 nsresult
 PresShell::SetIsActive(PRBool aIsActive)
 {
   NS_PRECONDITION(mDocument, "should only be called with a document");
 
   mIsActive = aIsActive;
   nsPresContext* presContext = GetPresContext();
   if (presContext &&
       presContext->RefreshDriver()->PresContext() == presContext) {
     presContext->RefreshDriver()->SetThrottled(!mIsActive);
   }
 
   // Propagate state-change to my resource documents' PresShells
   mDocument->EnumerateExternalResources(SetExternalResourceIsActive,
                                         &aIsActive);
+  mDocument->EnumerateFreezableElements(SetPluginIsActive,
+                                        &aIsActive);
   nsresult rv = UpdateImageLockingState();
 #ifdef ACCESSIBILITY
   if (aIsActive) {
     nsAccessibilityService* accService = AccService();
     if (accService) {
       accService->PresShellActivated(this);
     }
   }
--- a/layout/generic/nsIObjectFrame.h
+++ b/layout/generic/nsIObjectFrame.h
@@ -89,11 +89,18 @@ public:
    * is currently active in this frame.
    */
   virtual void StopPlugin() = 0;
 
   /**
    * Get the native widget for the plugin, if any.
    */
   virtual nsIWidget* GetWidget() = 0;
+
+  /**
+   * Update plugin active state. Frame should update if it is on an active tab
+   * or not and forward that information to the plugin to make it possible to
+   * throttle down plugin instance in non active case.
+   */
+  virtual void SetIsDocumentActive(PRBool aIsActive) = 0;
 };
 
 #endif /* nsIObjectFrame_h___ */
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -2490,16 +2490,26 @@ nsObjectFrame::GetCursor(const nsPoint& 
   if (!useDOMCursor) {
     return NS_ERROR_FAILURE;
   }
 
   return nsObjectFrameSuper::GetCursor(aPoint, aCursor);
 }
 
 void
+nsObjectFrame::SetIsDocumentActive(PRBool aIsActive)
+{
+#ifndef XP_MACOSX
+  if (mInstanceOwner) {
+    mInstanceOwner->UpdateDocumentActiveState(aIsActive);
+  }
+#endif
+}
+
+void
 nsObjectFrame::NotifyContentObjectWrapper()
 {
   nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
   if (!doc)
     return;
 
   nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
   if (!sgo)
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -123,16 +123,17 @@ public:
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_METHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance);
   virtual nsresult Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener);
   virtual nsresult Instantiate(const char* aMimeType, nsIURI* aURI);
   virtual void TryNotifyContentObjectWrapper();
   virtual void StopPlugin();
+  virtual void SetIsDocumentActive(PRBool aIsActive);
 
   /*
    * Stop a plugin instance. If aDelayedStop is true, the plugin will
    * be stopped at a later point when it's safe to do so (i.e. not
    * while destroying the frame tree). Delayed stopping is only
    * implemented on Win32 for now.
    */
   void StopPluginInternal(PRBool aDelayedStop);