diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..af9c916cd0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,36 @@ +# Security Policy + +## What is or is not a vulnerability? + +In general, vulnerabilities are those bugs that can actually be exploited to perform malicious tasks. +Most _crashes_ are not security vulnerabilities. Although important to fix, they don't inherently cause a problem for the +browser's security. + +What should be considered vulnerabilities or security hazards by default: +- Use-after-free crashes, since those can potentially be used for remote code execution; +- Spoofing issues in the UI; +- File security issues, like out-of-bounds access to arbitrary files or locations; +- Type confusion issues; +- Bypass of security measures like CSP or the various mechanisms around HTTPS. + +Generally not security vulnerabilities: +- Null dereferencing crashes; +- Malware extensions (but please do report those on the forum in the extensions board!); +- Denial-of-service (AKA "evil trap sites") +- Browser hangs +- Issues with non-standard manual configuration (either at build time or by manipulating about:config directly) + +## Reporting a Vulnerability + +If you find an issue in UXP or the applications it builds on that could impact the security or safety of users please **do not** +make an issue on GitHub about it. GitHub does not support restricted viewability for security sensitive bugs. + +If you want to report a security-sensitive issue then please go to the [forum](https://forum.palemoon.org) and report the issue +via a **private message** to **Moonchild** (the founder and prime responsible for security issues). +The forum's private message system is fully secure since your visits are encrypted and private messages are not available to anyone +except the recipient (not even moderators!). + +You will be informed via private message if the vulnerability report is accepted or declined, with reasoning. +Security updates occur regularly and are given priority over most other development tasks. In general, they can be solved +relatively quickly and will be included in the next point release (third digit if not rolled into a more major one). + diff --git a/application/basilisk/base/content/browser.css b/application/basilisk/base/content/browser.css index a2c2559d6f..776cea1104 100644 --- a/application/basilisk/base/content/browser.css +++ b/application/basilisk/base/content/browser.css @@ -205,7 +205,7 @@ toolbar[customizing] > .overflow-button { display: none; } -%ifdef CAN_DRAW_IN_TITLEBAR +%ifdef MOZ_CAN_DRAW_IN_TITLEBAR #main-window:not([chromemargin]) > #titlebar, #main-window[inFullscreen] > #titlebar, #main-window[inFullscreen] .titlebar-placeholder, diff --git a/application/basilisk/base/content/browser.xul b/application/basilisk/base/content/browser.xul index cef643ebc7..2aeb9b842e 100644 --- a/application/basilisk/base/content/browser.xul +++ b/application/basilisk/base/content/browser.xul @@ -45,7 +45,7 @@ titlemodifier_normal="&mainWindow.titlemodifier;" titlemodifier_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;" #endif -#ifdef CAN_DRAW_IN_TITLEBAR +#ifdef MOZ_CAN_DRAW_IN_TITLEBAR #ifdef XP_WIN chromemargin="0,2,2,2" #else @@ -388,7 +388,7 @@ onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/> -#ifdef CAN_DRAW_IN_TITLEBAR +#ifdef MOZ_CAN_DRAW_IN_TITLEBAR @@ -437,7 +437,7 @@ #include browser-menubar.inc -#ifdef CAN_DRAW_IN_TITLEBAR +#ifdef MOZ_CAN_DRAW_IN_TITLEBAR #ifndef XP_MACOSX #endif -#ifdef CAN_DRAW_IN_TITLEBAR +#ifdef MOZ_CAN_DRAW_IN_TITLEBAR -#ifdef CAN_DRAW_IN_TITLEBAR +#ifdef MOZ_CAN_DRAW_IN_TITLEBAR - - -
- - - - diff --git a/dom/tests/mochitest/webcomponents/test_document_shared_registry.html b/dom/tests/mochitest/webcomponents/test_document_shared_registry.html deleted file mode 100644 index db72e1e6ca..0000000000 --- a/dom/tests/mochitest/webcomponents/test_document_shared_registry.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - Test shared registry for associated HTML documents. - - - - -
-Bug 783129 - - - diff --git a/dom/tests/mochitest/webcomponents/test_dynamic_content_element_matching.html b/dom/tests/mochitest/webcomponents/test_dynamic_content_element_matching.html deleted file mode 100644 index c9af76610c..0000000000 --- a/dom/tests/mochitest/webcomponents/test_dynamic_content_element_matching.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Test for dynamic changes to content matching content elements - - - - -
-Bug 806506 - - - - diff --git a/dom/tests/mochitest/webcomponents/test_event_dispatch.html b/dom/tests/mochitest/webcomponents/test_event_dispatch.html deleted file mode 100644 index c73bfb214e..0000000000 --- a/dom/tests/mochitest/webcomponents/test_event_dispatch.html +++ /dev/null @@ -1,458 +0,0 @@ - - - - - Test for event model in web components - - - - -Bug 887541 - - - diff --git a/dom/tests/mochitest/webcomponents/test_fallback_dest_insertion_points.html b/dom/tests/mochitest/webcomponents/test_fallback_dest_insertion_points.html deleted file mode 100644 index 4eefa165f2..0000000000 --- a/dom/tests/mochitest/webcomponents/test_fallback_dest_insertion_points.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - Test for Bug 999999 - - - - -Mozilla Bug 999999 -

-
-
-
-
-
- - - diff --git a/dom/tests/mochitest/webcomponents/test_nested_content_element.html b/dom/tests/mochitest/webcomponents/test_nested_content_element.html deleted file mode 100644 index 1d98d2996b..0000000000 --- a/dom/tests/mochitest/webcomponents/test_nested_content_element.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - Test for HTMLContent element - - - - -
-Bug 806506 - - - - diff --git a/dom/tests/mochitest/webcomponents/test_shadowroot_host.html b/dom/tests/mochitest/webcomponents/test_shadowroot_host.html deleted file mode 100644 index f48d63e87d..0000000000 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_host.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - Test for Bug 1083587 - - - - -Mozilla Bug 1083587 -

- -
-
- - - diff --git a/dom/tests/mochitest/webcomponents/test_shadowroot_style_multiple_shadow.html b/dom/tests/mochitest/webcomponents/test_shadowroot_style_multiple_shadow.html deleted file mode 100644 index 7a606bcd7f..0000000000 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_style_multiple_shadow.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Test for ShadowRoot styles with multiple ShadowRoot on host. - - - - -
-
-Bug 806506 - - - - diff --git a/dom/tests/mochitest/webcomponents/test_shadowroot_youngershadowroot.html b/dom/tests/mochitest/webcomponents/test_shadowroot_youngershadowroot.html deleted file mode 100644 index 17743321bc..0000000000 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_youngershadowroot.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - Test for Bug 1083587 - - - - -Mozilla Bug 1083587 -

