Bug 1037687, load iframes in shadow DOM, r=wchen

--HG--
extra : rebase_source : 4db8f02b4e35c36100ee96b251ac6b405a70ba7d
This commit is contained in:
Olli Pettay 2015-02-24 16:41:43 +02:00
parent 5bff0c0b03
commit 556df42aa4
11 changed files with 106 additions and 24 deletions

View File

@ -1184,6 +1184,10 @@ FragmentOrElement::DestroyContent()
// The child can remove itself from the parent in BindToTree.
mAttrsAndChildren.ChildAt(i)->DestroyContent();
}
ShadowRoot* shadowRoot = GetShadowRoot();
if (shadowRoot) {
shadowRoot->DestroyContent();
}
}
void

View File

@ -711,6 +711,15 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument,
}
}
void
ShadowRoot::DestroyContent()
{
if (mOlderShadow) {
mOlderShadow->DestroyContent();
}
DocumentFragment::DestroyContent();
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList,
mShadowRoot)

View File

@ -133,6 +133,8 @@ public:
{
mIsComposedDocParticipant = aIsComposedDocParticipant;
}
virtual void DestroyContent() MOZ_OVERRIDE;
protected:
virtual ~ShadowRoot();

View File

@ -19,6 +19,13 @@ 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);
@ -63,9 +70,6 @@ ShouldExposeChildWindow(nsString& aNameBeingResolved, nsIDOMWindow *aChild)
// 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);
}

View File

@ -194,7 +194,7 @@ 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);
@ -349,7 +349,7 @@ private:
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);
@ -876,12 +876,12 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size,
// 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;
@ -972,8 +972,8 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
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;
@ -1191,8 +1191,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
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;
@ -1612,7 +1612,7 @@ nsFrameLoader::MaybeCreateDocShell()
// 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;
}

View File

@ -122,7 +122,7 @@ IsJavaMIME(const nsACString & aMIMEType)
static bool
InActiveDocument(nsIContent *aContent)
{
if (!aContent->IsInDoc()) {
if (!aContent->IsInComposedDoc()) {
return false;
}
nsIDocument *doc = aContent->OwnerDoc();
@ -3315,11 +3315,10 @@ 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;

View File

@ -767,6 +767,7 @@ support-files = file_bug503473-frame.sjs
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'

View File

@ -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>

View File

@ -68,7 +68,7 @@ HTMLObjectElement::DoneAddingChildren(bool aHaveNotified)
// 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);
}
}
@ -231,7 +231,7 @@ HTMLObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
// 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);
}
@ -248,7 +248,7 @@ HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
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);
}
@ -460,7 +460,7 @@ 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;
}

View File

@ -80,7 +80,7 @@ HTMLSharedObjectElement::DoneAddingChildren(bool aHaveNotified)
// 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);
}
}
@ -180,7 +180,7 @@ HTMLSharedObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
// 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);
}
@ -313,7 +313,7 @@ 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;
}

View File

@ -131,7 +131,7 @@ nsGenericHTMLFrameElement::GetContentWindow()
void
nsGenericHTMLFrameElement::EnsureFrameLoader()
{
if (!IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
if (!IsInComposedDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
// If frame loader is there, we just keep it around, cached
return;
}
@ -221,7 +221,7 @@ nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
if (IsInComposedDoc()) {
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Missing a script blocker!");