Bug 1365660: Part 2 - Add a HasRemoteContent flag to popup widgets that contain remote browsers. r?kats,bas.schouten
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
--- 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__