-
Notifications
You must be signed in to change notification settings - Fork 54
/
ReftestFissionParent.jsm
160 lines (141 loc) · 5.62 KB
/
ReftestFissionParent.jsm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
var EXPORTED_SYMBOLS = ["ReftestFissionParent"];
class ReftestFissionParent extends JSWindowActorParent {
tellChildrenToFlushRendering(browsingContext, ignoreThrottledAnimations) {
let promises = [];
this.tellChildrenToFlushRenderingRecursive(browsingContext, ignoreThrottledAnimations, promises);
return Promise.allSettled(promises);
}
tellChildrenToFlushRenderingRecursive(browsingContext, ignoreThrottledAnimations, promises) {
let cwg = browsingContext.currentWindowGlobal;
if (cwg && cwg.isProcessRoot) {
let a = cwg.getActor("ReftestFission");
if (a) {
let responsePromise = a.sendQuery("FlushRendering", {ignoreThrottledAnimations});
promises.push(responsePromise);
}
}
for (let context of browsingContext.children) {
this.tellChildrenToFlushRenderingRecursive(context, ignoreThrottledAnimations, 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};
}
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);
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);
}
}
}
}