ReftestFissionParent.sys.mjs (9288B)
1 export class ReftestFissionParent extends JSWindowActorParent { 2 tellChildrenToFlushRendering( 3 browsingContext, 4 ignoreThrottledAnimations, 5 needsAnimationFrame 6 ) { 7 let promises = []; 8 this.tellChildrenToFlushRenderingRecursive( 9 browsingContext, 10 ignoreThrottledAnimations, 11 needsAnimationFrame, 12 promises 13 ); 14 return Promise.allSettled(promises); 15 } 16 17 tellChildrenToFlushRenderingRecursive( 18 browsingContext, 19 ignoreThrottledAnimations, 20 needsAnimationFrame, 21 promises 22 ) { 23 let cwg = browsingContext.currentWindowGlobal; 24 if (cwg && cwg.isProcessRoot) { 25 let a = cwg.getActor("ReftestFission"); 26 if (a) { 27 let responsePromise = a.sendQuery("FlushRendering", { 28 ignoreThrottledAnimations, 29 needsAnimationFrame, 30 }); 31 promises.push(responsePromise); 32 } 33 } 34 35 for (let context of browsingContext.children) { 36 this.tellChildrenToFlushRenderingRecursive( 37 context, 38 ignoreThrottledAnimations, 39 needsAnimationFrame, 40 promises 41 ); 42 } 43 } 44 45 // not including browsingContext 46 getNearestProcessRootProperDescendants(browsingContext) { 47 let result = []; 48 for (let context of browsingContext.children) { 49 this.getNearestProcessRootProperDescendantsRecursive(context, result); 50 } 51 return result; 52 } 53 54 getNearestProcessRootProperDescendantsRecursive(browsingContext, result) { 55 let cwg = browsingContext.currentWindowGlobal; 56 if (cwg && cwg.isProcessRoot) { 57 result.push(browsingContext); 58 return; 59 } 60 for (let context of browsingContext.children) { 61 this.getNearestProcessRootProperDescendantsRecursive(context, result); 62 } 63 } 64 65 // tell children and itself 66 async tellChildrenToUpdateLayerTree(browsingContext) { 67 let errorStrings = []; 68 let infoStrings = []; 69 70 let cwg = browsingContext.currentWindowGlobal; 71 if (!cwg || !cwg.isProcessRoot) { 72 if (cwg) { 73 errorStrings.push( 74 "tellChildrenToUpdateLayerTree called on a non process root?" 75 ); 76 } 77 return { errorStrings, infoStrings }; 78 } 79 80 let actor = cwg.getActor("ReftestFission"); 81 if (!actor) { 82 return { errorStrings, infoStrings }; 83 } 84 85 // When we paint a document we also update the EffectsInfo visible rect in 86 // nsSubDocumentFrame for any remote subdocuments. This visible rect is 87 // used to limit painting for the subdocument in the subdocument's process. 88 // So we want to ensure that the IPC message that updates the visible rect 89 // to the subdocument's process arrives before we paint the subdocument 90 // (otherwise our painting might not be up to date). We do this by sending, 91 // and waiting for reply, an "EmptyMessage" to every direct descendant that 92 // is in another process. Since we send the "EmptyMessage" after the 93 // visible rect update message we know that the visible rect will be 94 // updated by the time we hear back from the "EmptyMessage". Then we can 95 // ask the subdocument process to paint. 96 97 try { 98 let result = await actor.sendQuery("UpdateLayerTree"); 99 errorStrings.push(...result.errorStrings); 100 } catch (e) { 101 infoStrings.push( 102 "tellChildrenToUpdateLayerTree UpdateLayerTree msg to child rejected: " + 103 e 104 ); 105 } 106 107 let descendants = 108 actor.getNearestProcessRootProperDescendants(browsingContext); 109 for (let context of descendants) { 110 let cwg2 = context.currentWindowGlobal; 111 if (cwg2) { 112 if (!cwg2.isProcessRoot) { 113 errorStrings.push( 114 "getNearestProcessRootProperDescendants returned a non process root?" 115 ); 116 } 117 let actor2 = cwg2.getActor("ReftestFission"); 118 if (actor2) { 119 try { 120 await actor2.sendQuery("EmptyMessage"); 121 } catch (e) { 122 infoStrings.push( 123 "tellChildrenToUpdateLayerTree EmptyMessage msg to child rejected: " + 124 e 125 ); 126 } 127 128 try { 129 let result2 = await actor2.tellChildrenToUpdateLayerTree(context); 130 errorStrings.push(...result2.errorStrings); 131 infoStrings.push(...result2.infoStrings); 132 } catch (e) { 133 errorStrings.push( 134 "tellChildrenToUpdateLayerTree recursive tellChildrenToUpdateLayerTree call rejected: " + 135 e 136 ); 137 } 138 } 139 } 140 } 141 142 return { errorStrings, infoStrings }; 143 } 144 145 tellChildrenToSetupDisplayport(browsingContext, promises) { 146 let cwg = browsingContext.currentWindowGlobal; 147 if (cwg && cwg.isProcessRoot) { 148 let a = cwg.getActor("ReftestFission"); 149 if (a) { 150 let responsePromise = a.sendQuery("SetupDisplayport"); 151 promises.push(responsePromise); 152 } 153 } 154 155 for (let context of browsingContext.children) { 156 this.tellChildrenToSetupDisplayport(context, promises); 157 } 158 } 159 160 tellChildrenToSetupAsyncScrollOffsets( 161 browsingContext, 162 allowFailure, 163 promises 164 ) { 165 let cwg = browsingContext.currentWindowGlobal; 166 if (cwg && cwg.isProcessRoot) { 167 let a = cwg.getActor("ReftestFission"); 168 if (a) { 169 let responsePromise = a.sendQuery("SetupAsyncScrollOffsets", { 170 allowFailure, 171 }); 172 promises.push(responsePromise); 173 } 174 } 175 176 for (let context of browsingContext.children) { 177 this.tellChildrenToSetupAsyncScrollOffsets( 178 context, 179 allowFailure, 180 promises 181 ); 182 } 183 } 184 185 receiveMessage(msg) { 186 switch (msg.name) { 187 case "ForwardAfterPaintEvent": { 188 let cwg = msg.data.toBrowsingContext.currentWindowGlobal; 189 if (cwg) { 190 let a = cwg.getActor("ReftestFission"); 191 if (a) { 192 a.sendAsyncMessage( 193 "ForwardAfterPaintEventToSelfAndParent", 194 msg.data 195 ); 196 } 197 } 198 break; 199 } 200 case "FlushRendering": { 201 let promise = this.tellChildrenToFlushRendering( 202 msg.data.browsingContext, 203 msg.data.ignoreThrottledAnimations, 204 msg.data.needsAnimationFrame 205 ); 206 return promise.then(function (results) { 207 let errorStrings = []; 208 let warningStrings = []; 209 let infoStrings = []; 210 for (let r of results) { 211 if (r.status != "fulfilled") { 212 if (r.status == "pending") { 213 errorStrings.push( 214 "FlushRendering sendQuery to child promise still pending?" 215 ); 216 } else { 217 // We expect actors to go away causing sendQuery's to fail, so 218 // just note it. 219 infoStrings.push( 220 "FlushRendering sendQuery to child promise rejected: " + 221 r.reason 222 ); 223 } 224 continue; 225 } 226 227 errorStrings.push(...r.value.errorStrings); 228 warningStrings.push(...r.value.warningStrings); 229 infoStrings.push(...r.value.infoStrings); 230 } 231 return { errorStrings, warningStrings, infoStrings }; 232 }); 233 } 234 case "UpdateLayerTree": { 235 return this.tellChildrenToUpdateLayerTree(msg.data.browsingContext); 236 } 237 case "TellChildrenToSetupDisplayport": { 238 let promises = []; 239 this.tellChildrenToSetupDisplayport(msg.data.browsingContext, promises); 240 return Promise.allSettled(promises).then(function (results) { 241 let errorStrings = []; 242 let infoStrings = []; 243 for (let r of results) { 244 if (r.status != "fulfilled") { 245 // We expect actors to go away causing sendQuery's to fail, so 246 // just note it. 247 infoStrings.push( 248 "SetupDisplayport sendQuery to child promise rejected: " + 249 r.reason 250 ); 251 continue; 252 } 253 254 errorStrings.push(...r.value.errorStrings); 255 infoStrings.push(...r.value.infoStrings); 256 } 257 return { errorStrings, infoStrings }; 258 }); 259 } 260 261 case "SetupAsyncScrollOffsets": { 262 let promises = []; 263 this.tellChildrenToSetupAsyncScrollOffsets( 264 this.manager.browsingContext, 265 msg.data.allowFailure, 266 promises 267 ); 268 return Promise.allSettled(promises).then(function (results) { 269 let errorStrings = []; 270 let infoStrings = []; 271 let updatedAny = false; 272 for (let r of results) { 273 if (r.status != "fulfilled") { 274 // We expect actors to go away causing sendQuery's to fail, so 275 // just note it. 276 infoStrings.push( 277 "SetupAsyncScrollOffsets sendQuery to child promise rejected: " + 278 r.reason 279 ); 280 continue; 281 } 282 283 errorStrings.push(...r.value.errorStrings); 284 infoStrings.push(...r.value.infoStrings); 285 if (r.value.updatedAny) { 286 updatedAny = true; 287 } 288 } 289 return { errorStrings, infoStrings, updatedAny }; 290 }); 291 } 292 } 293 return undefined; 294 } 295 }