From 97e8182bb2c56b49a867d8c46363271f879420dc Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 28 Nov 2019 21:46:33 +0000 Subject: [PATCH] Bug 1596709 - Move special chrome root element handling to an observer. r=smaug Enables any type of document to use the special root element attributes currently used by XUL . Differential Revision: https://phabricator.services.mozilla.com/D54016 --HG-- extra : moz-landing-system : lando --- dom/base/Document.cpp | 10 +- dom/base/Document.h | 2 + dom/xul/ChromeObserver.cpp | 263 +++++++++++++++++++++++++++++ dom/xul/ChromeObserver.h | 46 +++++ dom/xul/moz.build | 6 + dom/xul/nsXULElement.cpp | 210 ----------------------- dom/xul/nsXULElement.h | 15 +- dom/xul/nsXULPrototypeDocument.cpp | 1 + 8 files changed, 328 insertions(+), 225 deletions(-) create mode 100644 dom/xul/ChromeObserver.cpp create mode 100644 dom/xul/ChromeObserver.h diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 3081866bdcfb..5cca9fa34bc4 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -309,6 +309,7 @@ #include "mozilla/dom/SVGSVGElement.h" #include "mozilla/dom/DocGroup.h" #include "mozilla/dom/TabGroup.h" +#include "mozilla/dom/ChromeObserver.h" #ifdef MOZ_XUL # include "mozilla/dom/XULBroadcastManager.h" # include "mozilla/dom/XULPersist.h" @@ -11034,11 +11035,16 @@ void Document::SetReadyStateInternal(ReadyState aReadyState, } // At the time of loading start, we don't have timing object, record time. - if (READYSTATE_INTERACTIVE == aReadyState) { - if (!mXULPersist && nsContentUtils::IsSystemPrincipal(NodePrincipal())) { + if (READYSTATE_INTERACTIVE == aReadyState && + nsContentUtils::IsSystemPrincipal(NodePrincipal())) { + if (!mXULPersist) { mXULPersist = new XULPersist(this); mXULPersist->Init(); } + if (!mChromeObserver) { + mChromeObserver = new ChromeObserver(this); + mChromeObserver->Init(); + } } if (aUpdateTimingInformation) { diff --git a/dom/base/Document.h b/dom/base/Document.h index 4a5180bdaf35..53918d303d22 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -166,6 +166,7 @@ class AnonymousContent; class Attr; class XULBroadcastManager; class XULPersist; +class ChromeObserver; class ClientInfo; class ClientState; class CDATASection; @@ -5335,6 +5336,7 @@ class Document : public nsINode, RefPtr mXULBroadcastManager; RefPtr mXULPersist; + RefPtr mChromeObserver; RefPtr mAll; diff --git a/dom/xul/ChromeObserver.cpp b/dom/xul/ChromeObserver.cpp new file mode 100644 index 000000000000..86256cfafd0e --- /dev/null +++ b/dom/xul/ChromeObserver.cpp @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "ChromeObserver.h" + +#include "nsIBaseWindow.h" +#include "nsIWidget.h" +#include "nsIFrame.h" + +#include "nsContentUtils.h" +#include "nsView.h" +#include "nsPresContext.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentInlines.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/MutationEventBinding.h" +#include "nsXULElement.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_ISUPPORTS(ChromeObserver, nsIMutationObserver) + +ChromeObserver::ChromeObserver(Document* aDocument) + : nsStubMutationObserver(), mDocument(aDocument) {} + +ChromeObserver::~ChromeObserver() {} + +void ChromeObserver::Init() { + mDocument->AddMutationObserver(this); + Element* rootElement = mDocument->GetRootElement(); + if (!rootElement) { + return; + } + nsAutoScriptBlocker scriptBlocker; + uint32_t attributeCount = rootElement->GetAttrCount(); + for (uint32_t i = 0; i < attributeCount; i++) { + BorrowedAttrInfo info = rootElement->GetAttrInfoAt(i); + const nsAttrName* name = info.mName; + if (name->LocalName() == nsGkAtoms::chromemargin) { + // Some linux windows managers have an issue when the chrome margin is + // applied while the browser is loading (bug 1598848). For now, skip + // applying this attribute when initializing. + continue; + } + AttributeChanged(rootElement, name->NamespaceID(), name->LocalName(), + MutationEvent_Binding::ADDITION, nullptr); + } +} + +nsIWidget* ChromeObserver::GetWindowWidget() { + // only top level chrome documents can set the titlebar color + if (mDocument && mDocument->IsRootDisplayDocument()) { + nsCOMPtr container = mDocument->GetContainer(); + nsCOMPtr baseWindow = do_QueryInterface(container); + if (baseWindow) { + nsCOMPtr mainWidget; + baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); + return mainWidget; + } + } + return nullptr; +} + +class SetDrawInTitleBarEvent : public Runnable { + public: + SetDrawInTitleBarEvent(nsIWidget* aWidget, bool aState) + : mozilla::Runnable("SetDrawInTitleBarEvent"), + mWidget(aWidget), + mState(aState) {} + + NS_IMETHOD Run() override { + NS_ASSERTION(mWidget, + "You shouldn't call this runnable with a null widget!"); + + mWidget->SetDrawsInTitlebar(mState); + return NS_OK; + } + + private: + nsCOMPtr mWidget; + bool mState; +}; + +void ChromeObserver::SetDrawsInTitlebar(bool aState) { + nsIWidget* mainWidget = GetWindowWidget(); + if (mainWidget) { + nsContentUtils::AddScriptRunner( + new SetDrawInTitleBarEvent(mainWidget, aState)); + } +} + +void ChromeObserver::SetDrawsTitle(bool aState) { + nsIWidget* mainWidget = GetWindowWidget(); + if (mainWidget) { + // We can do this synchronously because SetDrawsTitle doesn't have any + // synchronous effects apart from a harmless invalidation. + mainWidget->SetDrawsTitle(aState); + } +} + +void ChromeObserver::UpdateBrightTitlebarForeground() { + nsIWidget* mainWidget = GetWindowWidget(); + if (mainWidget) { + // We can do this synchronously because SetBrightTitlebarForeground doesn't + // have any synchronous effects apart from a harmless invalidation. + mainWidget->SetUseBrightTitlebarForeground( + mDocument->GetDocumentLWTheme() == Document::Doc_Theme_Bright || + mDocument->GetRootElement()->AttrValueIs( + kNameSpaceID_None, nsGkAtoms::brighttitlebarforeground, + NS_LITERAL_STRING("true"), eCaseMatters)); + } +} + +class MarginSetter : public Runnable { + public: + explicit MarginSetter(nsIWidget* aWidget) + : mozilla::Runnable("MarginSetter"), + mWidget(aWidget), + mMargin(-1, -1, -1, -1) {} + MarginSetter(nsIWidget* aWidget, const LayoutDeviceIntMargin& aMargin) + : mozilla::Runnable("MarginSetter"), mWidget(aWidget), mMargin(aMargin) {} + + NS_IMETHOD Run() override { + // SetNonClientMargins can dispatch native events, hence doing + // it off a script runner. + mWidget->SetNonClientMargins(mMargin); + return NS_OK; + } + + private: + nsCOMPtr mWidget; + LayoutDeviceIntMargin mMargin; +}; + +void ChromeObserver::SetChromeMargins(const nsAttrValue* aValue) { + if (!aValue) return; + + nsIWidget* mainWidget = GetWindowWidget(); + if (!mainWidget) return; + + // top, right, bottom, left - see nsAttrValue + nsIntMargin margins; + bool gotMargins = false; + + if (aValue->Type() == nsAttrValue::eIntMarginValue) { + gotMargins = aValue->GetIntMarginValue(margins); + } else { + nsAutoString tmp; + aValue->ToString(tmp); + gotMargins = nsContentUtils::ParseIntMarginValue(tmp, margins); + } + if (gotMargins) { + nsContentUtils::AddScriptRunner(new MarginSetter( + mainWidget, LayoutDeviceIntMargin::FromUnknownMargin(margins))); + } +} + +void ChromeObserver::AttributeChanged(dom::Element* aElement, + int32_t aNamespaceID, nsAtom* aName, + int32_t aModType, + const nsAttrValue* aOldValue) { + // We only care about changes to the root element. + if (!mDocument || aElement != mDocument->GetRootElement()) { + return; + } + + const nsAttrValue* value = aElement->GetParsedAttr(aName, aNamespaceID); + if (value) { + // Hide chrome if needed + if (aName == nsGkAtoms::hidechrome) { + HideWindowChrome(value->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); + } else if (aName == nsGkAtoms::chromemargin) { + SetChromeMargins(value); + } else if (aName == nsGkAtoms::windowtype && aElement->IsXULElement()) { + RefPtr xulElement = nsXULElement::FromNodeOrNull(aElement); + xulElement->MaybeUpdatePrivateLifetime(); + } + // title and drawintitlebar are settable on + // any root node (windows, dialogs, etc) + else if (aName == nsGkAtoms::title) { + mDocument->NotifyPossibleTitleChange(false); + } else if (aName == nsGkAtoms::drawintitlebar) { + SetDrawsInTitlebar( + value->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); + } else if (aName == nsGkAtoms::drawtitle) { + SetDrawsTitle(value->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); + } else if (aName == nsGkAtoms::localedir) { + // if the localedir changed on the root element, reset the document + // direction + mDocument->ResetDocumentDirection(); + } else if (aName == nsGkAtoms::lwtheme || + aName == nsGkAtoms::lwthemetextcolor) { + // if the lwtheme changed, make sure to reset the document lwtheme + // cache + mDocument->ResetDocumentLWTheme(); + UpdateBrightTitlebarForeground(); + } else if (aName == nsGkAtoms::brighttitlebarforeground) { + UpdateBrightTitlebarForeground(); + } + } else { + if (aName == nsGkAtoms::hidechrome) { + HideWindowChrome(false); + } else if (aName == nsGkAtoms::chromemargin) { + ResetChromeMargins(); + } else if (aName == nsGkAtoms::localedir) { + // if the localedir changed on the root element, reset the document + // direction + mDocument->ResetDocumentDirection(); + } else if ((aName == nsGkAtoms::lwtheme || + aName == nsGkAtoms::lwthemetextcolor)) { + // if the lwtheme changed, make sure to restyle appropriately + mDocument->ResetDocumentLWTheme(); + UpdateBrightTitlebarForeground(); + } else if (aName == nsGkAtoms::brighttitlebarforeground) { + UpdateBrightTitlebarForeground(); + } else if (aName == nsGkAtoms::drawintitlebar) { + SetDrawsInTitlebar(false); + } else if (aName == nsGkAtoms::drawtitle) { + SetDrawsTitle(false); + } + } +} + +void ChromeObserver::NodeWillBeDestroyed(const nsINode* aNode) { + mDocument = nullptr; +} + +void ChromeObserver::ResetChromeMargins() { + nsIWidget* mainWidget = GetWindowWidget(); + if (!mainWidget) return; + // See nsIWidget + nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget)); +} + +nsresult ChromeObserver::HideWindowChrome(bool aShouldHide) { + // only top level chrome documents can hide the window chrome + if (!mDocument->IsRootDisplayDocument()) return NS_OK; + + nsPresContext* presContext = mDocument->GetPresContext(); + + if (presContext && presContext->IsChrome()) { + nsIFrame* frame = mDocument->GetDocumentElement()->GetPrimaryFrame(); + + if (frame) { + nsView* view = frame->GetClosestView(); + + if (view) { + nsIWidget* w = view->GetWidget(); + NS_ENSURE_STATE(w); + w->HideWindowChrome(aShouldHide); + } + } + } + + return NS_OK; +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/xul/ChromeObserver.h b/dom/xul/ChromeObserver.h new file mode 100644 index 000000000000..d974e7e35ef1 --- /dev/null +++ b/dom/xul/ChromeObserver.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_ChromeObserver_h +#define mozilla_dom_ChromeObserver_h + +#include "nsStubMutationObserver.h" + +class nsIWidget; + +namespace mozilla { +namespace dom { +class Document; + +class ChromeObserver final : public nsStubMutationObserver { + public: + NS_DECL_ISUPPORTS + + explicit ChromeObserver(Document* aDocument); + void Init(); + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + protected: + nsIWidget* GetWindowWidget(); + void SetDrawsInTitlebar(bool aState); + void SetDrawsTitle(bool aState); + void UpdateBrightTitlebarForeground(); + void SetChromeMargins(const nsAttrValue* aValue); + nsresult HideWindowChrome(bool aShouldHide); + + private: + void ResetChromeMargins(); + ~ChromeObserver(); + // A weak pointer cleared when the element will be destroyed. + Document* MOZ_NON_OWNING_REF mDocument; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_ChromeObserver_h diff --git a/dom/xul/moz.build b/dom/xul/moz.build index 6f02f7e71318..39b5de3d48ce 100644 --- a/dom/xul/moz.build +++ b/dom/xul/moz.build @@ -58,7 +58,13 @@ XPIDL_SOURCES += [ XPIDL_MODULE = 'xul' +EXPORTS.mozilla.dom += [ + 'ChromeObserver.h', +] + + UNIFIED_SOURCES += [ + 'ChromeObserver.cpp', 'nsXULControllers.cpp', ] diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index 2b9eebe024c4..fe896d832aae 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -771,73 +771,6 @@ nsresult nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, if (aNamespaceID == kNameSpaceID_None) { if (aValue) { AddListenerForAttributeIfNeeded(aName); - Document* document = GetUncomposedDoc(); - - // Hide chrome if needed - if (mNodeInfo->Equals(nsGkAtoms::window)) { - if (aName == nsGkAtoms::hidechrome) { - HideWindowChrome( - aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); - } else if (aName == nsGkAtoms::chromemargin) { - SetChromeMargins(aValue); - } else if (aName == nsGkAtoms::windowtype && document && - document->GetRootElement() == this) { - MaybeUpdatePrivateLifetime(); - } - } - // title and drawintitlebar are settable on - // any root node (windows, dialogs, etc) - if (document && document->GetRootElement() == this) { - if (aName == nsGkAtoms::title) { - document->NotifyPossibleTitleChange(false); - } else if (aName == nsGkAtoms::drawintitlebar) { - SetDrawsInTitlebar( - aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); - } else if (aName == nsGkAtoms::drawtitle) { - SetDrawsTitle( - aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); - } else if (aName == nsGkAtoms::localedir) { - // if the localedir changed on the root element, reset the document - // direction - document->ResetDocumentDirection(); - } else if (aName == nsGkAtoms::lwtheme || - aName == nsGkAtoms::lwthemetextcolor) { - // if the lwtheme changed, make sure to reset the document lwtheme - // cache - document->ResetDocumentLWTheme(); - UpdateBrightTitlebarForeground(document); - } else if (aName == nsGkAtoms::brighttitlebarforeground) { - UpdateBrightTitlebarForeground(document); - } - } - } else { - if (mNodeInfo->Equals(nsGkAtoms::window)) { - if (aName == nsGkAtoms::hidechrome) { - HideWindowChrome(false); - } else if (aName == nsGkAtoms::chromemargin) { - ResetChromeMargins(); - } - } - - Document* doc = GetUncomposedDoc(); - if (doc && doc->GetRootElement() == this) { - if (aName == nsGkAtoms::localedir) { - // if the localedir changed on the root element, reset the document - // direction - doc->ResetDocumentDirection(); - } else if ((aName == nsGkAtoms::lwtheme || - aName == nsGkAtoms::lwthemetextcolor)) { - // if the lwtheme changed, make sure to restyle appropriately - doc->ResetDocumentLWTheme(); - UpdateBrightTitlebarForeground(doc); - } else if (aName == nsGkAtoms::brighttitlebarforeground) { - UpdateBrightTitlebarForeground(doc); - } else if (aName == nsGkAtoms::drawintitlebar) { - SetDrawsInTitlebar(false); - } else if (aName == nsGkAtoms::drawtitle) { - SetDrawsTitle(false); - } - } } if (aName == nsGkAtoms::tooltip || aName == nsGkAtoms::tooltiptext) { @@ -1192,149 +1125,6 @@ nsresult nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype) { return NS_OK; } -nsresult nsXULElement::HideWindowChrome(bool aShouldHide) { - Document* doc = GetUncomposedDoc(); - if (!doc || doc->GetRootElement() != this) return NS_ERROR_UNEXPECTED; - - // only top level chrome documents can hide the window chrome - if (!doc->IsRootDisplayDocument()) return NS_OK; - - nsPresContext* presContext = doc->GetPresContext(); - - if (presContext && presContext->IsChrome()) { - nsIFrame* frame = GetPrimaryFrame(); - - if (frame) { - nsView* view = frame->GetClosestView(); - - if (view) { - nsIWidget* w = view->GetWidget(); - NS_ENSURE_STATE(w); - w->HideWindowChrome(aShouldHide); - } - } - } - - return NS_OK; -} - -nsIWidget* nsXULElement::GetWindowWidget() { - Document* doc = GetComposedDoc(); - - // only top level chrome documents can set the titlebar color - if (doc && doc->IsRootDisplayDocument()) { - nsCOMPtr container = doc->GetContainer(); - nsCOMPtr baseWindow = do_QueryInterface(container); - if (baseWindow) { - nsCOMPtr mainWidget; - baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); - return mainWidget; - } - } - return nullptr; -} - -class SetDrawInTitleBarEvent : public Runnable { - public: - SetDrawInTitleBarEvent(nsIWidget* aWidget, bool aState) - : mozilla::Runnable("SetDrawInTitleBarEvent"), - mWidget(aWidget), - mState(aState) {} - - NS_IMETHOD Run() override { - NS_ASSERTION(mWidget, - "You shouldn't call this runnable with a null widget!"); - - mWidget->SetDrawsInTitlebar(mState); - return NS_OK; - } - - private: - nsCOMPtr mWidget; - bool mState; -}; - -void nsXULElement::SetDrawsInTitlebar(bool aState) { - nsIWidget* mainWidget = GetWindowWidget(); - if (mainWidget) { - nsContentUtils::AddScriptRunner( - new SetDrawInTitleBarEvent(mainWidget, aState)); - } -} - -void nsXULElement::SetDrawsTitle(bool aState) { - nsIWidget* mainWidget = GetWindowWidget(); - if (mainWidget) { - // We can do this synchronously because SetDrawsTitle doesn't have any - // synchronous effects apart from a harmless invalidation. - mainWidget->SetDrawsTitle(aState); - } -} - -void nsXULElement::UpdateBrightTitlebarForeground(Document* aDoc) { - nsIWidget* mainWidget = GetWindowWidget(); - if (mainWidget) { - // We can do this synchronously because SetBrightTitlebarForeground doesn't - // have any synchronous effects apart from a harmless invalidation. - mainWidget->SetUseBrightTitlebarForeground( - aDoc->GetDocumentLWTheme() == Document::Doc_Theme_Bright || - aDoc->GetRootElement()->AttrValueIs( - kNameSpaceID_None, nsGkAtoms::brighttitlebarforeground, - NS_LITERAL_STRING("true"), eCaseMatters)); - } -} - -class MarginSetter : public Runnable { - public: - explicit MarginSetter(nsIWidget* aWidget) - : mozilla::Runnable("MarginSetter"), - mWidget(aWidget), - mMargin(-1, -1, -1, -1) {} - MarginSetter(nsIWidget* aWidget, const LayoutDeviceIntMargin& aMargin) - : mozilla::Runnable("MarginSetter"), mWidget(aWidget), mMargin(aMargin) {} - - NS_IMETHOD Run() override { - // SetNonClientMargins can dispatch native events, hence doing - // it off a script runner. - mWidget->SetNonClientMargins(mMargin); - return NS_OK; - } - - private: - nsCOMPtr mWidget; - LayoutDeviceIntMargin mMargin; -}; - -void nsXULElement::SetChromeMargins(const nsAttrValue* aValue) { - if (!aValue) return; - - nsIWidget* mainWidget = GetWindowWidget(); - if (!mainWidget) return; - - // top, right, bottom, left - see nsAttrValue - nsIntMargin margins; - bool gotMargins = false; - - if (aValue->Type() == nsAttrValue::eIntMarginValue) { - gotMargins = aValue->GetIntMarginValue(margins); - } else { - nsAutoString tmp; - aValue->ToString(tmp); - gotMargins = nsContentUtils::ParseIntMarginValue(tmp, margins); - } - if (gotMargins) { - nsContentUtils::AddScriptRunner(new MarginSetter( - mainWidget, LayoutDeviceIntMargin::FromUnknownMargin(margins))); - } -} - -void nsXULElement::ResetChromeMargins() { - nsIWidget* mainWidget = GetWindowWidget(); - if (!mainWidget) return; - // See nsIWidget - nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget)); -} - bool nsXULElement::BoolAttrIsTrue(nsAtom* aName) const { const nsAttrValue* attr = GetAttrInfo(kNameSpaceID_None, aName).mValue; diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 86582684ce17..135c84abfe20 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -512,6 +512,8 @@ class nsXULElement : public nsStyledElement { bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override; + void MaybeUpdatePrivateLifetime(); + protected: ~nsXULElement(); @@ -553,17 +555,6 @@ class nsXULElement : public nsStyledElement { void AddListenerForAttributeIfNeeded(const nsAttrName& aName); void AddListenerForAttributeIfNeeded(nsAtom* aLocalName); - nsIWidget* GetWindowWidget(); - - // attribute setters for widget - nsresult HideWindowChrome(bool aShouldHide); - void SetChromeMargins(const nsAttrValue* aValue); - void ResetChromeMargins(); - - void SetDrawsInTitlebar(bool aState); - void SetDrawsTitle(bool aState); - void UpdateBrightTitlebarForeground(Document* aDocument); - protected: void AddTooltipSupport(); void RemoveTooltipSupport(); @@ -595,8 +586,6 @@ class nsXULElement : public nsStyledElement { virtual JSObject* WrapNode(JSContext* aCx, JS::Handle aGivenProto) override; - void MaybeUpdatePrivateLifetime(); - bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage); MOZ_CAN_RUN_SCRIPT diff --git a/dom/xul/nsXULPrototypeDocument.cpp b/dom/xul/nsXULPrototypeDocument.cpp index e99611d25f8a..2aa42ea03c51 100644 --- a/dom/xul/nsXULPrototypeDocument.cpp +++ b/dom/xul/nsXULPrototypeDocument.cpp @@ -5,6 +5,7 @@ #include "nsXULPrototypeDocument.h" +#include "nsXULElement.h" #include "nsAString.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h"