gecko-dev/layout/tools/reftest/ReftestFissionParent.jsm

239 строки
8.4 KiB
JavaScript

var EXPORTED_SYMBOLS = ["ReftestFissionParent"];
class ReftestFissionParent extends JSWindowActorParent {
tellChildrenToFlushRendering(browsingContext, ignoreThrottledAnimations, needsAnimationFrame) {
let promises = [];
this.tellChildrenToFlushRenderingRecursive(browsingContext, ignoreThrottledAnimations, needsAnimationFrame, promises);
return Promise.allSettled(promises);
}
tellChildrenToFlushRenderingRecursive(browsingContext, ignoreThrottledAnimations, needsAnimationFrame, promises) {
let cwg = browsingContext.currentWindowGlobal;
if (cwg && cwg.isProcessRoot) {
let a = cwg.getActor("ReftestFission");
if (a) {
let responsePromise = a.sendQuery("FlushRendering", {ignoreThrottledAnimations, needsAnimationFrame});
promises.push(responsePromise);
}
}
for (let context of browsingContext.children) {
this.tellChildrenToFlushRenderingRecursive(context, ignoreThrottledAnimations, needsAnimationFrame, promises);
}
}
// not including browsingContext
getNearestProcessRootProperDescendants(browsingContext) {
let result = [];
for (let context of browsingContext.children) {
this.getNearestProcessRootProperDescendantsRecursive(context, result);
}
return result;
}
getNearestProcessRootProperDescendantsRecursive(browsingContext, result) {
let cwg = browsingContext.currentWindowGlobal;
if (cwg && cwg.isProcessRoot) {
result.push(browsingContext);
return;
}
for (let context of browsingContext.children) {
this.getNearestProcessRootProperDescendantsRecursive(context, result);
}
}
// tell children and itself
async tellChildrenToUpdateLayerTree(browsingContext) {
let errorStrings = [];
let infoStrings = [];
let cwg = browsingContext.currentWindowGlobal;
if (!cwg || !cwg.isProcessRoot) {
if (cwg) {
errorStrings.push("tellChildrenToUpdateLayerTree called on a non process root?");
}
return {errorStrings, infoStrings};
}
let actor = cwg.getActor("ReftestFission");
if (!actor) {
return {errorStrings, infoStrings};
}
// When we paint a document we also update the EffectsInfo visible rect in
// nsSubDocumentFrame for any remote subdocuments. This visible rect is
// used to limit painting for the subdocument in the subdocument's process.
// So we want to ensure that the IPC message that updates the visible rect
// to the subdocument's process arrives before we paint the subdocument
// (otherwise our painting might not be up to date). We do this by sending,
// and waiting for reply, an "EmptyMessage" to every direct descendant that
// is in another process. Since we send the "EmptyMessage" after the
// visible rect update message we know that the visible rect will be
// updated by the time we hear back from the "EmptyMessage". Then we can
// ask the subdocument process to paint.
try {
let result = await actor.sendQuery("UpdateLayerTree");
errorStrings.push(...result.errorStrings);
} catch (e) {
infoStrings.push("tellChildrenToUpdateLayerTree UpdateLayerTree msg to child rejected: " + e);
}
let descendants = actor.getNearestProcessRootProperDescendants(browsingContext);
for (let context of descendants) {
let cwg2 = context.currentWindowGlobal;
if (cwg2) {
if (!cwg2.isProcessRoot) {
errorStrings.push("getNearestProcessRootProperDescendants returned a non process root?");
}
let actor2 = cwg2.getActor("ReftestFission");
if (actor2) {
try {
await actor2.sendQuery("EmptyMessage");
} catch(e) {
infoStrings.push("tellChildrenToUpdateLayerTree EmptyMessage msg to child rejected: " + e);
}
try {
let result2 = await actor2.tellChildrenToUpdateLayerTree(context);
errorStrings.push(...result2.errorStrings);
infoStrings.push(...result2.infoStrings);
} catch (e) {
errorStrings.push("tellChildrenToUpdateLayerTree recursive tellChildrenToUpdateLayerTree call rejected: " + e);
}
}
}
}
return {errorStrings, infoStrings};
}
tellChildrenToSetupDisplayport(browsingContext, promises) {
let cwg = browsingContext.currentWindowGlobal;
if (cwg && cwg.isProcessRoot) {
let a = cwg.getActor("ReftestFission");
if (a) {
let responsePromise = a.sendQuery("SetupDisplayport");
promises.push(responsePromise);
}
}
for (let context of browsingContext.children) {
this.tellChildrenToSetupDisplayport(context, promises);
}
}
tellChildrenToSetupAsyncScrollOffsets(browsingContext, allowFailure, promises) {
let cwg = browsingContext.currentWindowGlobal;
if (cwg && cwg.isProcessRoot) {
let a = cwg.getActor("ReftestFission");
if (a) {
let responsePromise = a.sendQuery("SetupAsyncScrollOffsets", {allowFailure});
promises.push(responsePromise);
}
}
for (let context of browsingContext.children) {
this.tellChildrenToSetupAsyncScrollOffsets(context, allowFailure, promises);
}
}
receiveMessage(msg) {
switch (msg.name) {
case "ForwardAfterPaintEvent":
{
let cwg = msg.data.toBrowsingContext.currentWindowGlobal;
if (cwg) {
let a = cwg.getActor("ReftestFission");
if (a) {
a.sendAsyncMessage("ForwardAfterPaintEventToSelfAndParent", msg.data);
}
}
break;
}
case "FlushRendering":
{
let promise = this.tellChildrenToFlushRendering(msg.data.browsingContext, msg.data.ignoreThrottledAnimations, msg.data.needsAnimationFrame);
return promise.then(function (results) {
let errorStrings = [];
let warningStrings = [];
let infoStrings = [];
for (let r of results) {
if (r.status != "fulfilled") {
if (r.status == "pending") {
errorStrings.push("FlushRendering sendQuery to child promise still pending?");
} else {
// We expect actors to go away causing sendQuery's to fail, so
// just note it.
infoStrings.push("FlushRendering sendQuery to child promise rejected: " + r.reason);
}
continue;
}
errorStrings.push(...r.value.errorStrings);
warningStrings.push(...r.value.warningStrings);
infoStrings.push(...r.value.infoStrings);
}
return {errorStrings, warningStrings, infoStrings};
});
}
case "UpdateLayerTree":
{
return this.tellChildrenToUpdateLayerTree(msg.data.browsingContext);
}
case "TellChildrenToSetupDisplayport":
{
let promises = [];
this.tellChildrenToSetupDisplayport(msg.data.browsingContext, promises);
return Promise.allSettled(promises).then(function (results) {
let errorStrings = [];
let infoStrings = [];
for (let r of results) {
if (r.status != "fulfilled") {
// We expect actors to go away causing sendQuery's to fail, so
// just note it.
infoStrings.push("SetupDisplayport sendQuery to child promise rejected: " + r.reason);
continue;
}
errorStrings.push(...r.value.errorStrings);
infoStrings.push(...r.value.infoStrings);
}
return {errorStrings, infoStrings}
});
}
case "SetupAsyncScrollOffsets":
{
let promises = [];
this.tellChildrenToSetupAsyncScrollOffsets(this.manager.browsingContext, msg.data.allowFailure, promises);
return Promise.allSettled(promises).then(function (results) {
let errorStrings = [];
let infoStrings = [];
let updatedAny = false;
for (let r of results) {
if (r.status != "fulfilled") {
// We expect actors to go away causing sendQuery's to fail, so
// just note it.
infoStrings.push("SetupAsyncScrollOffsets sendQuery to child promise rejected: " + r.reason);
continue;
}
errorStrings.push(...r.value.errorStrings);
infoStrings.push(...r.value.infoStrings);
if (r.value.updatedAny) {
updatedAny = true;
}
}
return {errorStrings, infoStrings, updatedAny};
});
}
}
}
}