author | Sean Feng <sefeng@mozilla.com> |
Sat, 14 Sep 2019 00:09:44 +0000 | |
changeset 495151 | c8a2c27a1128c4800c1fefc9fafd06204e48ec2a |
parent 495150 | deba67add7d2d31d593cb0438bfff33be9760226 |
child 495152 | e10a3c2499439232e95ecff9b90c3689c48d7ae2 |
push id | 36623 |
push user | shindli@mozilla.com |
push date | Fri, 27 Sep 2019 04:28:18 +0000 |
treeherder | mozilla-central@dcfdecc355c0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1467970 |
milestone | 71.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/tests/mochitest/aom/test_general.html +++ b/accessible/tests/mochitest/aom/test_general.html @@ -187,17 +187,17 @@ } // Check if an AccessibleNode is properly cached. let node = ifrDoc.createElement("div"); anode = node.accessibleNode; is(anode, node.accessibleNode, "an AccessibleNode is properly cached"); // Adopting node to another document doesn't change .accessibleNode - let anotherDoc = document.implementation.createDocument("", "", null); + let anotherDoc = ifrDoc.implementation.createDocument("", "", null); let adopted_node = anotherDoc.adoptNode(node); is(anode, adopted_node.accessibleNode, "adopting node to another document doesn't change node.accessibleNode"); const relationProps = ["activeDescendant", "details", "errorMessage"]; for (const relationProp of relationProps) { testRelationProp(anode, node, relationProp); }
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html +++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html @@ -591,17 +591,17 @@ new invokerChecker(EVENT_REORDER, () => { return getNode("t9_container").contentDocument; }), ]; this.invoke = () => { // trigger a tree update. let doc = getNode("t9_container").contentDocument; - doc.body.appendChild(document.createElement("p")); + doc.body.appendChild(doc.createElement("p")); }; this.finalCheck = () => { var tree = { INTERNAL_FRAME: [ { DOCUMENT: [ { PARAGRAPH: [] }, { SECTION: [] },
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -9410,20 +9410,20 @@ TabModalPromptBox.prototype = { "focus-tab-by-prompt", Services.perms.ALLOW_ACTION ); } onCloseCallback.apply(this, args); }, appendPrompt(args, onCloseCallback) { - let newPrompt = new TabModalPrompt(window); + let browser = this.browser; + let newPrompt = new TabModalPrompt(browser.ownerGlobal); this.prompts.set(newPrompt.element, newPrompt); - let browser = this.browser; browser.parentNode.insertBefore( newPrompt.element, browser.nextElementSibling ); browser.setAttribute("tabmodalPromptShowing", true); let prompts = this.listPrompts(); if (prompts.length > 1) {
--- a/devtools/server/actors/inspector/walker.js +++ b/devtools/server/actors/inspector/walker.js @@ -1640,18 +1640,30 @@ var WalkerActor = protocol.ActorClassWit * @param {NodeActor} node The node. * @param {string} value The piece of HTML content. */ setOuterHTML: function(node, value) { if (isNodeDead(node)) { return; } - const parsedDOM = new DOMParser().parseFromString(value, "text/html"); const rawNode = node.rawNode; + const doc = nodeDocument(rawNode); + const win = doc.defaultView; + let parser; + if (!win) { + throw new Error("The window object shouldn't be null"); + } else { + // We create DOMParser under window object because we want a content + // DOMParser, which means all the DOM objects created by this DOMParser + // will be in the same DocGroup as rawNode.parentNode. Then the newly + // created nodes can be adopted into rawNode.parentNode. + parser = new win.DOMParser(); + } + const parsedDOM = parser.parseFromString(value, "text/html"); const parentNode = rawNode.parentNode; // Special case for head and body. Setting document.body.outerHTML // creates an extra <head> tag, and document.head.outerHTML creates // an extra <body>. So instead we will call replaceChild with the // parsed DOM, assuming that they aren't trying to set both tags at once. if (rawNode.tagName === "BODY") { if (parsedDOM.head.innerHTML === "") {
--- a/dom/base/DOMParser.cpp +++ b/dom/base/DOMParser.cpp @@ -4,16 +4,17 @@ * 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/. */ #include "mozilla/dom/DOMParser.h" #include "nsNetUtil.h" #include "nsDOMString.h" #include "MainThreadUtils.h" +#include "SystemPrincipal.h" #include "nsIStreamListener.h" #include "nsStringStream.h" #include "nsIScriptError.h" #include "nsIScriptSecurityManager.h" #include "nsCRT.h" #include "nsStreamUtils.h" #include "nsContentUtils.h" #include "nsDOMJSUtils.h" @@ -98,16 +99,32 @@ already_AddRefed<Document> DOMParser::Pa aRv.Throw(rv); return nullptr; } return ParseFromStream(stream, NS_LITERAL_STRING("UTF-8"), utf8str.Length(), aType, aRv); } +already_AddRefed<Document> DOMParser::ParseFromSafeString(const nsAString& aStr, + SupportedType aType, + ErrorResult& aRv) { + // Since we disable cross docGroup node adoption, it is safe to create + // new document with the system principal, then the new document will be + // placed in the same docGroup as the chrome document. + nsCOMPtr<nsIPrincipal> docPrincipal = mPrincipal; + if (!nsContentUtils::IsSystemPrincipal(mPrincipal)) { + mPrincipal = SystemPrincipal::Create(); + } + + RefPtr<Document> ret = ParseFromString(aStr, aType, aRv); + mPrincipal = docPrincipal; + return ret.forget(); +} + already_AddRefed<Document> DOMParser::ParseFromBuffer(const Uint8Array& aBuf, SupportedType aType, ErrorResult& aRv) { aBuf.ComputeLengthAndData(); return ParseFromBuffer(MakeSpan(aBuf.Data(), aBuf.Length()), aType, aRv); } already_AddRefed<Document> DOMParser::ParseFromBuffer(Span<const uint8_t> aBuf,
--- a/dom/base/DOMParser.h +++ b/dom/base/DOMParser.h @@ -32,16 +32,20 @@ class DOMParser final : public nsISuppor // WebIDL API static already_AddRefed<DOMParser> Constructor(const GlobalObject& aOwner, mozilla::ErrorResult& rv); already_AddRefed<Document> ParseFromString(const nsAString& aStr, SupportedType aType, ErrorResult& aRv); + // ChromeOnly API + already_AddRefed<Document> ParseFromSafeString(const nsAString& aStr, + SupportedType aType, + ErrorResult& aRv); // Sequence converts to Span, so we can use this overload for both // the Sequence case and our internal uses. already_AddRefed<Document> ParseFromBuffer(Span<const uint8_t> aBuf, SupportedType aType, ErrorResult& aRv); already_AddRefed<Document> ParseFromBuffer(const Uint8Array& aBuf, SupportedType aType,
--- a/dom/base/nsNodeUtils.h +++ b/dom/base/nsNodeUtils.h @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsNodeUtils_h___ #define nsNodeUtils_h___ #include "mozilla/Maybe.h" #include "nsIContent.h" // for use in inline function (ParentChainChanged) #include "nsIMutationObserver.h" // for use in inline function (ParentChainChanged) +#include "mozilla/dom/Document.h" #include "js/TypeDecls.h" #include "nsCOMArray.h" struct CharacterDataChangeInfo; template <class E> class nsCOMArray; class nsCycleCollectionTraversalCallback; namespace mozilla { @@ -199,16 +200,27 @@ class nsNodeUtils { * @param aNodesWithProperties All nodes (from amongst aNode and its * descendants) with properties. * @param aError The error, if any. */ static void Adopt(nsINode* aNode, nsNodeInfoManager* aNewNodeInfoManager, JS::Handle<JSObject*> aReparentScope, nsCOMArray<nsINode>& aNodesWithProperties, mozilla::ErrorResult& aError) { + if (aNode && aNewNodeInfoManager) { + mozilla::dom::Document* newDoc = aNewNodeInfoManager->GetDocument(); + mozilla::dom::Document* oldDoc = aNode->OwnerDoc(); + if (newDoc && oldDoc && + (oldDoc->GetDocGroup() != newDoc->GetDocGroup())) { + MOZ_ASSERT(false, "Cross docGroup adoption is not allowed"); + aError.Throw(NS_ERROR_DOM_SECURITY_ERR); + return; + } + } + // Just need to store the return value of CloneAndAdopt in a // temporary nsCOMPtr to make sure we release it. nsCOMPtr<nsINode> node = CloneAndAdopt(aNode, false, true, aNewNodeInfoManager, aReparentScope, &aNodesWithProperties, nullptr, aError); nsMutationGuard::DidMutate(); }
--- a/dom/bindings/test/test_dom_xrays.html +++ b/dom/bindings/test/test_dom_xrays.html @@ -289,17 +289,17 @@ function test() { isnot(typeof elem.ELEMENT_NODE, "undefined", "Should see constant property on prototype objects"); is(Object.getOwnPropertyDescriptor(elem, "ELEMENT_NODE"), undefined, "Shouldn't see constant property on instances"); isnot(typeof Object.getOwnPropertyDescriptor(win.Node.prototype, "ELEMENT_NODE"), "undefined", "Should see constant property on prototype objects"); // Adopting nodes should not lose expandos. - elem = doc.createElement("span"); + elem = document.createElement("span"); elem.expando = 5; is(elem.expando, 5, "We just set this property"); document.adoptNode(elem); is(elem.wrappedJSObject, undefined, "Shouldn't be an Xray anymore"); is(elem.expando, 5, "Expando should not get lost"); // Instanceof tests var img = doc.createElement("img");
--- a/dom/tests/mochitest/general/test_focusrings.xul +++ b/dom/tests/mochitest/general/test_focusrings.xul @@ -116,17 +116,17 @@ var htmlElements = [ var htmlElementsMacPrefSet = [ "<button id='elem' class='canfocus'>Button</button>", "<input id='elem' class='canfocus'>", "<input id='elem' type='button' class='canfocus'>", "<input id='elem' type='checkbox' class='canfocus'>", ]; function createElement(str) { - let doc = new DOMParser().parseFromString(`<html><body>${str}</body></html>`, "text/html"); + let doc = new DOMParser().parseFromSafeString(`<html><body>${str}</body></html>`, "text/html"); return doc.body.firstChild; } function testHTMLElements(list, isMac, expectedNoRingsOnWin) { var childwin = frames[0]; var childdoc = childwin.document; var container = childdoc.getElementById("container");
--- a/dom/tests/mochitest/webcomponents/test_xul_custom_element.xul +++ b/dom/tests/mochitest/webcomponents/test_xul_custom_element.xul @@ -12,17 +12,17 @@ <script type="application/javascript"> <![CDATA[ SimpleTest.waitForExplicitFinish(); var gXULDOMParser = new DOMParser(); gXULDOMParser.forceEnableXULXBL(); function parseXULToFragment(str) { - let doc = gXULDOMParser.parseFromString(` + let doc = gXULDOMParser.parseFromSafeString(` <box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">${str}</box>`, "application/xml"); // We use a range here so that we don't access the inner DOM elements from // JavaScript before they are imported and inserted into a document. let range = doc.createRange(); range.selectNodeContents(doc.firstChild); return range.extractContents(); }
--- a/dom/webidl/DOMParser.webidl +++ b/dom/webidl/DOMParser.webidl @@ -20,16 +20,19 @@ enum SupportedType { interface DOMParser { [Throws] constructor(); [NewObject, Throws] Document parseFromString(DOMString str, SupportedType type); + [NewObject, ChromeOnly, Throws] + Document parseFromSafeString(DOMString str, SupportedType type); + // Mozilla-specific stuff [NewObject, Throws, ChromeOnly] Document parseFromBuffer(sequence<octet> buf, SupportedType type); [NewObject, Throws, ChromeOnly] Document parseFromBuffer(Uint8Array buf, SupportedType type); [NewObject, Throws, ChromeOnly] Document parseFromStream(InputStream stream, DOMString? charset, long contentLength, SupportedType type);
--- a/js/xpconnect/tests/chrome/chrome.ini +++ b/js/xpconnect/tests/chrome/chrome.ini @@ -39,17 +39,16 @@ support-files = [test_bug448587.xul] [test_bug484459.xul] skip-if = os == 'win' || os == 'mac' || (os == 'linux' && !debug) # bug 1131110, 1255284 [test_bug500931.xul] [test_bug503926.xul] [test_bug533596.xul] [test_bug571849.xul] [test_bug596580.xul] -[test_bug601803.xul] [test_bug610390.xul] [test_bug614757.xul] [test_bug616992.xul] [test_bug618176.xul] [test_bug654370.xul] [test_bug658560.xul] [test_bug658909.xul] [test_bug664689.xul]
deleted file mode 100644 --- a/js/xpconnect/tests/chrome/test_bug601803.xul +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0"?> -<?xml-stylesheet href="chrome://global/skin" type="text/css"?> -<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" - type="text/css"?> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=500931 ---> -<window title="Mozilla Bug 601803" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> - - <!-- test results are displayed in the html:body --> - <body xmlns="http://www.w3.org/1999/xhtml"> - <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601803" - target="_blank">Mozilla Bug 601803</a> - - <!-- test code goes here --> - <script type="application/javascript"><![CDATA[ - - /** Test for Bug 601803 **/ - - function go() { - var ifr = document.getElementById('ifr'); - var elem = document.createElementNS("http://www.w3.org/1999/xhtml","html:div"); - elem.appendChild(document.createTextNode("hello, world")); - elem.expando = 42; - ifr.contentDocument.body.appendChild(elem); - is(elem.wrappedJSObject.expando, 42, "expando is preserved"); - SimpleTest.finish(); - } - - SimpleTest.waitForExplicitFinish(); - - ]]></script> - <iframe type="content" src="about:blank" onload="go()" id="ifr" /> - </body> -</window>
--- a/toolkit/content/customElements.js +++ b/toolkit/content/customElements.js @@ -481,17 +481,17 @@ * @param {string[]} [entities] * An array of DTD URLs containing entity definitions. * * @return {DocumentFragment} `DocumentFragment` instance containing * the corresponding element tree, including element nodes * but excluding any text node. */ static parseXULToFragment(str, entities = []) { - let doc = gXULDOMParser.parseFromString( + let doc = gXULDOMParser.parseFromSafeString( ` ${ entities.length ? `<!DOCTYPE bindings [ ${entities.reduce((preamble, url, index) => { return ( preamble + `<!ENTITY % _dtd-${index} SYSTEM "${url}">