- -
-
- - - diff --git a/dom/tests/mochitest/webcomponents/test_template_custom_elements.html b/dom/tests/mochitest/webcomponents/test_template_custom_elements.html deleted file mode 100644 index f7f4340cf4..0000000000 --- a/dom/tests/mochitest/webcomponents/test_template_custom_elements.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Test for custom elements in template - - - - - -Bug 1091425 - - - - diff --git a/dom/tests/mochitest/webcomponents/test_unresolved_pseudo_class.html b/dom/tests/mochitest/webcomponents/test_unresolved_pseudo_class.html deleted file mode 100644 index 3e1fae8ee8..0000000000 --- a/dom/tests/mochitest/webcomponents/test_unresolved_pseudo_class.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Test template element in stale document. - - - - - -Bug 1111633 -
- -This text should be green - - - - - - diff --git a/dom/webidl/AnonymousContent.webidl b/dom/webidl/AnonymousContent.webidl index 6755fe598a..8be69cd26f 100644 --- a/dom/webidl/AnonymousContent.webidl +++ b/dom/webidl/AnonymousContent.webidl @@ -77,4 +77,12 @@ interface AnonymousContent { [Throws] void setCutoutRectsForElement(DOMString elementId, sequence rects); + + /** + * Get the computed value of a property on an element inside this custom + * anonymous content. + */ + [Throws] + DOMString? getComputedStylePropertyValue(DOMString elementId, + DOMString propertyName); }; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index b28903ae23..ba2ec17ea7 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -17,6 +17,9 @@ enum VisibilityState { "hidden", "visible", "prerender" }; /* https://dom.spec.whatwg.org/#dictdef-elementcreationoptions */ dictionary ElementCreationOptions { DOMString is; + + [ChromeOnly] + DOMString pseudo; }; /* http://dom.spec.whatwg.org/#interface-document */ @@ -268,13 +271,6 @@ partial interface Document { attribute EventHandler onpointerlockerror; }; -//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register -partial interface Document { - // this is deprecated from CustomElements v0 - [Throws, Func="CustomElementRegistry::IsCustomElementEnabled"] - object registerElement(DOMString name, optional ElementRegistrationOptions options); -}; - // https://w3c.github.io/page-visibility/#extensions-to-the-document-interface partial interface Document { [Pref="dom.visibilityAPI.enabled"] diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl index a6b2bfdd5c..d5cac7c647 100644 --- a/dom/webidl/Element.webidl +++ b/dom/webidl/Element.webidl @@ -228,14 +228,26 @@ partial interface Element { NodeList querySelectorAll(DOMString selectors); }; -// http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-element-interface +// https://dom.spec.whatwg.org/#dictdef-shadowrootinit +dictionary ShadowRootInit { + required ShadowRootMode mode; +}; + +// https://dom.spec.whatwg.org/#element partial interface Element { - [Throws,Func="nsDocument::IsWebComponentsEnabled"] - ShadowRoot createShadowRoot(); - [Func="nsDocument::IsWebComponentsEnabled"] - NodeList getDestinationInsertionPoints(); - [Func="nsDocument::IsWebComponentsEnabled"] + // Shadow DOM v1 + [Throws, Func="nsDocument::IsWebComponentsEnabled"] + ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict); + [BinaryName="shadowRootByMode", Func="nsDocument::IsWebComponentsEnabled"] readonly attribute ShadowRoot? shadowRoot; + [BinaryName="assignedSlotByMode", Func="nsDocument::IsWebComponentsEnabled"] + readonly attribute HTMLSlotElement? assignedSlot; + [CEReactions, Unscopable, SetterThrows, Func="nsDocument::IsWebComponentsEnabled"] + attribute DOMString slot; + + // [deprecated] Shadow DOM v0 + [Throws, Func="nsDocument::IsWebComponentsEnabled"] + ShadowRoot createShadowRoot(); }; Element implements ChildNode; diff --git a/dom/webidl/Event.webidl b/dom/webidl/Event.webidl index a5d7da7d43..8a8e71c43b 100644 --- a/dom/webidl/Event.webidl +++ b/dom/webidl/Event.webidl @@ -22,6 +22,8 @@ interface Event { [Pure] readonly attribute EventTarget? currentTarget; + sequence composedPath(); + const unsigned short NONE = 0; const unsigned short CAPTURING_PHASE = 1; const unsigned short AT_TARGET = 2; diff --git a/dom/webidl/HTMLContentElement.webidl b/dom/webidl/HTMLContentElement.webidl deleted file mode 100644 index ea809f120c..0000000000 --- a/dom/webidl/HTMLContentElement.webidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html - * - * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and - * Opera Software ASA. You are granted a license to use, reproduce - * and create derivative works of this document. - */ - -[Func="nsDocument::IsWebComponentsEnabled"] -interface HTMLContentElement : HTMLElement -{ - attribute DOMString select; - NodeList getDistributedNodes(); -}; - diff --git a/dom/webidl/HTMLShadowElement.webidl b/dom/webidl/HTMLSlotElement.webidl similarity index 57% rename from dom/webidl/HTMLShadowElement.webidl rename to dom/webidl/HTMLSlotElement.webidl index f72cd06e18..24dfcf3508 100644 --- a/dom/webidl/HTMLShadowElement.webidl +++ b/dom/webidl/HTMLSlotElement.webidl @@ -4,16 +4,19 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html + * https://html.spec.whatwg.org/multipage/forms.html#the-dialog-element * * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and * Opera Software ASA. You are granted a license to use, reproduce * and create derivative works of this document. */ -[Func="nsDocument::IsWebComponentsEnabled"] -interface HTMLShadowElement : HTMLElement -{ - readonly attribute ShadowRoot? olderShadowRoot; +[Func="nsDocument::IsWebComponentsEnabled", Exposed=Window, HTMLConstructor] +interface HTMLSlotElement : HTMLElement { + [CEReactions, SetterThrows] attribute DOMString name; + sequence assignedNodes(optional AssignedNodesOptions options); }; +dictionary AssignedNodesOptions { + boolean flatten = false; +}; \ No newline at end of file diff --git a/dom/webidl/ShadowRoot.webidl b/dom/webidl/ShadowRoot.webidl index 8dd069244c..47e6cf5ec5 100644 --- a/dom/webidl/ShadowRoot.webidl +++ b/dom/webidl/ShadowRoot.webidl @@ -10,17 +10,27 @@ * liability, trademark and document use rules apply. */ +// https://dom.spec.whatwg.org/#enumdef-shadowrootmode +enum ShadowRootMode { + "open", + "closed" +}; + +// https://dom.spec.whatwg.org/#shadowroot [Func="nsDocument::IsWebComponentsEnabled"] interface ShadowRoot : DocumentFragment { + // Shadow DOM v1 + readonly attribute ShadowRootMode mode; + readonly attribute Element host; + + // [deprecated] Shadow DOM v0 Element? getElementById(DOMString elementId); HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString innerHTML; - readonly attribute Element host; - readonly attribute ShadowRoot? olderShadowRoot; attribute boolean applyAuthorStyles; readonly attribute StyleSheetList styleSheets; }; diff --git a/dom/webidl/Text.webidl b/dom/webidl/Text.webidl index dcd25cec3a..fb7b5d6857 100644 --- a/dom/webidl/Text.webidl +++ b/dom/webidl/Text.webidl @@ -18,4 +18,9 @@ interface Text : CharacterData { readonly attribute DOMString wholeText; }; +partial interface Text { + [BinaryName="assignedSlotByMode", Func="nsTextNode::IsWebComponentsEnabled"] + readonly attribute HTMLSlotElement? assignedSlot; +}; + Text implements GeometryUtils; diff --git a/dom/webidl/WebComponents.webidl b/dom/webidl/WebComponents.webidl index f9bb8214af..9c5e53131b 100644 --- a/dom/webidl/WebComponents.webidl +++ b/dom/webidl/WebComponents.webidl @@ -25,8 +25,3 @@ dictionary LifecycleCallbacks { LifecycleAdoptedCallback? adoptedCallback; LifecycleAttributeChangedCallback? attributeChangedCallback; }; - -dictionary ElementRegistrationOptions { - object? prototype = null; - DOMString? extends = null; -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 0299ea4207..7640c03d8c 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -177,7 +177,6 @@ WEBIDL_FILES = [ 'HTMLButtonElement.webidl', 'HTMLCanvasElement.webidl', 'HTMLCollection.webidl', - 'HTMLContentElement.webidl', 'HTMLDataElement.webidl', 'HTMLDataListElement.webidl', 'HTMLDetailsElement.webidl', @@ -226,7 +225,7 @@ WEBIDL_FILES = [ 'HTMLQuoteElement.webidl', 'HTMLScriptElement.webidl', 'HTMLSelectElement.webidl', - 'HTMLShadowElement.webidl', + 'HTMLSlotElement.webidl', 'HTMLSourceElement.webidl', 'HTMLSpanElement.webidl', 'HTMLStyleElement.webidl', diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 99bb503397..71c644405c 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -181,7 +181,7 @@ SharedWorker::WrapObject(JSContext* aCx, JS::Handle aGivenProto) } nsresult -SharedWorker::PreHandleEvent(EventChainPreVisitor& aVisitor) +SharedWorker::GetEventTargetParent(EventChainPreVisitor& aVisitor) { AssertIsOnMainThread(); @@ -196,9 +196,9 @@ SharedWorker::PreHandleEvent(EventChainPreVisitor& aVisitor) QueueEvent(event); aVisitor.mCanHandle = false; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } - return DOMEventTargetHelper::PreHandleEvent(aVisitor); + return DOMEventTargetHelper::GetEventTargetParent(aVisitor); } diff --git a/dom/workers/SharedWorker.h b/dom/workers/SharedWorker.h index 220436e4dc..4b50d39e85 100644 --- a/dom/workers/SharedWorker.h +++ b/dom/workers/SharedWorker.h @@ -76,7 +76,7 @@ public: WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; virtual nsresult - PreHandleEvent(EventChainPreVisitor& aVisitor) override; + GetEventTargetParent(EventChainPreVisitor& aVisitor) override; WorkerPrivate* GetWorkerPrivate() const diff --git a/dom/xbl/XBLChildrenElement.cpp b/dom/xbl/XBLChildrenElement.cpp index e4058a7890..f785a3058a 100644 --- a/dom/xbl/XBLChildrenElement.cpp +++ b/dom/xbl/XBLChildrenElement.cpp @@ -7,6 +7,7 @@ #include "mozilla/dom/XBLChildrenElement.h" #include "nsCharSeparatedTokenizer.h" #include "mozilla/dom/NodeListBinding.h" +#include "nsAttrValueOrString.h" namespace mozilla { namespace dom { @@ -27,34 +28,24 @@ NS_INTERFACE_MAP_END_INHERITING(Element) NS_IMPL_ELEMENT_CLONE(XBLChildrenElement) nsresult -XBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) +XBLChildrenElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) { - if (aAttribute == nsGkAtoms::includes && - aNameSpaceID == kNameSpaceID_None) { - mIncludes.Clear(); - } - - return Element::UnsetAttr(aNameSpaceID, aAttribute, aNotify); -} - -bool -XBLChildrenElement::ParseAttribute(int32_t aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult) -{ - if (aAttribute == nsGkAtoms::includes && - aNamespaceID == kNameSpaceID_None) { - mIncludes.Clear(); - nsCharSeparatedTokenizer tok(aValue, '|', - nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); - while (tok.hasMoreTokens()) { - mIncludes.AppendElement(NS_Atomize(tok.nextToken())); + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::includes) { + mIncludes.Clear(); + if (aValue) { + nsCharSeparatedTokenizer tok(aValue->String(), '|', + nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); + while (tok.hasMoreTokens()) { + mIncludes.AppendElement(NS_Atomize(tok.nextToken())); + } + } } } - return false; + return nsXMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify); } } // namespace dom diff --git a/dom/xbl/XBLChildrenElement.h b/dom/xbl/XBLChildrenElement.h index 4714da4a84..c010854742 100644 --- a/dom/xbl/XBLChildrenElement.h +++ b/dom/xbl/XBLChildrenElement.h @@ -37,14 +37,6 @@ public: virtual nsIDOMNode* AsDOMNode() override { return this; } - // nsIContent interface methods - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; - virtual bool ParseAttribute(int32_t aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult) override; - void AppendInsertedChild(nsIContent* aChild) { mInsertedChildren.AppendElement(aChild); @@ -147,6 +139,10 @@ public: protected: ~XBLChildrenElement(); + virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; + private: nsTArray mInsertedChildren; // WEAK nsTArray > mIncludes; diff --git a/dom/xbl/nsXBLService.cpp b/dom/xbl/nsXBLService.cpp index 1475b1368d..b50b2c6fe3 100644 --- a/dom/xbl/nsXBLService.cpp +++ b/dom/xbl/nsXBLService.cpp @@ -115,45 +115,19 @@ public: if (!doc) return; - // Destroy the frames for mBoundElement. - nsIContent* destroyedFramesFor = nullptr; - nsIPresShell* shell = doc->GetShell(); - if (shell) { - shell->DestroyFramesFor(mBoundElement, &destroyedFramesFor); - } - MOZ_ASSERT(!mBoundElement->GetPrimaryFrame()); - // Get the binding. bool ready = false; nsXBLService::GetInstance()->BindingReady(mBoundElement, mBindingURI, &ready); if (!ready) return; - // If |mBoundElement| is (in addition to having binding |mBinding|) - // also a descendant of another element with binding |mBinding|, - // then we might have just constructed it due to the - // notification of its parent. (We can know about both if the - // binding loads were triggered from the DOM rather than frame - // construction.) So we have to check both whether the element - // has a primary frame and whether it's in the frame manager maps - // before sending a ContentInserted notification, or bad things - // will happen. - MOZ_ASSERT(shell == doc->GetShell()); - if (shell) { - nsIFrame* childFrame = mBoundElement->GetPrimaryFrame(); - if (!childFrame) { - // Check to see if it's in the undisplayed content map... - nsFrameManager* fm = shell->FrameManager(); - nsStyleContext* sc = fm->GetUndisplayedContent(mBoundElement); - if (!sc) { - // or in the display:contents map. - sc = fm->GetDisplayContentsStyleFor(mBoundElement); - } - if (!sc) { - shell->CreateFramesFor(destroyedFramesFor); - } - } + // Destroy the frames for mBoundElement. Do this after getting the binding, + // since if the binding fetch fails then we don't want to destroy the + // frames. + if (nsIPresShell* shell = doc->GetShell()) { + shell->DestroyFramesForAndRestyle(mBoundElement->AsElement()); } + MOZ_ASSERT(!mBoundElement->GetPrimaryFrame()); } nsXBLBindingRequest(nsIURI* aURI, nsIContent* aBoundElement) diff --git a/dom/xml/nsXMLElement.cpp b/dom/xml/nsXMLElement.cpp index 45163a1c42..ad0314f4ca 100644 --- a/dom/xml/nsXMLElement.cpp +++ b/dom/xml/nsXMLElement.cpp @@ -9,6 +9,7 @@ #include "mozilla/dom/ElementInlines.h" #include "nsContentUtils.h" // nsAutoScriptBlocker +using namespace mozilla; using namespace mozilla::dom; nsresult @@ -29,4 +30,26 @@ nsXMLElement::WrapNode(JSContext *aCx, JS::Handle aGivenProto) return ElementBinding::Wrap(aCx, this, aGivenProto); } +void +nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent) +{ + CSSPseudoElementType pseudoType = GetPseudoElementType(); + bool isBefore = pseudoType == CSSPseudoElementType::before; + nsIAtom* property = isBefore + ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty; + + switch (pseudoType) { + case CSSPseudoElementType::before: + case CSSPseudoElementType::after: { + MOZ_ASSERT(GetParent()); + MOZ_ASSERT(GetParent()->IsElement()); + GetParent()->DeleteProperty(property); + break; + } + default: + break; + } + Element::UnbindFromTree(aDeep, aNullParent); +} + NS_IMPL_ELEMENT_CLONE(nsXMLElement) diff --git a/dom/xml/nsXMLElement.h b/dom/xml/nsXMLElement.h index d16b82f399..85f79970cd 100644 --- a/dom/xml/nsXMLElement.h +++ b/dom/xml/nsXMLElement.h @@ -35,6 +35,9 @@ public: virtual nsIDOMNode* AsDOMNode() override { return this; } + virtual void UnbindFromTree(bool aDeep = true, + bool aNullParent = true) override; + protected: virtual ~nsXMLElement() {} diff --git a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp index facb435b4c..0a2dd9b084 100644 --- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp +++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp @@ -1284,6 +1284,11 @@ txMozillaXSLTProcessor::WrapObject(JSContext* aCx, JS::Handle aGivenP return XSLTProcessorBinding::Wrap(aCx, this, aGivenProto); } +DocGroup* +txMozillaXSLTProcessor::GetDocGroup() const +{ + return mStylesheetDocument ? mStylesheetDocument->GetDocGroup() : nullptr; +} /* static */ already_AddRefed txMozillaXSLTProcessor::Constructor(const GlobalObject& aGlobal, diff --git a/dom/xslt/xslt/txMozillaXSLTProcessor.h b/dom/xslt/xslt/txMozillaXSLTProcessor.h index 93d3c2c301..fc76585f2d 100644 --- a/dom/xslt/xslt/txMozillaXSLTProcessor.h +++ b/dom/xslt/xslt/txMozillaXSLTProcessor.h @@ -29,6 +29,7 @@ class txIGlobalParameter; namespace mozilla { namespace dom { +class DocGroup; class Document; class DocumentFragment; class GlobalObject; @@ -103,6 +104,8 @@ public: return mOwner; } + mozilla::dom::DocGroup* GetDocGroup() const; + static already_AddRefed Constructor(const mozilla::dom::GlobalObject& aGlobal, mozilla::ErrorResult& aRv); diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index 1dcb55aee4..929efc1afc 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -66,7 +66,6 @@ #include "nsContentUtils.h" #include "nsIParser.h" #include "nsCharsetSource.h" -#include "nsIParserService.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/css/Loader.h" #include "nsIScriptError.h" diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index a854f53ecd..2ae03e0b17 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -126,6 +126,8 @@ uint32_t nsXULPrototypeAttribute::gNumCacheSets; uint32_t nsXULPrototypeAttribute::gNumCacheFills; #endif +#define NS_DISPATCH_XUL_COMMAND (1 << 0) + class nsXULElementTearoff final : public nsIFrameLoaderOwner { ~nsXULElementTearoff() {} @@ -202,7 +204,7 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo * element->SetHasID(); } if (aPrototype->mHasClassAttribute) { - element->SetFlags(NODE_MAY_HAVE_CLASS); + element->SetMayHaveClass(); } if (aPrototype->mHasStyleAttribute) { element->SetMayHaveStyle(); @@ -358,12 +360,15 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const attrValue.SetTo(*originalValue); } + bool oldValueSet; if (originalName->IsAtom()) { rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(), - attrValue); + attrValue, + &oldValueSet); } else { rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(), - attrValue); + attrValue, + &oldValueSet); } NS_ENSURE_SUCCESS(rv, rv); element->AddListenerFor(*originalName, true); @@ -372,7 +377,7 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const element->SetHasID(); } if (originalName->Equals(nsGkAtoms::_class)) { - element->SetFlags(NODE_MAY_HAVE_CLASS); + element->SetMayHaveClass(); } if (originalName->Equals(nsGkAtoms::style)) { element->SetMayHaveStyle(); @@ -1005,7 +1010,7 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue) nsresult nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, bool aNotify) + const nsAttrValueOrString* aValue, bool aNotify) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey && IsInUncomposedDoc()) { @@ -1051,7 +1056,8 @@ nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsresult nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aValue) { @@ -1172,7 +1178,7 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, } return nsStyledElement::AfterSetAttr(aNamespaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } bool @@ -1236,20 +1242,68 @@ nsXULElement::List(FILE* out, int32_t aIndent) const } #endif +bool +nsXULElement::IsEventStoppedFromAnonymousScrollbar(EventMessage aMessage) +{ + return (IsRootOfNativeAnonymousSubtree() && + IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner) && + (aMessage == eMouseClick || aMessage == eMouseDoubleClick || + aMessage == eXULCommand || aMessage == eContextMenu || + aMessage == eDragStart)); +} + nsresult -nsXULElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsXULElement::DispatchXULCommand(const EventChainVisitor& aVisitor, + nsAutoString& aCommand) +{ + // XXX sXBL/XBL2 issue! Owner or current document? + nsCOMPtr domDoc(do_QueryInterface(GetUncomposedDoc())); + NS_ENSURE_STATE(domDoc); + nsCOMPtr commandElt; + domDoc->GetElementById(aCommand, getter_AddRefs(commandElt)); + nsCOMPtr commandContent(do_QueryInterface(commandElt)); + if (commandContent) { + // Create a new command event to dispatch to the element + // pointed to by the command attribute. The new event's + // sourceEvent will be the original command event that we're + // handling. + nsCOMPtr domEvent = aVisitor.mDOMEvent; + while (domEvent) { + Event* event = domEvent->InternalDOMEvent(); + NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), + commandContent)); + nsCOMPtr commandEvent = + do_QueryInterface(domEvent); + if (commandEvent) { + commandEvent->GetSourceEvent(getter_AddRefs(domEvent)); + } else { + domEvent = nullptr; + } + } + WidgetInputEvent* orig = aVisitor.mEvent->AsInputEvent(); + nsContentUtils::DispatchXULCommand( + commandContent, + orig->IsTrusted(), + aVisitor.mDOMEvent, + nullptr, + orig->IsControl(), + orig->IsAlt(), + orig->IsShift(), + orig->IsMeta()); + } else { + NS_WARNING("A XUL element is attached to a command that doesn't exist!\n"); + } + return NS_OK; +} + +nsresult +nsXULElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119 - if (IsRootOfNativeAnonymousSubtree() && - (IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner)) && - (aVisitor.mEvent->mMessage == eMouseClick || - aVisitor.mEvent->mMessage == eMouseDoubleClick || - aVisitor.mEvent->mMessage == eXULCommand || - aVisitor.mEvent->mMessage == eContextMenu || - aVisitor.mEvent->mMessage == eDragStart)) { + if (IsEventStoppedFromAnonymousScrollbar(aVisitor.mEvent->mMessage)) { // Don't propagate these events from native anonymous scrollbar. aVisitor.mCanHandle = true; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } if (aVisitor.mEvent->mMessage == eXULCommand && @@ -1263,55 +1317,33 @@ nsXULElement::PreHandleEvent(EventChainPreVisitor& aVisitor) // See if we have a command elt. If so, we execute on the command // instead of on our content element. nsAutoString command; - if (xulEvent && GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) && + if (xulEvent && + GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) && !command.IsEmpty()) { // Stop building the event target chain for the original event. // We don't want it to propagate to any DOM nodes. aVisitor.mCanHandle = false; aVisitor.mAutomaticChromeDispatch = false; - - // XXX sXBL/XBL2 issue! Owner or current document? - nsCOMPtr domDoc(do_QueryInterface(GetUncomposedDoc())); - NS_ENSURE_STATE(domDoc); - nsCOMPtr commandElt; - domDoc->GetElementById(command, getter_AddRefs(commandElt)); - nsCOMPtr commandContent(do_QueryInterface(commandElt)); - if (commandContent) { - // Create a new command event to dispatch to the element - // pointed to by the command attribute. The new event's - // sourceEvent will be the original command event that we're - // handling. - nsCOMPtr domEvent = aVisitor.mDOMEvent; - while (domEvent) { - Event* event = domEvent->InternalDOMEvent(); - NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), - commandContent)); - nsCOMPtr commandEvent = - do_QueryInterface(domEvent); - if (commandEvent) { - commandEvent->GetSourceEvent(getter_AddRefs(domEvent)); - } else { - domEvent = nullptr; - } - } - - WidgetInputEvent* orig = aVisitor.mEvent->AsInputEvent(); - nsContentUtils::DispatchXULCommand( - commandContent, - aVisitor.mEvent->IsTrusted(), - aVisitor.mDOMEvent, - nullptr, - orig->IsControl(), - orig->IsAlt(), - orig->IsShift(), - orig->IsMeta()); - } else { - NS_WARNING("A XUL element is attached to a command that doesn't exist!\n"); - } + // Dispatch XUL command in PreHandleEvent to prevent it breaks event + // target chain creation + aVisitor.mWantsPreHandleEvent = true; + aVisitor.mItemFlags |= NS_DISPATCH_XUL_COMMAND; return NS_OK; } } + return nsStyledElement::GetEventTargetParent(aVisitor); +} + +nsresult +nsXULElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (aVisitor.mItemFlags & NS_DISPATCH_XUL_COMMAND) { + nsAutoString command; + GetAttr(kNameSpaceID_None, nsGkAtoms::command, command); + MOZ_ASSERT(!command.IsEmpty()); + return DispatchXULCommand(aVisitor, command); + } return nsStyledElement::PreHandleEvent(aVisitor); } @@ -1880,12 +1912,14 @@ nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype) attrValue.SetTo(protoattr->mValue); } + bool oldValueSet; // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName if (protoattr->mName.IsAtom()) { - rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue); + rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), + attrValue, &oldValueSet); } else { rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(), - attrValue); + attrValue, &oldValueSet); } NS_ENSURE_SUCCESS(rv, rv); } diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 80424412f8..a307141452 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -355,9 +355,10 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement) // nsINode - virtual nsresult PreHandleEvent( + virtual nsresult GetEventTargetParent( mozilla::EventChainPreVisitor& aVisitor) override; - + virtual nsresult PreHandleEvent( + mozilla::EventChainVisitor& aVisitor) override; // nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -623,10 +624,12 @@ protected: nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype); virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual void UpdateEditableState(bool aNotify) override; @@ -689,6 +692,11 @@ protected: virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; void MaybeUpdatePrivateLifetime(); + + bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage); + + nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor, + nsAutoString& aCommand); }; #endif // nsXULElement_h__ diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp index f7988cd1ad..3f419a74ed 100644 --- a/editor/libeditor/EditorBase.cpp +++ b/editor/libeditor/EditorBase.cpp @@ -37,6 +37,7 @@ #include "mozilla/TextComposition.h" // for TextComposition #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" // for Element, nsINode::AsElement +#include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/Text.h" #include "mozilla/dom/Event.h" #include "mozilla/mozalloc.h" // for operator new, etc. @@ -71,7 +72,6 @@ #include "nsIDOMNode.h" // for nsIDOMNode, etc. #include "nsIDOMNodeList.h" // for nsIDOMNodeList #include "nsIDOMText.h" // for nsIDOMText -#include "nsIDocument.h" // for nsIDocument #include "nsIDocumentStateListener.h" // for nsIDocumentStateListener #include "nsIEditActionListener.h" // for nsIEditActionListener #include "nsIEditorObserver.h" // for nsIEditorObserver @@ -107,16 +107,12 @@ #include "prtime.h" // for PR_Now class nsIOutputStream; -class nsIParserService; class nsITransferable; #ifdef DEBUG #include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument #endif -// Defined in nsEditorRegistration.cpp -extern nsIParserService *sParserService; - namespace mozilla { using namespace dom; @@ -127,13 +123,13 @@ using namespace widget; *****************************************************************************/ EditorBase::EditorBase() - : mPlaceHolderName(nullptr) + : mPlaceholderName(nullptr) , mSelState(nullptr) , mPhonetic(nullptr) , mModCount(0) , mFlags(0) , mUpdateCount(0) - , mPlaceHolderBatch(0) + , mPlaceholderBatch(0) , mAction(EditAction::none) , mIMETextOffset(0) , mIMETextLength(0) @@ -151,7 +147,8 @@ EditorBase::EditorBase() EditorBase::~EditorBase() { - NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?"); + MOZ_ASSERT(!IsInitialized() || mDidPreDestroy, + "Why PreDestroy hasn't been called?"); if (mComposition) { mComposition->OnEditorDestroyed(); @@ -220,20 +217,21 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase) NS_IMETHODIMP -EditorBase::Init(nsIDOMDocument* aDoc, +EditorBase::Init(nsIDOMDocument* aDOMDocument, nsIContent* aRoot, - nsISelectionController* aSelCon, + nsISelectionController* aSelectionController, uint32_t aFlags, const nsAString& aValue) { MOZ_ASSERT(mAction == EditAction::none, "Initializing during an edit action is an error"); - MOZ_ASSERT(aDoc); - if (!aDoc) + MOZ_ASSERT(aDOMDocument); + if (!aDOMDocument) { return NS_ERROR_NULL_POINTER; + } // First only set flags, but other stuff shouldn't be initialized now. - // Don't move this call after initializing mDocWeak. + // Don't move this call after initializing mDocumentWeak. // SetFlags() can check whether it's called during initialization or not by // them. Note that SetFlags() will be called by PostCreate(). #ifdef DEBUG @@ -242,19 +240,21 @@ EditorBase::Init(nsIDOMDocument* aDoc, SetFlags(aFlags); NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed"); - mDocWeak = do_GetWeakReference(aDoc); // weak reference to doc + nsCOMPtr document = do_QueryInterface(aDOMDocument); + mDocumentWeak = document.get(); // HTML editors currently don't have their own selection controller, // so they'll pass null as aSelCon, and we'll get the selection controller // off of the presshell. - nsCOMPtr selCon; - if (aSelCon) { - mSelConWeak = do_GetWeakReference(aSelCon); // weak reference to selectioncontroller - selCon = aSelCon; + nsCOMPtr selectionController; + if (aSelectionController) { + mSelectionControllerWeak = aSelectionController; + selectionController = aSelectionController; } else { nsCOMPtr presShell = GetPresShell(); - selCon = do_QueryInterface(presShell); + selectionController = do_QueryInterface(presShell); } - NS_ASSERTION(selCon, "Selection controller should be available at this point"); + MOZ_ASSERT(selectionController, + "Selection controller should be available at this point"); //set up root element if we are passed one. if (aRoot) @@ -271,13 +271,14 @@ EditorBase::Init(nsIDOMDocument* aDoc, mIMETextNode = nullptr; } - /* Show the caret */ - selCon->SetCaretReadOnly(false); - selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON); + // Show the caret. + selectionController->SetCaretReadOnly(false); + selectionController->SetDisplaySelection( + nsISelectionController::SELECTION_ON); + // Show all the selection reflected to user. + selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL); - selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);//we want to see all the selection reflected to user - - NS_POSTCONDITION(mDocWeak, "bad state"); + MOZ_ASSERT(IsInitialized()); // Make sure that the editor will be destroyed properly mDidPreDestroy = false; @@ -356,8 +357,9 @@ EditorBase::CreateEventListeners() nsresult EditorBase::InstallEventListeners() { - NS_ENSURE_TRUE(mDocWeak && mEventListener, - NS_ERROR_NOT_INITIALIZED); + if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) { + return NS_ERROR_NOT_INITIALIZED; + } // Initialize the event target. nsCOMPtr rootContent = GetRoot(); @@ -378,7 +380,7 @@ EditorBase::InstallEventListeners() void EditorBase::RemoveEventListeners() { - if (!mDocWeak || !mEventListener) { + if (!IsInitialized() || !mEventListener) { return; } reinterpret_cast(mEventListener.get())->Disconnect(); @@ -501,7 +503,7 @@ EditorBase::SetFlags(uint32_t aFlags) bool spellcheckerWasEnabled = CanEnableSpellCheck(); mFlags = aFlags; - if (!mDocWeak) { + if (!IsInitialized()) { // If we're initializing, we shouldn't do anything now. // SetFlags() will be called by PostCreate(), // we should synchronize some stuff for the flags at that time. @@ -567,17 +569,15 @@ EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable) already_AddRefed EditorBase::GetDocument() { - NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized"); - nsCOMPtr doc = do_QueryReferent(mDocWeak); - return doc.forget(); + nsCOMPtr document = mDocumentWeak.get(); + return document.forget(); } already_AddRefed EditorBase::GetDOMDocument() { - NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized"); - nsCOMPtr doc = do_QueryReferent(mDocWeak); - return doc.forget(); + nsCOMPtr domDocument = do_QueryInterface(mDocumentWeak); + return domDocument.forget(); } NS_IMETHODIMP @@ -590,11 +590,12 @@ EditorBase::GetDocument(nsIDOMDocument** aDoc) already_AddRefed EditorBase::GetPresShell() { - NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak"); - nsCOMPtr doc = do_QueryReferent(mDocWeak); - NS_ENSURE_TRUE(doc, nullptr); - nsCOMPtr ps = doc->GetShell(); - return ps.forget(); + nsCOMPtr document = GetDocument(); + if (NS_WARN_IF(!document)) { + return nullptr; + } + nsCOMPtr presShell = document->GetShell(); + return presShell.forget(); } already_AddRefed @@ -629,20 +630,27 @@ EditorBase::GetSelectionController(nsISelectionController** aSel) { NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER); *aSel = nullptr; // init out param - nsCOMPtr selCon; - if (mSelConWeak) { - selCon = do_QueryReferent(mSelConWeak); - } else { - nsCOMPtr presShell = GetPresShell(); - selCon = do_QueryInterface(presShell); - } - if (!selCon) { + nsCOMPtr selCon = GetSelectionController(); + if (NS_WARN_IF(!selCon)) { return NS_ERROR_NOT_INITIALIZED; } - NS_ADDREF(*aSel = selCon); + selCon.forget(aSel); return NS_OK; } +already_AddRefed +EditorBase::GetSelectionController() +{ + nsCOMPtr selectionController; + if (mSelectionControllerWeak) { + selectionController = mSelectionControllerWeak.get(); + } else { + nsCOMPtr presShell = GetPresShell(); + selectionController = do_QueryInterface(presShell); + } + return selectionController.forget(); +} + NS_IMETHODIMP EditorBase::DeleteSelection(EDirection aAction, EStripWrappers aStripWrappers) @@ -663,8 +671,7 @@ EditorBase::GetSelection(SelectionType aSelectionType, { NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER); *aSelection = nullptr; - nsCOMPtr selcon; - GetSelectionController(getter_AddRefs(selcon)); + nsCOMPtr selcon = GetSelectionController(); if (!selcon) { return NS_ERROR_NOT_INITIALIZED; } @@ -686,32 +693,29 @@ EditorBase::GetSelection(SelectionType aSelectionType) NS_IMETHODIMP EditorBase::DoTransaction(nsITransaction* aTxn) { - if (mPlaceHolderBatch && !mPlaceHolderTxn) { - nsCOMPtr placeholderTransaction = - new PlaceholderTransaction(); + if (mPlaceholderBatch && !mPlaceholderTransactionWeak) { + RefPtr placeholderTransaction = + new PlaceholderTransaction(*this, mPlaceholderName, Move(mSelState)); // Save off weak reference to placeholder transaction - mPlaceHolderTxn = do_GetWeakReference(placeholderTransaction); - placeholderTransaction->Init(mPlaceHolderName, mSelState, this); - // placeholder txn took ownership of this pointer - mSelState = nullptr; + mPlaceholderTransactionWeak = placeholderTransaction; - // QI to an nsITransaction since that's what DoTransaction() expects - nsCOMPtr transaction = - do_QueryInterface(placeholderTransaction); // We will recurse, but will not hit this case in the nested call - DoTransaction(transaction); + DoTransaction(placeholderTransaction); if (mTxnMgr) { - nsCOMPtr topTxn = mTxnMgr->PeekUndoStack(); - if (topTxn) { - placeholderTransaction = do_QueryInterface(topTxn); - if (placeholderTransaction) { + nsCOMPtr topTransaction = mTxnMgr->PeekUndoStack(); + nsCOMPtr topAbsorbingTransaction = + do_QueryInterface(topTransaction); + if (topAbsorbingTransaction) { + RefPtr topPlaceholderTransaction = + topAbsorbingTransaction->AsPlaceholderTransaction(); + if (topPlaceholderTransaction) { // there is a placeholder transaction on top of the undo stack. It // is either the one we just created, or an earlier one that we are // now merging into. From here on out remember this placeholder // instead of the one we just created. - mPlaceHolderTxn = do_GetWeakReference(placeholderTransaction); + mPlaceholderTransactionWeak = topPlaceholderTransaction; } } } @@ -935,28 +939,28 @@ EditorBase::EndTransaction() NS_IMETHODIMP EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName) { - NS_PRECONDITION(mPlaceHolderBatch >= 0, "negative placeholder batch count!"); - if (!mPlaceHolderBatch) { + MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!"); + if (!mPlaceholderBatch) { NotifyEditorObservers(eNotifyEditorObserversOfBefore); // time to turn on the batch BeginUpdateViewBatch(); - mPlaceHolderTxn = nullptr; - mPlaceHolderName = aName; + mPlaceholderTransactionWeak = nullptr; + mPlaceholderName = aName; RefPtr selection = GetSelection(); if (selection) { - mSelState = new SelectionState(); + mSelState = MakeUnique(); mSelState->SaveSelection(selection); // Composition transaction can modify multiple nodes and it merges text // node for ime into single text node. // So if current selection is into IME text node, it might be failed // to restore selection by UndoTransaction. // So we need update selection by range updater. - if (mPlaceHolderName == nsGkAtoms::IMETxnName) { + if (mPlaceholderName == nsGkAtoms::IMETxnName) { mRangeUpdater.RegisterSelectionState(*mSelState); } } } - mPlaceHolderBatch++; + mPlaceholderBatch++; return NS_OK; } @@ -964,8 +968,9 @@ EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName) NS_IMETHODIMP EditorBase::EndPlaceHolderTransaction() { - NS_PRECONDITION(mPlaceHolderBatch > 0, "zero or negative placeholder batch count when ending batch!"); - if (mPlaceHolderBatch == 1) { + MOZ_ASSERT(mPlaceholderBatch > 0, + "zero or negative placeholder batch count when ending batch!"); + if (mPlaceholderBatch == 1) { RefPtr selection = GetSelection(); // By making the assumption that no reflow happens during the calls @@ -1005,22 +1010,16 @@ EditorBase::EndPlaceHolderTransaction() if (mSelState) { // we saved the selection state, but never got to hand it to placeholder // (else we ould have nulled out this pointer), so destroy it to prevent leaks. - if (mPlaceHolderName == nsGkAtoms::IMETxnName) { + if (mPlaceholderName == nsGkAtoms::IMETxnName) { mRangeUpdater.DropSelectionState(*mSelState); } - delete mSelState; mSelState = nullptr; } // We might have never made a placeholder if no action took place. - if (mPlaceHolderTxn) { - nsCOMPtr plcTxn = do_QueryReferent(mPlaceHolderTxn); - if (plcTxn) { - plcTxn->EndPlaceHolderBatch(); - } else { - // in the future we will check to make sure undo is off here, - // since that is the only known case where the placeholdertxn would disappear on us. - // For now just removing the assert. - } + if (mPlaceholderTransactionWeak) { + RefPtr placeholderTransaction = + mPlaceholderTransactionWeak.get(); + placeholderTransaction->EndPlaceHolderBatch(); // notify editor observers of action but if composing, it's done by // compositionchange event handler. if (!mComposition) { @@ -1030,7 +1029,7 @@ EditorBase::EndPlaceHolderTransaction() NotifyEditorObservers(eNotifyEditorObserversOfCancel); } } - mPlaceHolderBatch--; + mPlaceholderBatch--; return NS_OK; } @@ -1067,7 +1066,8 @@ EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty) NS_IMETHODIMP EditorBase::SelectAll() { - if (!mDocWeak) { + // XXX Why doesn't this check if the document is alive? + if (!IsInitialized()) { return NS_ERROR_NOT_INITIALIZED; } ForceCompositionEnd(); @@ -1080,7 +1080,8 @@ EditorBase::SelectAll() NS_IMETHODIMP EditorBase::BeginningOfDocument() { - if (!mDocWeak) { + // XXX Why doesn't this check if the document is alive? + if (!IsInitialized()) { return NS_ERROR_NOT_INITIALIZED; } @@ -1117,7 +1118,10 @@ EditorBase::BeginningOfDocument() NS_IMETHODIMP EditorBase::EndOfDocument() { - NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED); + // XXX Why doesn't this check if the document is alive? + if (NS_WARN_IF(!IsInitialized())) { + return NS_ERROR_NOT_INITIALIZED; + } // get selection RefPtr selection = GetSelection(); @@ -1152,20 +1156,22 @@ EditorBase::GetDocumentModified(bool* outDocModified) NS_IMETHODIMP EditorBase::GetDocumentCharacterSet(nsACString& characterSet) { - nsCOMPtr doc = do_QueryReferent(mDocWeak); - NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); - - characterSet = doc->GetDocumentCharacterSet(); + nsCOMPtr document = GetDocument(); + if (NS_WARN_IF(!document)) { + return NS_ERROR_UNEXPECTED; + } + characterSet = document->GetDocumentCharacterSet(); return NS_OK; } NS_IMETHODIMP EditorBase::SetDocumentCharacterSet(const nsACString& characterSet) { - nsCOMPtr doc = do_QueryReferent(mDocWeak); - NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); - - doc->SetDocumentCharacterSet(characterSet); + nsCOMPtr document = GetDocument(); + if (NS_WARN_IF(!document)) { + return NS_ERROR_UNEXPECTED; + } + document->SetDocumentCharacterSet(characterSet); return NS_OK; } @@ -1385,9 +1391,12 @@ EditorBase::CreateNode(nsIAtom* aTag, AutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext); - for (auto& listener : mActionListeners) { - listener->WillCreateNode(nsDependentAtomString(aTag), - GetAsDOMNode(aParent), aPosition); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillCreateNode(nsDependentAtomString(aTag), + GetAsDOMNode(aParent), aPosition); + } } nsCOMPtr ret; @@ -1402,9 +1411,12 @@ EditorBase::CreateNode(nsIAtom* aTag, mRangeUpdater.SelAdjCreateNode(aParent, aPosition); - for (auto& listener : mActionListeners) { - listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret), - GetAsDOMNode(aParent), aPosition, rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret), + GetAsDOMNode(aParent), aPosition, rv); + } } return ret.forget(); @@ -1429,9 +1441,12 @@ EditorBase::InsertNode(nsIContent& aNode, { AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext); - for (auto& listener : mActionListeners) { - listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), - aPosition); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), + aPosition); + } } RefPtr transaction = @@ -1440,9 +1455,12 @@ EditorBase::InsertNode(nsIContent& aNode, mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition); - for (auto& listener : mActionListeners) { - listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition, - rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition, + rv); + } } return rv; @@ -1468,8 +1486,11 @@ EditorBase::SplitNode(nsIContent& aNode, { AutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext); - for (auto& listener : mActionListeners) { - listener->WillSplitNode(aNode.AsDOMNode(), aOffset); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillSplitNode(aNode.AsDOMNode(), aOffset); + } } RefPtr transaction = @@ -1482,9 +1503,12 @@ EditorBase::SplitNode(nsIContent& aNode, mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode); nsresult rv = aResult.StealNSResult(); - for (auto& listener : mActionListeners) { - listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode), - rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode), + rv); + } } // Note: result might be a success code, so we can't use Throw() to // set it on aResult. @@ -1520,9 +1544,12 @@ EditorBase::JoinNodes(nsINode& aLeftNode, // Find the number of children of the lefthand node uint32_t oldLeftNodeLen = aLeftNode.Length(); - for (auto& listener : mActionListeners) { - listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), - parent->AsDOMNode()); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), + parent->AsDOMNode()); + } } nsresult rv = NS_OK; @@ -1535,9 +1562,12 @@ EditorBase::JoinNodes(nsINode& aLeftNode, mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset, (int32_t)oldLeftNodeLen); - for (auto& listener : mActionListeners) { - listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), - parent->AsDOMNode(), rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), + parent->AsDOMNode(), rv); + } } return rv; @@ -1558,8 +1588,11 @@ EditorBase::DeleteNode(nsINode* aNode) nsIEditor::ePrevious); // save node location for selection updating code. - for (auto& listener : mActionListeners) { - listener->WillDeleteNode(aNode->AsDOMNode()); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillDeleteNode(aNode->AsDOMNode()); + } } RefPtr transaction; @@ -1568,8 +1601,11 @@ EditorBase::DeleteNode(nsINode* aNode) rv = DoTransaction(transaction); } - for (auto& listener : mActionListeners) { - listener->DidDeleteNode(aNode->AsDOMNode(), rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidDeleteNode(aNode->AsDOMNode(), rv); + } } NS_ENSURE_SUCCESS(rv, rv); @@ -1844,7 +1880,7 @@ void EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification) { // Copy the observers since EditAction()s can modify mEditorObservers. - nsTArray> observers(mEditorObservers); + AutoEditorObserverArray observers(mEditorObservers); switch (aNotification) { case eNotifyEditorObserversOfEnd: mIsInEditAction = false; @@ -1976,12 +2012,17 @@ NS_IMETHODIMP EditorBase::DebugDumpContent() { #ifdef DEBUG - nsCOMPtr doc = do_QueryReferent(mDocWeak); - NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED); - - nsCOMPtrbodyElem; - doc->GetBody(getter_AddRefs(bodyElem)); - nsCOMPtr content = do_QueryInterface(bodyElem); + nsCOMPtr document = GetDocument(); + if (NS_WARN_IF(!document)) { + return NS_ERROR_NOT_INITIALIZED; + } + nsCOMPtr domHTMLDocument = do_QueryInterface(document); + if (NS_WARN_IF(!domHTMLDocument)) { + return NS_ERROR_NOT_INITIALIZED; + } + nsCOMPtr bodyElement; + domHTMLDocument->GetBody(getter_AddRefs(bodyElement)); + nsCOMPtr content = do_QueryInterface(bodyElement); if (content) { content->List(); } @@ -2295,18 +2336,20 @@ EditorBase::CloneAttributes(Element* aDest, NS_IMETHODIMP EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor) { - nsCOMPtr selCon; - if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) { - int16_t region = nsISelectionController::SELECTION_FOCUS_REGION; - - if (aScrollToAnchor) { - region = nsISelectionController::SELECTION_ANCHOR_REGION; - } - - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - region, nsISelectionController::SCROLL_OVERFLOW_HIDDEN); + nsCOMPtr selectionController = + GetSelectionController(); + if (!selectionController) { + return NS_OK; } + int16_t region = nsISelectionController::SELECTION_FOCUS_REGION; + if (aScrollToAnchor) { + region = nsISelectionController::SELECTION_ANCHOR_REGION; + } + selectionController->ScrollSelectionIntoView( + nsISelectionController::SELECTION_NORMAL, + region, + nsISelectionController::SCROLL_OVERFLOW_HIDDEN); return NS_OK; } @@ -2505,10 +2548,13 @@ EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, } // Let listeners know what's up - for (auto& listener : mActionListeners) { - listener->WillInsertText( - static_cast(insertedTextNode->AsDOMNode()), - insertedOffset, aStringToInsert); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillInsertText( + static_cast(insertedTextNode->AsDOMNode()), + insertedOffset, aStringToInsert); + } } // XXX We may not need these view batches anymore. This is handled at a @@ -2518,10 +2564,13 @@ EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, EndUpdateViewBatch(); // let listeners know what happened - for (auto& listener : mActionListeners) { - listener->DidInsertText( - static_cast(insertedTextNode->AsDOMNode()), - insertedOffset, aStringToInsert, rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidInsertText( + static_cast(insertedTextNode->AsDOMNode()), + insertedOffset, aStringToInsert, rv); + } } // Added some cruft here for bug 43366. Layout was crashing because we left @@ -2583,8 +2632,7 @@ EditorBase::NotifyDocumentListeners( return NS_OK; } - nsTArray> - listeners(mDocStateListeners); + AutoDocumentStateListenerArray listeners(mDocStateListeners); nsresult rv = NS_OK; switch (aNotificationType) { @@ -2656,19 +2704,25 @@ EditorBase::DeleteText(nsGenericDOMDataNode& aCharData, nsIEditor::ePrevious); // Let listeners know what's up - for (auto& listener : mActionListeners) { - listener->WillDeleteText( - static_cast(GetAsDOMNode(&aCharData)), aOffset, - aLength); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->WillDeleteText( + static_cast(GetAsDOMNode(&aCharData)), aOffset, + aLength); + } } nsresult rv = DoTransaction(transaction); // Let listeners know what happened - for (auto& listener : mActionListeners) { - listener->DidDeleteText( - static_cast(GetAsDOMNode(&aCharData)), aOffset, - aLength, rv); + { + AutoActionListenerArray listeners(mActionListeners); + for (auto& listener : listeners) { + listener->DidDeleteText( + static_cast(GetAsDOMNode(&aCharData)), aOffset, + aLength, rv); + } } return rv; @@ -4034,17 +4088,20 @@ EditorBase::DeleteSelectionImpl(EDirection aAction, if (NS_SUCCEEDED(rv)) { AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction); // Notify nsIEditActionListener::WillDelete[Selection|Text|Node] - if (!deleteNode) { - for (auto& listener : mActionListeners) { - listener->WillDeleteSelection(selection); - } - } else if (deleteCharData) { - for (auto& listener : mActionListeners) { - listener->WillDeleteText(deleteCharData, deleteCharOffset, 1); - } - } else { - for (auto& listener : mActionListeners) { - listener->WillDeleteNode(deleteNode->AsDOMNode()); + { + AutoActionListenerArray listeners(mActionListeners); + if (!deleteNode) { + for (auto& listener : listeners) { + listener->WillDeleteSelection(selection); + } + } else if (deleteCharData) { + for (auto& listener : listeners) { + listener->WillDeleteText(deleteCharData, deleteCharOffset, 1); + } + } else { + for (auto& listener : listeners) { + listener->WillDeleteNode(deleteNode->AsDOMNode()); + } } } @@ -4052,17 +4109,20 @@ EditorBase::DeleteSelectionImpl(EDirection aAction, rv = DoTransaction(transaction); // Notify nsIEditActionListener::DidDelete[Selection|Text|Node] - if (!deleteNode) { - for (auto& listener : mActionListeners) { - listener->DidDeleteSelection(selection); - } - } else if (deleteCharData) { - for (auto& listener : mActionListeners) { - listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv); - } - } else { - for (auto& listener : mActionListeners) { - listener->DidDeleteNode(deleteNode->AsDOMNode(), rv); + { + AutoActionListenerArray listeners(mActionListeners); + if (!deleteNode) { + for (auto& listener : mActionListeners) { + listener->DidDeleteSelection(selection); + } + } else if (deleteCharData) { + for (auto& listener : mActionListeners) { + listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv); + } + } else { + for (auto& listener : mActionListeners) { + listener->DidDeleteNode(deleteNode->AsDOMNode(), rv); + } } } } @@ -4739,22 +4799,27 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget) nsCOMPtr presShell = GetPresShell(); NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED); - nsCOMPtr selCon; - nsresult rv = GetSelectionController(getter_AddRefs(selCon)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr selectionController = + GetSelectionController(); + if (NS_WARN_IF(!selectionController)) { + return NS_ERROR_FAILURE; + } // Init the caret RefPtr caret = presShell->GetCaret(); NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED); caret->SetIgnoreUserModify(false); caret->SetSelection(selection); - selCon->SetCaretReadOnly(IsReadonly()); - selCon->SetCaretEnabled(true); + selectionController->SetCaretReadOnly(IsReadonly()); + selectionController->SetCaretEnabled(true); // Init selection - selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON); - selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL); - selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL); + selectionController->SetDisplaySelection( + nsISelectionController::SELECTION_ON); + selectionController->SetSelectionFlags( + nsISelectionDisplay::DISPLAY_ALL); + selectionController->RepaintSelection( + nsISelectionController::SELECTION_NORMAL); // If the computed selection root isn't root content, we should set it // as selection ancestor limit. However, if that is root element, it means // there is not limitation of the selection, then, we must set nullptr. @@ -4822,9 +4887,11 @@ private: NS_IMETHODIMP EditorBase::FinalizeSelection() { - nsCOMPtr selCon; - nsresult rv = GetSelectionController(getter_AddRefs(selCon)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr selectionController = + GetSelectionController(); + if (NS_WARN_IF(!selectionController)) { + return NS_ERROR_FAILURE; + } RefPtr selection = GetSelection(); NS_ENSURE_STATE(selection); @@ -4834,7 +4901,7 @@ EditorBase::FinalizeSelection() nsCOMPtr presShell = GetPresShell(); NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED); - selCon->SetCaretEnabled(false); + selectionController->SetCaretEnabled(false); nsFocusManager* fm = nsFocusManager::GetFocusManager(); NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED); @@ -4849,29 +4916,33 @@ EditorBase::FinalizeSelection() ErrorResult ret; if (!doc || !doc->HasFocus(ret)) { // If the document already lost focus, mark the selection as disabled. - selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED); + selectionController->SetDisplaySelection( + nsISelectionController::SELECTION_DISABLED); } else { // Otherwise, mark selection as normal because outside of a // contenteditable element should be selected with normal selection // color after here. - selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON); + selectionController->SetDisplaySelection( + nsISelectionController::SELECTION_ON); } } else if (IsFormWidget() || IsPasswordEditor() || IsReadonly() || IsDisabled() || IsInputFiltered()) { // In or