зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1597253 - [remote] Implement Page.lifecycleEvent. r=remote-protocol-reviewers,maja_zf
Differential Revision: https://phabricator.services.mozilla.com/D53827 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
88538854d7
Коммит
e02cc0bfe1
|
@ -157,8 +157,16 @@ class Page extends ContentProcessDomain {
|
|||
});
|
||||
}
|
||||
|
||||
emitLifecycleEvent(frameId, loaderId, name, timestamp) {
|
||||
if (this.lifecycleEnabled) {
|
||||
this.emit("Page.lifecycleEvent", { frameId, loaderId, name, timestamp });
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent({ type, target }) {
|
||||
if (target.defaultView != this.content) {
|
||||
const isFrame = target.defaultView != this.content;
|
||||
|
||||
if (isFrame) {
|
||||
// Ignore iframes for now
|
||||
return;
|
||||
}
|
||||
|
@ -170,18 +178,44 @@ class Page extends ContentProcessDomain {
|
|||
switch (type) {
|
||||
case "DOMContentLoaded":
|
||||
this.emit("Page.domContentEventFired", { timestamp });
|
||||
if (!isFrame) {
|
||||
this.emitLifecycleEvent(
|
||||
frameId,
|
||||
/* loaderId */ null,
|
||||
"DOMContentLoaded",
|
||||
timestamp
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "pagehide":
|
||||
// Maybe better to bound to "unload" once we can register for this event
|
||||
this.emit("Page.frameStartedLoading", { frameId });
|
||||
if (!isFrame) {
|
||||
this.emitLifecycleEvent(
|
||||
frameId,
|
||||
/* loaderId */ null,
|
||||
"init",
|
||||
timestamp
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "pageshow":
|
||||
this.emit("Page.loadEventFired", { timestamp });
|
||||
if (!isFrame) {
|
||||
this.emitLifecycleEvent(
|
||||
frameId,
|
||||
/* loaderId */ null,
|
||||
"load",
|
||||
timestamp
|
||||
);
|
||||
}
|
||||
|
||||
// XXX this should most likely be sent differently
|
||||
this.emit("Page.navigatedWithinDocument", { frameId, url });
|
||||
this.emit("Page.frameStoppedLoading", { frameId });
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,3 +178,12 @@ function getContentProperty(prop) {
|
|||
_prop => content[_prop]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new promise, which resolves after ms have been elapsed
|
||||
*/
|
||||
function timeoutPromise(ms) {
|
||||
return new Promise(resolve => {
|
||||
window.setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,5 +14,6 @@ support-files =
|
|||
[browser_javascriptDialog_confirm.js]
|
||||
[browser_javascriptDialog_otherTarget.js]
|
||||
[browser_javascriptDialog_prompt.js]
|
||||
[browser_lifecycleEvent.js]
|
||||
[browser_reload.js]
|
||||
[browser_runtimeEvents.js]
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test the Page lifecycle events
|
||||
|
||||
const DOC = toDataURL("default-test-page");
|
||||
|
||||
add_task(async function noInitialEvents({ Page }) {
|
||||
await Page.enable();
|
||||
info("Page domain has been enabled");
|
||||
|
||||
const promise = recordPromises(Page, ["init", "DOMContentLoaded", "load"]);
|
||||
info("Lifecycle events are not enabled");
|
||||
|
||||
let pageLoaded = Page.loadEventFired();
|
||||
const { frameId } = await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("A new page has been loaded");
|
||||
|
||||
await assertNavigationLifecycleEvents({ promise, frameId, timeout: 1000 });
|
||||
});
|
||||
|
||||
add_task(async function noEventsAfterDisable({ Page }) {
|
||||
await Page.enable();
|
||||
info("Page domain has been enabled");
|
||||
|
||||
await Page.setLifecycleEventsEnabled({ enabled: true });
|
||||
await Page.setLifecycleEventsEnabled({ enabled: false });
|
||||
const promise = recordPromises(Page, ["init", "DOMContentLoaded", "load"]);
|
||||
info("Lifecycle events are not enabled");
|
||||
|
||||
let pageLoaded = Page.loadEventFired();
|
||||
const { frameId } = await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("A new page has been loaded");
|
||||
|
||||
await assertNavigationLifecycleEvents({ promise, frameId, timeout: 1000 });
|
||||
});
|
||||
|
||||
add_task(async function navigateEvents({ Page }) {
|
||||
await Page.enable();
|
||||
info("Page domain has been enabled");
|
||||
|
||||
await Page.setLifecycleEventsEnabled({ enabled: true });
|
||||
const promise = recordPromises(Page, ["init", "DOMContentLoaded", "load"]);
|
||||
info("Lifecycle events have been enabled");
|
||||
|
||||
let pageLoaded = Page.loadEventFired();
|
||||
const { frameId } = await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("A new page has been loaded");
|
||||
|
||||
await assertNavigationLifecycleEvents({ promise, frameId });
|
||||
});
|
||||
|
||||
add_task(async function navigateEventsOnReload({ Page }) {
|
||||
await Page.enable();
|
||||
info("Page domain has been enabled");
|
||||
|
||||
let pageLoaded = Page.loadEventFired();
|
||||
const { frameId } = await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("Initial page has been loaded");
|
||||
|
||||
await Page.setLifecycleEventsEnabled({ enabled: true });
|
||||
const promise = recordPromises(Page, ["init", "DOMContentLoaded", "load"]);
|
||||
info("Lifecycle events have been enabled");
|
||||
|
||||
pageLoaded = Page.loadEventFired();
|
||||
await Page.reload();
|
||||
await pageLoaded;
|
||||
info("The page has been reloaded");
|
||||
|
||||
await assertNavigationLifecycleEvents({ promise, frameId });
|
||||
});
|
||||
|
||||
add_task(async function navigateEventsOnNavigateToSameURL({ Page }) {
|
||||
await Page.enable();
|
||||
info("Page domain has been enabled");
|
||||
|
||||
let pageLoaded = Page.loadEventFired();
|
||||
const { frameId } = await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("Initial page has been loaded");
|
||||
|
||||
await Page.setLifecycleEventsEnabled({ enabled: true });
|
||||
const promise = recordPromises(Page, ["init", "DOMContentLoaded", "load"]);
|
||||
info("Lifecycle events have been enabled");
|
||||
|
||||
pageLoaded = Page.loadEventFired();
|
||||
await Page.navigate({ url: DOC });
|
||||
await pageLoaded;
|
||||
info("The page has been reloaded");
|
||||
|
||||
await assertNavigationLifecycleEvents({ promise, frameId });
|
||||
});
|
||||
|
||||
function recordPromises(Page, names) {
|
||||
return new Promise(resolve => {
|
||||
const resolutions = new Map();
|
||||
|
||||
const unsubscribe = Page.lifecycleEvent(event => {
|
||||
info(`Received Page.lifecycleEvent for ${event.name}`);
|
||||
resolutions.set(event.name, event);
|
||||
|
||||
if (event.name == names[names.length - 1]) {
|
||||
unsubscribe();
|
||||
resolve(resolutions);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function assertNavigationLifecycleEvents({ promise, frameId, timeout }) {
|
||||
// Wait for all the promises to resolve
|
||||
const promises = [promise];
|
||||
|
||||
if (timeout) {
|
||||
promises.push(timeoutPromise(timeout));
|
||||
}
|
||||
|
||||
const resolutions = await Promise.race(promises);
|
||||
|
||||
if (timeout) {
|
||||
is(resolutions, undefined, "No lifecycle events have been recorded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Assert the order in which they resolved
|
||||
const expectedResolutions = ["init", "DOMContentLoaded", "load"];
|
||||
Assert.deepEqual(
|
||||
[...resolutions.keys()],
|
||||
expectedResolutions,
|
||||
"Received various lifecycle events in the expected order"
|
||||
);
|
||||
|
||||
// Now assert the data exposed by each of these events
|
||||
const frameStartedLoading = resolutions.get("init");
|
||||
is(frameStartedLoading.frameId, frameId, "init frameId is the same one");
|
||||
|
||||
const DOMContentLoaded = resolutions.get("DOMContentLoaded");
|
||||
is(
|
||||
DOMContentLoaded.frameId,
|
||||
frameId,
|
||||
"DOMContentLoaded frameId is the same one"
|
||||
);
|
||||
|
||||
const load = resolutions.get("load");
|
||||
is(load.frameId, frameId, "load frameId is the same one");
|
||||
}
|
Загрузка…
Ссылка в новой задаче