зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1440212 part 2. Add the ability to fire the load event on a frame element async from the load event on the window inside if they are in different docgroups. r=nika
Behind a pref for now. Differential Revision: https://phabricator.services.mozilla.com/D35600 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
5f4fd391ec
Коммит
16a5db7bc2
|
@ -173,6 +173,7 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsFrameLoaderOwner.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "prenv.h"
|
||||
|
@ -1898,29 +1899,73 @@ void nsGlobalWindowInner::FireFrameLoadEvent() {
|
|||
}
|
||||
|
||||
// If embedder is same-process, fire the event on our embedder element.
|
||||
//
|
||||
// XXX: Bug 1440212 is looking into potentially changing this behaviour to act
|
||||
// more like the remote case when in-process.
|
||||
RefPtr<Element> element = GetBrowsingContext()->GetEmbedderElement();
|
||||
if (element) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetEvent event(/* aIsTrusted = */ true, eLoad);
|
||||
event.mFlags.mBubbles = false;
|
||||
event.mFlags.mCancelable = false;
|
||||
|
||||
if (mozilla::dom::DocGroup::TryToLoadIframesInBackground()) {
|
||||
nsDocShell* ds = nsDocShell::Cast(GetDocShell());
|
||||
|
||||
if (ds && !ds->HasFakeOnLoadDispatched()) {
|
||||
EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
|
||||
if (!ds || ds->HasFakeOnLoadDispatched()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
RefPtr<nsFrameLoaderOwner> loaderOwner(do_QueryObject(element));
|
||||
if (!loaderOwner) {
|
||||
// Pretty surprising!
|
||||
MOZ_ASSERT(false, "How did we get here?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Track the frameloader, not the element, for purposes of firing our load
|
||||
// event. That way if the element gets a new frame loader (e.g. gets moved
|
||||
// around in the DOM) while our runnable is pending we will not fire an
|
||||
// incorrect (because having nothing to do with the browsing context,
|
||||
// window, etc now inside the element) load event at it.
|
||||
RefPtr<nsFrameLoader> loader = loaderOwner->GetFrameLoader();
|
||||
if (!loader) {
|
||||
// Still pretty surprising, if we got this far!
|
||||
return;
|
||||
}
|
||||
|
||||
auto fireLoadEvent = [loader]() -> void {
|
||||
RefPtr<Element> currentElement = loader->GetOwnerElement();
|
||||
if (!currentElement) {
|
||||
// The loader has gotten torn down. Just bail.
|
||||
return;
|
||||
}
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetEvent event(/* aIsTrusted = */ true, eLoad);
|
||||
event.mFlags.mBubbles = false;
|
||||
event.mFlags.mCancelable = false;
|
||||
|
||||
// Most of the time we could get a pres context to pass in here,
|
||||
// but not always (i.e. if this window is not shown there won't
|
||||
// be a pres context available). Since we're not firing a GUI
|
||||
// event we don't need a pres context anyway so we just pass
|
||||
// null as the pres context all the time here.
|
||||
EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
|
||||
EventDispatcher::Dispatch(currentElement, nullptr, &event, nullptr,
|
||||
&status);
|
||||
};
|
||||
|
||||
if (GetDocGroup() == element->GetDocGroup() ||
|
||||
!StaticPrefs::dom_cross_docgroup_iframe_async_load_event()) {
|
||||
fireLoadEvent();
|
||||
} else {
|
||||
// Make sure we don't fire the load event on |element|'s document before
|
||||
// we fire it on the element.
|
||||
RefPtr<Document> doc = element->OwnerDoc();
|
||||
doc->BlockOnload();
|
||||
RefPtr<Runnable> fireEvent = NS_NewRunnableFunction(
|
||||
"Cross-docgroup frame load", [doc, fireLoadEvent]() -> void {
|
||||
fireLoadEvent();
|
||||
// Sync unblocking is OK here, because we're coming from a
|
||||
// runnable anyway. Note that we capture "doc" here,
|
||||
// instead of using element->OwnerDoc(), because the
|
||||
// latter could change before our runnable runs and then
|
||||
// we will get incorrectly paired block/unblock calls.
|
||||
doc->UnblockOnload(true);
|
||||
});
|
||||
doc->Dispatch(TaskCategory::Network, fireEvent.forget());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,18 @@ function doTest() {
|
|||
window.parent.ok_wrapper(true, "a document that was loaded, navigated to another document, had 'allow-same-origin' added and then was" +
|
||||
" navigated back should be same-origin with its parent");
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
// We depend on our link click adding a new session history entry for the new
|
||||
// load. That means we need to make sure it runs after our parent is done
|
||||
// loading. Otherwise the load can get turned into a replace load, not create a
|
||||
// new session history entry, and then the back() call in the parent will fail.
|
||||
//
|
||||
// Since we are not same-origin with the parent, we wait for it to tell us when
|
||||
// it's done loading.
|
||||
onmessage = function(e) {
|
||||
if (e.data == "start") {
|
||||
navigateAway();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,16 @@ function ok_wrapper(result, msg) {
|
|||
function doIf11TestPart2() {
|
||||
var if_11 = document.getElementById('if_11');
|
||||
if_11.sandbox = 'allow-scripts allow-same-origin';
|
||||
// window.history is no longer cross-origin accessible in gecko.
|
||||
SpecialPowers.wrap(if_11).contentWindow.history.back();
|
||||
}
|
||||
// History is unified for the entire toplevel window and all its
|
||||
// subframes, so we can just call history.back() on ourselves; we
|
||||
// don't have to do it on our child.
|
||||
history.back();
|
||||
}
|
||||
|
||||
onload = function() {
|
||||
document.getElementById('if_11').contentWindow.postMessage("start", "*");
|
||||
}
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<iframe sandbox='allow-scripts' id="if_11" src="file_iframe_sandbox_d_if11.html" height="10" width="10"></iframe>
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
<head>
|
||||
<title>crash in nsContentList::nsContentList on print preview</title>
|
||||
</head><body>
|
||||
|
||||
<iframe onload="window.location.reload()" src="data:text/html,">
|
||||
<script>
|
||||
onmessage = function () {
|
||||
window.location.reload();
|
||||
}
|
||||
</script>
|
||||
<!-- Give our load event a chance to fire too -->
|
||||
<iframe onload="postMessage(null, '*')" src="data:text/html,">
|
||||
</iframe>
|
||||
|
||||
|
||||
|
|
|
@ -3035,6 +3035,13 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# When this pref is set, we can fire load events on iframe elements async if
|
||||
# the iframe is in a different docgroup from the document it contains.
|
||||
- name: dom.cross_docgroup_iframe_async_load_event
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# WebIDL test prefs.
|
||||
- name: dom.webidl.test1
|
||||
type: bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче