Bug 1365660: Part 2 - Add a HasRemoteContent flag to popup widgets that contain remote browsers. r=kats,bas
authorKris Maglione <maglione.k@gmail.com>
Wed, 17 May 2017 10:16:25 -0700
changeset 359232 cfe30fc6158c4dcb6c9fe2bc9bff35674ed9b247
parent 359231 5e53d393c722f451c0e8dca642dbb1ace5331f6f
child 359233 cb4b09616e235659ac4b6570c99f5a771d2d9206
push id31850
push userryanvm@gmail.com
push dateFri, 19 May 2017 15:47:16 +0000
treeherdermozilla-central@c800b6dfca67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, bas
bugs1365660
milestone55.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 1365660: Part 2 - Add a HasRemoteContent flag to popup widgets that contain remote browsers. r=kats,bas There are several behaviors that we only need to apply to popups which are known to contain remote content. And since those behaviors can cause issues elsewhere, we need to be able to identify popups which should contain remote content, and treat them specially, where appropriate. MozReview-Commit-ID: EMFrSP8lZiD
dom/base/nsGkAtomList.h
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsMenuPopupFrame.h
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/nsWidgetInitData.h
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -1098,16 +1098,17 @@ GK_ATOM(range, "range")
 GK_ATOM(readonly, "readonly")
 GK_ATOM(rect, "rect")
 GK_ATOM(rectangle, "rectangle")
 GK_ATOM(ref, "ref")
 GK_ATOM(refresh, "refresh")
 GK_ATOM(rel, "rel")
 GK_ATOM(onreloadpage, "onreloadpage")
 GK_ATOM(rem, "rem")
+GK_ATOM(remote, "remote")
 GK_ATOM(removeelement, "removeelement")
 GK_ATOM(renderingobserverlist, "renderingobserverlist")
 GK_ATOM(repeat, "repeat")
 GK_ATOM(replace, "replace")
 GK_ATOM(required, "required")
 GK_ATOM(reserved, "reserved")
 GK_ATOM(reset, "reset")
 GK_ATOM(resizeafter, "resizeafter")
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -185,16 +185,24 @@ nsMenuPopupFrame::Init(nsIContent*      
       rootBox->SetDefaultTooltip(aContent);
     }
   }
 
   AddStateBits(NS_FRAME_IN_POPUP);
 }
 
 bool
+nsMenuPopupFrame::HasRemoteContent() const
+{
+  return (!mInContentShell && mPopupType == ePopupTypePanel &&
+          mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::remote,
+                                nsGkAtoms::_true, eIgnoreCase));
+}
+
+bool
 nsMenuPopupFrame::IsNoAutoHide() const
 {
   // Panels with noautohide="true" don't hide when the mouse is clicked
   // outside of them, or when another application is made active. Non-autohide
   // panels cannot be used in content windows.
   return (!mInContentShell && mPopupType == ePopupTypePanel &&
            mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
                                  nsGkAtoms::_true, eIgnoreCase));
@@ -235,19 +243,22 @@ nsMenuPopupFrame::PopupLevel(bool aIsNoA
   if (aIsNoAutoHide)
     return ePopupLevelParent;
 
   // Otherwise, the result depends on the platform.
   return sDefaultLevelIsTop ? ePopupLevelTop : ePopupLevelParent;
 }
 
 void
-nsMenuPopupFrame::EnsureWidget()
+nsMenuPopupFrame::EnsureWidget(bool aRecreate)
 {
   nsView* ourView = GetView();
+  if (aRecreate) {
+    ourView->DestroyWidget();
+  }
   if (!ourView->HasWidget()) {
     NS_ASSERTION(!mGeneratedChildren && !PrincipalChildList().FirstChild(),
                  "Creating widget for MenuPopupFrame with children");
     CreateWidgetForView(ourView);
   }
 }
 
 nsresult
@@ -286,21 +297,24 @@ nsMenuPopupFrame::CreateWidgetForView(ns
       if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::close,
                                 nsGkAtoms::_true, eCaseMatters)) {
         widgetData.mBorderStyle =
           static_cast<enum nsBorderStyle>(widgetData.mBorderStyle | eBorderStyle_close);
       }
     }
   }
 
+  bool remote = HasRemoteContent();
+
   nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(this, this);
   nsIContent* parentContent = GetContent()->GetParent();
   nsIAtom *tag = nullptr;
   if (parentContent && parentContent->IsXULElement())
     tag = parentContent->NodeInfo()->NameAtom();
+  widgetData.mHasRemoteContent = remote;
   widgetData.mSupportTranslucency = mode == eTransparencyTransparent;
   widgetData.mDropShadow = !(mode == eTransparencyTransparent || tag == nsGkAtoms::menulist);
   widgetData.mPopupLevel = PopupLevel(widgetData.mNoAutoHide);
 
   // panels which have a parent level need a parent widget. This allows them to
   // always appear in front of the parent window but behind other windows that
   // should be in front of it.
   nsCOMPtr<nsIWidget> parentWidget;
@@ -2229,16 +2243,23 @@ nsMenuPopupFrame::AttributeChanged(int32
 #ifndef MOZ_GTK2
   if (aAttribute == nsGkAtoms::noautohide) {
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm)
       pm->EnableRollup(mContent, !IsNoAutoHide());
   }
 #endif
 
