Skip to content

Commit b0fae0f

Browse files
authored
browser(firefox): merge FrameData into Frame (#6365)
1 parent 1c40c94 commit b0fae0f

File tree

3 files changed

+83
-124
lines changed

3 files changed

+83
-124
lines changed

browser_patches/firefox/BUILD_NUMBER

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1248
2-
Changed: [email protected] Mon Apr 26 12:48:04 -05 2021
1+
1249
2+
Changed: [email protected] Thu 29 Apr 2021 02:45:14 PM PDT

browser_patches/firefox/juggler/content/FrameTree.js

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class FrameTree {
2323
this._browsingContextGroup.__jugglerFrameTrees = new Set();
2424
this._browsingContextGroup.__jugglerFrameTrees.add(this);
2525
this._scriptsToEvaluateOnNewDocument = new Map();
26+
this._isolatedWorlds = new Map();
2627

2728
this._webSocketEventService = Cc[
2829
"@mozilla.org/websocketevent/service;1"
@@ -72,6 +73,25 @@ class FrameTree {
7273
return this._runtime;
7374
}
7475

76+
addScriptToEvaluateOnNewDocument(script, worldName) {
77+
const scriptId = helper.generateId();
78+
if (worldName) {
79+
this._isolatedWorlds.set(scriptId, {script, worldName});
80+
for (const frame of this.frames())
81+
frame.createIsolatedWorld(worldName);
82+
} else {
83+
this._scriptsToEvaluateOnNewDocument.set(scriptId, script);
84+
}
85+
return {scriptId};
86+
}
87+
88+
removeScriptToEvaluateOnNewDocument(scriptId) {
89+
if (this._isolatedWorlds.has(scriptId))
90+
this._isolatedWorlds.delete(scriptId);
91+
else
92+
this._scriptsToEvaluateOnNewDocument.delete(scriptId);
93+
}
94+
7595
_frameForWorker(workerDebugger) {
7696
if (workerDebugger.type !== Ci.nsIWorkerDebugger.TYPE_DEDICATED)
7797
return null;
@@ -86,7 +106,6 @@ class FrameTree {
86106
if (!frame)
87107
return;
88108
frame._onGlobalObjectCleared();
89-
this.emit(FrameTree.Events.GlobalObjectCreated, { frame, window });
90109
}
91110

92111
_onWorkerCreated(workerDebugger) {
@@ -129,16 +148,6 @@ class FrameTree {
129148
return true;
130149
}
131150

132-
addScriptToEvaluateOnNewDocument(script) {
133-
const scriptId = helper.generateId();
134-
this._scriptsToEvaluateOnNewDocument.set(scriptId, script);
135-
return scriptId;
136-
}
137-
138-
removeScriptToEvaluateOnNewDocument(scriptId) {
139-
this._scriptsToEvaluateOnNewDocument.delete(scriptId);
140-
}
141-
142151
addBinding(name, script) {
143152
this._bindings.set(name, script);
144153
for (const frame of this.frames())
@@ -291,7 +300,6 @@ FrameTree.Events = {
291300
BindingCalled: 'bindingcalled',
292301
FrameAttached: 'frameattached',
293302
FrameDetached: 'framedetached',
294-
GlobalObjectCreated: 'globalobjectcreated',
295303
WorkerCreated: 'workercreated',
296304
WorkerDestroyed: 'workerdestroyed',
297305
WebSocketCreated: 'websocketcreated',
@@ -330,6 +338,9 @@ class Frame {
330338
this._textInputProcessor = null;
331339
this._executionContext = null;
332340

341+
this._isolatedWorlds = new Map();
342+
this._initialNavigationDone = false;
343+
333344
this._webSocketListenerInnerWindowId = 0;
334345
// WebSocketListener calls frameReceived event before webSocketOpened.
335346
// To avoid this, serialize event reporting.
@@ -415,7 +426,36 @@ class Frame {
415426
};
416427
}
417428

429+
createIsolatedWorld(name) {
430+
const principal = [this.domWindow()]; // extended principal
431+
const sandbox = Cu.Sandbox(principal, {
432+
sandboxPrototype: this.domWindow(),
433+
wantComponents: false,
434+
wantExportHelpers: false,
435+
wantXrays: true,
436+
});
437+
const world = this._runtime.createExecutionContext(this.domWindow(), sandbox, {
438+
frameId: this.id(),
439+
name,
440+
});
441+
this._isolatedWorlds.set(world.id(), world);
442+
return world;
443+
}
444+
445+
unsafeObject(objectId) {
446+
const contexts = [this.executionContext(), ...this._isolatedWorlds.values()];
447+
for (const context of contexts) {
448+
const result = context.unsafeObject(objectId);
449+
if (result)
450+
return result.object;
451+
}
452+
throw new Error('Cannot find object with id = ' + objectId);
453+
}
454+
418455
dispose() {
456+
for (const world of this._isolatedWorlds.values())
457+
this._runtime.destroyExecutionContext(world);
458+
this._isolatedWorlds.clear();
419459
if (this._executionContext)
420460
this._runtime.destroyExecutionContext(this._executionContext);
421461
this._executionContext = null;
@@ -458,6 +498,19 @@ class Frame {
458498
dump(`ERROR: ${e.message}\n${e.stack}\n`);
459499
}
460500
}
501+
502+
for (const world of this._isolatedWorlds.values())
503+
this._runtime.destroyExecutionContext(world);
504+
this._isolatedWorlds.clear();
505+
for (const {script, worldName} of this._frameTree._isolatedWorlds.values()) {
506+
const context = worldName ? this.createIsolatedWorld(worldName) : this.executionContext();
507+
try {
508+
let result = context.evaluateScript(script);
509+
if (result && result.objectId)
510+
context.disposeObject(result.objectId);
511+
} catch (e) {
512+
}
513+
}
461514
}
462515

463516
executionContext() {

browser_patches/firefox/juggler/content/PageAgent.js

Lines changed: 16 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -49,65 +49,6 @@ class WorkerData {
4949
}
5050
}
5151

52-
class FrameData {
53-
constructor(agent, runtime, frame) {
54-
this._agent = agent;
55-
this._runtime = runtime;
56-
this._frame = frame;
57-
this._isolatedWorlds = new Map();
58-
this._initialNavigationDone = false;
59-
this.reset();
60-
}
61-
62-
reset() {
63-
for (const world of this._isolatedWorlds.values())
64-
this._runtime.destroyExecutionContext(world);
65-
this._isolatedWorlds.clear();
66-
67-
for (const {script, worldName} of this._agent._isolatedWorlds.values()) {
68-
const context = worldName ? this.createIsolatedWorld(worldName) : this._frame.executionContext();
69-
try {
70-
let result = context.evaluateScript(script);
71-
if (result && result.objectId)
72-
context.disposeObject(result.objectId);
73-
} catch (e) {
74-
}
75-
}
76-
}
77-
78-
createIsolatedWorld(name) {
79-
const principal = [this._frame.domWindow()]; // extended principal
80-
const sandbox = Cu.Sandbox(principal, {
81-
sandboxPrototype: this._frame.domWindow(),
82-
wantComponents: false,
83-
wantExportHelpers: false,
84-
wantXrays: true,
85-
});
86-
const world = this._runtime.createExecutionContext(this._frame.domWindow(), sandbox, {
87-
frameId: this._frame.id(),
88-
name,
89-
});
90-
this._isolatedWorlds.set(world.id(), world);
91-
return world;
92-
}
93-
94-
unsafeObject(objectId) {
95-
const contexts = [this._frame.executionContext(), ...this._isolatedWorlds.values()];
96-
for (const context of contexts) {
97-
const result = context.unsafeObject(objectId);
98-
if (result)
99-
return result.object;
100-
}
101-
throw new Error('Cannot find object with id = ' + objectId);
102-
}
103-
104-
dispose() {
105-
for (const world of this._isolatedWorlds.values())
106-
this._runtime.destroyExecutionContext(world);
107-
this._isolatedWorlds.clear();
108-
}
109-
}
110-
11152
class PageAgent {
11253
constructor(messageManager, browserChannel, frameTree) {
11354
this._messageManager = messageManager;
@@ -116,10 +57,7 @@ class PageAgent {
11657
this._frameTree = frameTree;
11758
this._runtime = frameTree.runtime();
11859

119-
this._frameData = new Map();
12060
this._workerData = new Map();
121-
this._scriptsToEvaluateOnNewDocument = new Map();
122-
this._isolatedWorlds = new Map();
12361

12462
const docShell = frameTree.mainFrame().docShell();
12563
this._docShell = docShell;
@@ -169,7 +107,6 @@ class PageAgent {
169107
helper.on(this._frameTree, 'bindingcalled', this._onBindingCalled.bind(this)),
170108
helper.on(this._frameTree, 'frameattached', this._onFrameAttached.bind(this)),
171109
helper.on(this._frameTree, 'framedetached', this._onFrameDetached.bind(this)),
172-
helper.on(this._frameTree, 'globalobjectcreated', this._onGlobalObjectCreated.bind(this)),
173110
helper.on(this._frameTree, 'navigationstarted', this._onNavigationStarted.bind(this)),
174111
helper.on(this._frameTree, 'navigationcommitted', this._onNavigationCommitted.bind(this)),
175112
helper.on(this._frameTree, 'navigationaborted', this._onNavigationAborted.bind(this)),
@@ -198,7 +135,7 @@ class PageAgent {
198135
this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)),
199136
browserChannel.register('page', {
200137
addBinding: ({ name, script }) => this._frameTree.addBinding(name, script),
201-
addScriptToEvaluateOnNewDocument: this._addScriptToEvaluateOnNewDocument.bind(this),
138+
addScriptToEvaluateOnNewDocument: ({script, worldName}) => this._frameTree.addScriptToEvaluateOnNewDocument(script, worldName),
202139
adoptNode: this._adoptNode.bind(this),
203140
crash: this._crash.bind(this),
204141
describeNode: this._describeNode.bind(this),
@@ -213,7 +150,7 @@ class PageAgent {
213150
insertText: this._insertText.bind(this),
214151
navigate: this._navigate.bind(this),
215152
reload: this._reload.bind(this),
216-
removeScriptToEvaluateOnNewDocument: this._removeScriptToEvaluateOnNewDocument.bind(this),
153+
removeScriptToEvaluateOnNewDocument: ({scriptId}) => this._frameTree.removeScriptToEvaluateOnNewDocument(scriptId),
217154
screenshot: this._screenshot.bind(this),
218155
scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
219156
setCacheDisabled: this._setCacheDisabled.bind(this),
@@ -227,27 +164,6 @@ class PageAgent {
227164
];
228165
}
229166

230-
_addScriptToEvaluateOnNewDocument({script, worldName}) {
231-
if (worldName)
232-
return this._createIsolatedWorld({script, worldName});
233-
return {scriptId: this._frameTree.addScriptToEvaluateOnNewDocument(script)};
234-
}
235-
236-
_createIsolatedWorld({script, worldName}) {
237-
const scriptId = helper.generateId();
238-
this._isolatedWorlds.set(scriptId, {script, worldName});
239-
for (const frameData of this._frameData.values())
240-
frameData.createIsolatedWorld(worldName);
241-
return {scriptId};
242-
}
243-
244-
_removeScriptToEvaluateOnNewDocument({scriptId}) {
245-
if (this._isolatedWorlds.has(scriptId))
246-
this._isolatedWorlds.delete(scriptId);
247-
else
248-
this._frameTree.removeScriptToEvaluateOnNewDocument(scriptId);
249-
}
250-
251167
_setCacheDisabled({cacheDisabled}) {
252168
const enable = Ci.nsIRequest.LOAD_NORMAL;
253169
const disable = Ci.nsIRequest.LOAD_BYPASS_CACHE |
@@ -333,16 +249,16 @@ class PageAgent {
333249
_filePickerShown(inputElement) {
334250
if (inputElement.ownerGlobal.docShell !== this._docShell)
335251
return;
336-
const frameData = this._findFrameForNode(inputElement);
252+
const frame = this._findFrameForNode(inputElement);
337253
this._browserPage.emit('pageFileChooserOpened', {
338-
executionContextId: frameData._frame.executionContext().id(),
339-
element: frameData._frame.executionContext().rawValueToRemoteObject(inputElement)
254+
executionContextId: frame.executionContext().id(),
255+
element: frame.executionContext().rawValueToRemoteObject(inputElement)
340256
});
341257
}
342258

343259
_findFrameForNode(node) {
344-
return Array.from(this._frameData.values()).find(data => {
345-
const doc = data._frame.domWindow().document;
260+
return this._frameTree.frames().find(frame => {
261+
const doc = frame.domWindow().document;
346262
return node === doc || node.ownerDocument === doc;
347263
});
348264
}
@@ -404,10 +320,9 @@ class PageAgent {
404320
navigationId,
405321
errorText,
406322
});
407-
const frameData = this._frameData.get(frame);
408-
if (!frameData._initialNavigationDone && frame !== this._frameTree.mainFrame())
323+
if (!frame._initialNavigationDone && frame !== this._frameTree.mainFrame())
409324
this._emitAllEvents(frame);
410-
frameData._initialNavigationDone = true;
325+
frame._initialNavigationDone = true;
411326
}
412327

413328
_onSameDocumentNavigation(frame) {
@@ -424,23 +339,17 @@ class PageAgent {
424339
url: frame.url(),
425340
name: frame.name(),
426341
});
427-
this._frameData.get(frame)._initialNavigationDone = true;
428-
}
429-
430-
_onGlobalObjectCreated({ frame }) {
431-
this._frameData.get(frame).reset();
342+
frame._initialNavigationDone = true;
432343
}
433344

434345
_onFrameAttached(frame) {
435346
this._browserPage.emit('pageFrameAttached', {
436347
frameId: frame.id(),
437348
parentFrameId: frame.parentFrame() ? frame.parentFrame().id() : undefined,
438349
});
439-
this._frameData.set(frame, new FrameData(this, this._runtime, frame));
440350
}
441351

442352
_onFrameDetached(frame) {
443-
this._frameData.delete(frame);
444353
this._browserPage.emit('pageFrameDetached', {
445354
frameId: frame.id(),
446355
});
@@ -458,9 +367,6 @@ class PageAgent {
458367
for (const workerData of this._workerData.values())
459368
workerData.dispose();
460369
this._workerData.clear();
461-
for (const frameData of this._frameData.values())
462-
frameData.dispose();
463-
this._frameData.clear();
464370
helper.removeListeners(this._eventListeners);
465371
}
466372

@@ -525,7 +431,7 @@ class PageAgent {
525431
const frame = this._frameTree.frame(frameId);
526432
if (!frame)
527433
throw new Error('Failed to find frame with id = ' + frameId);
528-
const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
434+
const unsafeObject = frame.unsafeObject(objectId);
529435
const context = this._runtime.findExecutionContext(executionContextId);
530436
const fromPrincipal = unsafeObject.nodePrincipal;
531437
const toFrame = this._frameTree.frame(context.auxData().frameId);
@@ -539,7 +445,7 @@ class PageAgent {
539445
const frame = this._frameTree.frame(frameId);
540446
if (!frame)
541447
throw new Error('Failed to find frame with id = ' + frameId);
542-
const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
448+
const unsafeObject = frame.unsafeObject(objectId);
543449
if (!unsafeObject)
544450
throw new Error('Object is not input!');
545451
const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
@@ -550,7 +456,7 @@ class PageAgent {
550456
const frame = this._frameTree.frame(frameId);
551457
if (!frame)
552458
throw new Error('Failed to find frame with id = ' + frameId);
553-
const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
459+
const unsafeObject = frame.unsafeObject(objectId);
554460
if (!unsafeObject.getBoxQuads)
555461
throw new Error('RemoteObject is not a node');
556462
const quads = unsafeObject.getBoxQuads({relativeTo: this._frameTree.mainFrame().domWindow().document}).map(quad => {
@@ -568,7 +474,7 @@ class PageAgent {
568474
const frame = this._frameTree.frame(frameId);
569475
if (!frame)
570476
throw new Error('Failed to find frame with id = ' + frameId);
571-
const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
477+
const unsafeObject = frame.unsafeObject(objectId);
572478
const browsingContextGroup = frame.docShell().browsingContext.group;
573479
const frames = this._frameTree.allFramesInBrowsingContextGroup(browsingContextGroup);
574480
let contentFrame;
@@ -590,7 +496,7 @@ class PageAgent {
590496
const frame = this._frameTree.frame(frameId);
591497
if (!frame)
592498
throw new Error('Failed to find frame with id = ' + frameId);
593-
const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
499+
const unsafeObject = frame.unsafeObject(objectId);
594500
if (!unsafeObject.isConnected)
595501
throw new Error('Node is detached from document');
596502
if (!rect)
@@ -877,7 +783,7 @@ class PageAgent {
877783
async _getFullAXTree({objectId}) {
878784
let unsafeObject = null;
879785
if (objectId) {
880-
unsafeObject = this._frameData.get(this._frameTree.mainFrame()).unsafeObject(objectId);
786+
unsafeObject = this._frameTree.mainFrame().unsafeObject(objectId);
881787
if (!unsafeObject)
882788
throw new Error(`No object found for id "${objectId}"`);
883789
}

0 commit comments

Comments
 (0)