SingleFile actor: Skip cross-origin frames to fix error (#3721)

This commit is contained in:
Abe Jellinek 2024-02-21 06:43:45 -05:00 committed by GitHub
parent 130a72af1b
commit 64b8c7b250
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 75 additions and 1 deletions

View file

@ -50,7 +50,14 @@ class SingleFileChild extends JSWindowActorChild {
// Create sandboxes for all the frames we find
const frameSandboxes = [];
for (let i = 0; i < sandbox.window.frames.length; ++i) {
let frameSandbox = this.createSnapshotSandbox(sandbox.window.frames[i]);
let frameWindow = sandbox.window.frames[i];
if (this.isCrossOrigin(frameWindow)) {
console.warn('Unable to inject SingleFile into cross-origin frame ' + i);
continue;
}
let frameSandbox = this.createSnapshotSandbox(frameWindow);
// Run all the scripts of SingleFile scripts in Sandbox
frameScripts.forEach(
@ -163,6 +170,16 @@ class SingleFileChild extends JSWindowActorChild {
return sandbox;
}
isCrossOrigin(window) {
try {
void window.document;
return false;
}
catch (e) {
return true;
}
}
// From Mozilla's ScreenshotsComponentChild.jsm
documentIsReady() {

View file

@ -107,6 +107,53 @@ describe("HiddenBrowser", function() {
});
describe("#snapshot()", function () {
var httpd1;
var httpd2;
var port1 = 16213;
var port2 = 16214;
var baseURL1 = `http://127.0.0.1:${port1}/`;
var baseURL2 = `http://127.0.0.1:${port2}/`;
before(function () {
Cu.import("resource://zotero-unit/httpd.js");
// Create two servers with two separate origins
httpd1 = new HttpServer();
httpd1.start(port1);
httpd2 = new HttpServer();
httpd2.start(port2);
});
beforeEach(async function () {
httpd1.registerPathHandler(
'/parent',
{
handle: function (request, response) {
response.setHeader('Content-Type', 'text/html', false);
response.setStatusLine(null, 200, 'OK');
response.write(`
<p>This is text in the parent.</p>
<iframe src="${baseURL2}child">
`);
}
}
);
httpd2.registerPathHandler(
'/child',
{
handle: function (request, response) {
response.setHeader('Content-Type', 'text/html', false);
response.setStatusLine(null, 200, 'OK');
response.write('<p>This is text in the child.</p>');
}
}
);
});
after(async function () {
await new Promise(resolve => httpd1.stop(resolve));
await new Promise(resolve => httpd2.stop(resolve));
});
it("should return a SingleFile snapshot", async function () {
let path = OS.Path.join(getTestDataDirectory().path, 'test-hidden.html');
var browser = new HiddenBrowser();
@ -115,5 +162,15 @@ describe("HiddenBrowser", function() {
assert.include(snapshot, 'Page saved with SingleFile');
assert.include(snapshot, 'This is hidden text.');
});
it("should successfully import a snapshot, skipping a cross-origin iframe", async function () {
let url = baseURL1 + 'parent';
let browser = new HiddenBrowser();
await browser.load(url);
let snapshot = await browser.snapshot();
assert.include(snapshot, 'This is text in the parent.');
// Child frame will be skipped
assert.notInclude(snapshot, 'This is text in the child.');
});
});
});