+  if (aAttribute == nsGkAtoms::remote) {
+    // When the remote attribute changes, we need to create a new widget to
+    // ensure that it has the correct compositor and transparency settings to
+    // match the new value.
+    EnsureWidget(true);
+  }
+
   if (aAttribute == nsGkAtoms::followanchor) {
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm) {
       pm->UpdateFollowAnchor(this);
     }
   }
 
   if (aAttribute == nsGkAtoms::label) {
--- a/layout/xul/nsMenuPopupFrame.h
+++ b/layout/xul/nsMenuPopupFrame.h
@@ -220,26 +220,31 @@ public:
                     nsIFrame*         aPrevInFlow) override;
 
   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
+  bool HasRemoteContent() const;
+
   // returns true if the popup is a panel with the noautohide attribute set to
   // true. These panels do not roll up automatically.
   bool IsNoAutoHide() const;
 
   nsPopupLevel PopupLevel() const
   {
     return PopupLevel(IsNoAutoHide()); 
   }
 
-  void EnsureWidget();
+  // Ensure that a widget has already been created for this view, and create
+  // one if it hasn't. If aRecreate is true, destroys any existing widget and
+  // creates a new one, regardless of whether one has already been created.
+  void EnsureWidget(bool aRecreate = false);
 
   nsresult CreateWidgetForView(nsView* aView);
   uint8_t GetShadowStyle();
 
   virtual void SetInitialChildList(ChildListID  aListID,
                                    nsFrameList& aChildList) override;
 
   virtual bool IsLeaf() const override;
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -158,16 +158,17 @@ nsBaseWidget::nsBaseWidget()
 , mCursor(eCursor_standard)
 , mBorderStyle(eBorderStyle_none)
 , mBounds(0,0,0,0)
 , mOriginalBounds(nullptr)
 , mClipRectCount(0)
 , mSizeMode(nsSizeMode_Normal)
 , mPopupLevel(ePopupLevelTop)
 , mPopupType(ePopupTypeAny)
+, mHasRemoteContent(false)
 , mCompositorWidgetDelegate(nullptr)
 , mUpdateCursor(true)
 , mUseAttachedEvents(false)
 , mIMEHasFocus(false)
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
 , mAccessibilityInUseFlag(false)
 #endif
 {
@@ -375,16 +376,17 @@ void nsBaseWidget::BaseCreate(nsIWidget*
   }
 
   // keep a reference to the device context
   if (nullptr != aInitData) {
     mWindowType = aInitData->mWindowType;
     mBorderStyle = aInitData->mBorderStyle;
     mPopupLevel = aInitData->mPopupLevel;
     mPopupType = aInitData->mPopupHint;
+    mHasRemoteContent = aInitData->mHasRemoteContent;
   }
 
   if (aParent) {
     aParent->AddChild(this);
   }
 }
 
 //-------------------------------------------------------------------------
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -544,16 +544,18 @@ protected:
     nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
     return widget.forget();
   }
 
   LayerManager* CreateBasicLayerManager();
 
   nsPopupType PopupType() const { return mPopupType; }
 
+  bool HasRemoteContent() const { return mHasRemoteContent; }
+
   void NotifyRollupGeometryChange()
   {
     // XULPopupManager isn't interested in this notification, so only
     // send it if gRollupListener is set.
     if (gRollupListener) {
       gRollupListener->NotifyGeometryChange();
     }
   }
@@ -678,16 +680,17 @@ protected:
   LayoutDeviceIntRect* mOriginalBounds;
   // When this pointer is null, the widget is not clipped
   mozilla::UniquePtr<LayoutDeviceIntRect[]> mClipRects;
   uint32_t          mClipRectCount;
   nsSizeMode        mSizeMode;
   nsPopupLevel      mPopupLevel;
   nsPopupType       mPopupType;
   SizeConstraints   mSizeConstraints;
+  bool              mHasRemoteContent;
 
   CompositorWidgetDelegate* mCompositorWidgetDelegate;
 
   bool              mUpdateCursor;
   bool              mUseAttachedEvents;
   bool              mIMEHasFocus;
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
   bool              mAccessibilityInUseFlag;
--- a/widget/nsWidgetInitData.h
+++ b/widget/nsWidgetInitData.h
@@ -100,17 +100,18 @@ struct nsWidgetInitData {
       mDropShadow(false),
       mListenForResizes(false),
       mUnicode(true),
       mRTL(false),
       mNoAutoHide(false),
       mIsDragPopup(false),
       mIsAnimationSuppressed(false),
       mSupportTranslucency(false),
-      mMouseTransparent(false)
+      mMouseTransparent(false),
+      mHasRemoteContent(false)
   {
   }
 
   nsWindowType  mWindowType;
   nsBorderStyle mBorderStyle;
   nsPopupType   mPopupHint;
   nsPopupLevel  mPopupLevel;
   // B2G multi-screen support. Screen ID is for differentiating screens of
@@ -126,11 +127,12 @@ struct nsWidgetInitData {
   bool          mIsDragPopup;  // true for drag feedback panels
   // true if window creation animation is suppressed, e.g. for session restore
   bool          mIsAnimationSuppressed;
   // true if the window should support an alpha channel, if available.
   bool          mSupportTranslucency;
   // true if the window should be transparent to mouse events. Currently this is
   // only valid for eWindowType_popup widgets
   bool          mMouseTransparent;
+  bool          mHasRemoteContent;
 };
 
 #endif // nsWidgetInitData_h__