author | Olli Pettay <Olli.Pettay@helsinki.fi> |
Tue, 24 Feb 2015 16:41:43 +0200 | |
changeset 259345 | 53365d1c2b7f61efd40dd3839e6205f63d10c0e5 |
parent 259344 | 26cc212192fa8034fa3a9b9246ec7c141691738b |
child 259346 | c26d8b2d5edf85ace207f634a097daf441e0a853 |
push id | 4718 |
push user | raliiev@mozilla.com |
push date | Mon, 11 May 2015 18:39:53 +0000 |
treeherder | mozilla-beta@c20c4ef55f08 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | wchen |
bugs | 1037687 |
milestone | 39.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/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1179,16 +1179,20 @@ FragmentOrElement::DestroyContent() // leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684). ReleaseWrapper(this); uint32_t i, count = mAttrsAndChildren.ChildCount(); for (i = 0; i < count; ++i) { // The child can remove itself from the parent in BindToTree. mAttrsAndChildren.ChildAt(i)->DestroyContent(); } + ShadowRoot* shadowRoot = GetShadowRoot(); + if (shadowRoot) { + shadowRoot->DestroyContent(); + } } void FragmentOrElement::SaveSubtreeState() { uint32_t i, count = mAttrsAndChildren.ChildCount(); for (i = 0; i < count; ++i) { mAttrsAndChildren.ChildAt(i)->SaveSubtreeState();
--- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -706,16 +706,25 @@ ShadowRoot::ContentRemoved(nsIDocument* // Watch for node that is removed from the pool because // it may need to be removed from an insertion point. if (IsPooledNode(aChild, aContainer, mPoolHost)) { RemoveDistributedNode(aChild); } } +void +ShadowRoot::DestroyContent() +{ + if (mOlderShadow) { + mOlderShadow->DestroyContent(); + } + DocumentFragment::DestroyContent(); +} + NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList, mShadowRoot) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList) NS_INTERFACE_MAP_END_INHERITING(StyleSheetList) NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList) NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
--- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -128,16 +128,18 @@ public: ShadowRoot* GetOlderShadowRoot() { return mOlderShadow; } void StyleSheetChanged(); bool IsComposedDocParticipant() { return mIsComposedDocParticipant; } void SetIsComposedDocParticipant(bool aIsComposedDocParticipant) { mIsComposedDocParticipant = aIsComposedDocParticipant; } + + virtual void DestroyContent() MOZ_OVERRIDE; protected: virtual ~ShadowRoot(); // The pool host is the parent of the nodes that will be distributed // into the insertion points in this ShadowRoot. See |ChangeShadowRoot|. nsCOMPtr<nsIContent> mPoolHost; // An array of content insertion points that are a descendant of the ShadowRoot
--- a/dom/base/WindowNamedPropertiesHandler.cpp +++ b/dom/base/WindowNamedPropertiesHandler.cpp @@ -14,16 +14,23 @@ #include "xpcprivate.h" namespace mozilla { namespace dom { static bool ShouldExposeChildWindow(nsString& aNameBeingResolved, nsIDOMWindow *aChild) { + nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aChild); + NS_ENSURE_TRUE(piWin, false); + Element* e = piWin->GetFrameElementInternal(); + if (e && e->IsInShadowTree()) { + return false; + } + // If we're same-origin with the child, go ahead and expose it. nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aChild); NS_ENSURE_TRUE(sop, false); if (nsContentUtils::SubjectPrincipal()->Equals(sop->GetPrincipal())) { return true; } // If we're not same-origin, expose it _only_ if the name of the browsing @@ -58,19 +65,16 @@ ShouldExposeChildWindow(nsString& aNameB // in Gecko, and probably in other UAs as well. So we go with a simpler // approximation of the above. This approximation will only break sites that // rely on their cross-origin subframes setting window.name to a known value, // which is unlikely to be very common. And while it does introduce a // dependency on cross-origin state when doing global lookups, it doesn't // allow the child to arbitrarily pollute the parent namespace, and requires // cross-origin communication only in a limited set of cases that can be // computed independently by the parent. - nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aChild); - NS_ENSURE_TRUE(piWin, false); - Element* e = piWin->GetFrameElementInternal(); return e && e->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aNameBeingResolved, eCaseMatters); } bool WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
--- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -189,17 +189,17 @@ nsFrameLoader::~nsFrameLoader() } nsFrameLoader* nsFrameLoader::Create(Element* aOwner, bool aNetworkCreated) { NS_ENSURE_TRUE(aOwner, nullptr); nsIDocument* doc = aOwner->OwnerDoc(); NS_ENSURE_TRUE(!doc->IsResourceDoc() && - ((!doc->IsLoadedAsData() && aOwner->GetUncomposedDoc()) || + ((!doc->IsLoadedAsData() && aOwner->GetComposedDoc()) || doc->IsStaticDocument()), nullptr); return new nsFrameLoader(aOwner, aNetworkCreated); } NS_IMETHODIMP nsFrameLoader::LoadFrame() @@ -344,17 +344,17 @@ public: private: nsRefPtr<nsFrameLoader> mFrameLoader; }; nsresult nsFrameLoader::ReallyStartLoadingInternal() { - NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc()); + NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInComposedDoc()); PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading", js::ProfileEntry::Category::OTHER); nsresult rv = MaybeCreateDocShell(); if (NS_FAILED(rv)) { return rv; } @@ -871,22 +871,22 @@ nsFrameLoader::ShowRemoteFrame(const nsI } } // FIXME/bug 589337: Show()/Hide() is pretty expensive for // cross-process layers; need to figure out what behavior we really // want here. For now, hack. if (!mRemoteBrowserShown) { if (!mOwnerContent || - !mOwnerContent->GetUncomposedDoc()) { + !mOwnerContent->GetComposedDoc()) { return false; } nsRefPtr<layers::LayerManager> layerManager = - nsContentUtils::LayerManagerForDocument(mOwnerContent->GetUncomposedDoc()); + nsContentUtils::LayerManagerForDocument(mOwnerContent->GetComposedDoc()); if (!layerManager) { // This is just not going to work. return false; } nsPIDOMWindow* win = mOwnerContent->OwnerDoc()->GetWindow(); bool parentIsActive = false; if (win) { @@ -967,18 +967,18 @@ nsFrameLoader::SwapWithOtherRemoteLoader bool equal; nsresult rv = ourContent->NodePrincipal()->Equals(otherContent->NodePrincipal(), &equal); if (NS_FAILED(rv) || !equal) { // Security problems loom. Just bail on it all return NS_ERROR_DOM_SECURITY_ERR; } - nsIDocument* ourDoc = ourContent->GetCurrentDoc(); - nsIDocument* otherDoc = otherContent->GetCurrentDoc(); + nsIDocument* ourDoc = ourContent->GetComposedDoc(); + nsIDocument* otherDoc = otherContent->GetComposedDoc(); if (!ourDoc || !otherDoc) { // Again, how odd, given that we had docshells return NS_ERROR_NOT_IMPLEMENTED; } nsIPresShell* ourShell = ourDoc->GetShell(); nsIPresShell* otherShell = otherDoc->GetShell(); if (!ourShell || !otherShell) { @@ -1186,18 +1186,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra } nsCOMPtr<nsIDocument> ourParentDocument = ourChildDocument->GetParentDocument(); nsCOMPtr<nsIDocument> otherParentDocument = otherChildDocument->GetParentDocument(); // Make sure to swap docshells between the two frames. - nsIDocument* ourDoc = ourContent->GetUncomposedDoc(); - nsIDocument* otherDoc = otherContent->GetUncomposedDoc(); + nsIDocument* ourDoc = ourContent->GetComposedDoc(); + nsIDocument* otherDoc = otherContent->GetComposedDoc(); if (!ourDoc || !otherDoc) { // Again, how odd, given that we had docshells return NS_ERROR_NOT_IMPLEMENTED; } NS_ASSERTION(ourDoc == ourParentDocument, "Unexpected parent document"); NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document"); @@ -1607,17 +1607,17 @@ nsFrameLoader::MaybeCreateDocShell() mRemoteFrame = true; return NS_OK; } // Get our parent docshell off the document of mOwnerContent // XXXbz this is such a total hack.... We really need to have a // better setup for doing this. nsIDocument* doc = mOwnerContent->OwnerDoc(); - if (!(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) { + if (!(doc->IsStaticDocument() || mOwnerContent->IsInComposedDoc())) { return NS_ERROR_UNEXPECTED; } if (doc->IsResourceDoc() || !doc->IsActive()) { // Don't allow subframe loads in resource documents, nor // in non-active documents. return NS_ERROR_NOT_AVAILABLE; }
--- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -117,17 +117,17 @@ IsJavaMIME(const nsACString & aMIMEType) { return nsPluginHost::GetSpecialType(aMIMEType) == nsPluginHost::eSpecialType_Java; } static bool InActiveDocument(nsIContent *aContent) { - if (!aContent->IsInDoc()) { + if (!aContent->IsInComposedDoc()) { return false; } nsIDocument *doc = aContent->OwnerDoc(); return (doc && doc->IsActive()); } /// /// Runnables and helper classes @@ -3310,21 +3310,20 @@ nsObjectLoadingContent::ShouldPlay(Fallb } nsIDocument* nsObjectLoadingContent::GetContentDocument() { nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); - if (!thisContent->IsInDoc()) { + if (!thisContent->IsInComposedDoc()) { return nullptr; } - // XXXbz should this use GetComposedDoc()? sXBL/XBL2 issue! nsIDocument *sub_doc = thisContent->OwnerDoc()->GetSubDocumentFor(thisContent); if (!sub_doc) { return nullptr; } // Return null for cross-origin contentDocument. if (!nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) { return nullptr;
--- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -762,16 +762,17 @@ disabled = Disabled for now. Mochitest i support-files = bug444546.sjs [test_bug503473.html] disabled = Disabled due to making the harness time out support-files = file_bug503473-frame.sjs [test_bug1011748.html] skip-if = buildapp == 'b2g' || e10s support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs [test_bug1025933.html] +[test_bug1037687.html] [test_element.matches.html] [test_user_select.html] skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' [test_bug1081686.html] skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s [test_window_define_nonconfigurable.html] skip-if = true # bug 1107443 - code for newly-added test was disabled [test_root_iframe.html]
new file mode 100644 --- /dev/null +++ b/dom/base/test/test_bug1037687.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1037687 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1037687</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1037687 **/ + + SimpleTest.waitForExplicitFinish(); + + var host; + var sr; + var embed; + var object; + var iframe; + var resourceLoadCount = 0; + + function resourceLoaded(event) { + ++resourceLoadCount; + ok(true, event.target + " got " + event.load); + if (resourceLoadCount == 3) { + SimpleTest.finish(); + } + } + + function createResource(sr, type) { + var el = document.createElement(type); + var attrName = type == "object" ? "data" : "src"; + el.setAttribute(attrName, "file_mozfiledataurl_img.jpg"); + el.onload = resourceLoaded; + var info = document.createElement("div"); + info.textContent = type; + sr.appendChild(info); + sr.appendChild(el); + } + + function test() { + host = document.getElementById("host"); + sr = host.createShadowRoot(); + embed = createResource(sr, "embed"); + object = createResource(sr, "object"); + iframe = createResource(sr, "iframe"); + } + + </script> +</head> +<body onload="test()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1037687">Mozilla Bug 1037687</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +<div id="host"></div> +</body> +</html>
--- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -63,17 +63,17 @@ HTMLObjectElement::IsDoneAddingChildren( void HTMLObjectElement::DoneAddingChildren(bool aHaveNotified) { mIsDoneAddingChildren = true; // If we're already in a document, we need to trigger the load // Otherwise, BindToTree takes care of that. - if (IsInDoc()) { + if (IsInComposedDoc()) { StartObjectLoad(aHaveNotified); } } NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLObjectElement, nsGenericHTMLFormElement) @@ -226,34 +226,34 @@ HTMLObjectElement::SetAttr(int32_t aName // if aNotify is false, we are coming from the parser or some such place; // we'll get bound after all the attributes have been set, so we'll do the // object load from BindToTree/DoneAddingChildren. // Skip the LoadObject call in that case. // We also don't want to start loading the object when we're not yet in // a document, just in case that the caller wants to set additional // attributes before inserting the node into the document. - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) { return LoadObject(aNotify, true); } return NS_OK; } nsresult HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) { nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); NS_ENSURE_SUCCESS(rv, rv); // See comment in SetAttr - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { return LoadObject(aNotify, true); } return NS_OK; } bool @@ -455,17 +455,17 @@ HTMLObjectElement::GetAttributeMappingFu return &MapAttributesIntoRule; } void HTMLObjectElement::StartObjectLoad(bool aNotify) { // BindToTree can call us asynchronously, and we may be removed from the tree // in the interim - if (!IsInDoc() || !OwnerDoc()->IsActive()) { + if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) { return; } LoadObject(aNotify); SetIsNetworkCreated(false); } EventStates
--- a/dom/html/HTMLSharedObjectElement.cpp +++ b/dom/html/HTMLSharedObjectElement.cpp @@ -75,17 +75,17 @@ HTMLSharedObjectElement::IsDoneAddingChi void HTMLSharedObjectElement::DoneAddingChildren(bool aHaveNotified) { if (!mIsDoneAddingChildren) { mIsDoneAddingChildren = true; // If we're already in a document, we need to trigger the load // Otherwise, BindToTree takes care of that. - if (IsInDoc()) { + if (IsInComposedDoc()) { StartObjectLoad(aHaveNotified); } } } NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLSharedObjectElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSharedObjectElement, @@ -175,17 +175,17 @@ HTMLSharedObjectElement::SetAttr(int32_t // if aNotify is false, we are coming from the parser or some such place; // we'll get bound after all the attributes have been set, so we'll do the // object load from BindToTree/DoneAddingChildren. // Skip the LoadObject call in that case. // We also don't want to start loading the object when we're not yet in // a document, just in case that the caller wants to set additional // attributes before inserting the node into the document. - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == URIAttrName()) { return LoadObject(aNotify, true); } return NS_OK; } bool @@ -308,17 +308,17 @@ HTMLSharedObjectElement::GetAttributeMap return &MapAttributesIntoRule; } void HTMLSharedObjectElement::StartObjectLoad(bool aNotify) { // BindToTree can call us asynchronously, and we may be removed from the tree // in the interim - if (!IsInDoc() || !OwnerDoc()->IsActive()) { + if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) { return; } LoadObject(aNotify); SetIsNetworkCreated(false); } EventStates
--- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -126,17 +126,17 @@ nsGenericHTMLFrameElement::GetContentWin "Uh, this window should always be an outer window!"); return win.forget(); } void nsGenericHTMLFrameElement::EnsureFrameLoader() { - if (!IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) { + if (!IsInComposedDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) { // If frame loader is there, we just keep it around, cached return; } // Strangely enough, this method doesn't actually ensure that the // frameloader exists. It's more of a best-effort kind of thing. mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated); if (mIsPrerendered) { @@ -216,17 +216,17 @@ nsGenericHTMLFrameElement::BindToTree(ns nsIContent* aBindingParent, bool aCompileEventHandlers) { nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); - if (aDocument) { + if (IsInComposedDoc()) { NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!"); PROFILER_LABEL("nsGenericHTMLFrameElement", "BindToTree", js::ProfileEntry::Category::OTHER); // We're in a document now. Kick off the frame load. LoadSrc();