mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1763598 - Fix docshell_helpers.js for session history in the parent. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D143159
This commit is contained in:
parent
14be294b2d
commit
926498605f
78
docshell/test/chrome/DocShellHelpers.jsm
Normal file
78
docshell/test/chrome/DocShellHelpers.jsm
Normal file
@ -0,0 +1,78 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["DocShellHelpersParent", "DocShellHelpersChild"];
|
||||
|
||||
class DocShellHelpersParent extends JSWindowActorParent {
|
||||
static eventListener;
|
||||
|
||||
// These static variables should be set when registering the actor
|
||||
// (currently doPageNavigation in docshell_helpers.js).
|
||||
static eventsToListenFor;
|
||||
static observers;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
receiveMessage({ name, data }) {
|
||||
if (name == "docshell_helpers:event") {
|
||||
let { event, originalTargetIsHTMLDocument } = data;
|
||||
|
||||
if (this.constructor.eventsToListenFor.includes(event.type)) {
|
||||
this.constructor.eventListener(event, originalTargetIsHTMLDocument);
|
||||
}
|
||||
} else if (name == "docshell_helpers:observe") {
|
||||
let { topic } = data;
|
||||
|
||||
this.constructor.observers.get(topic).call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DocShellHelpersChild extends JSWindowActorChild {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
receiveMessage({ name, data }) {
|
||||
if (name == "docshell_helpers:preventBFCache") {
|
||||
// Add an RTCPeerConnection to prevent the page from being bfcached.
|
||||
let win = this.contentWindow;
|
||||
win.blockBFCache = new win.RTCPeerConnection();
|
||||
}
|
||||
}
|
||||
handleEvent(event) {
|
||||
if (
|
||||
Document.isInstance(event.originalTarget) &&
|
||||
event.originalTarget.isInitialDocument
|
||||
) {
|
||||
dump(`TEST: ignoring a ${event.type} event for an initial about:blank\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendAsyncMessage("docshell_helpers:event", {
|
||||
event: {
|
||||
type: event.type,
|
||||
persisted: event.persisted,
|
||||
originalTarget: {
|
||||
title: event.originalTarget.title,
|
||||
location: event.originalTarget.location.href,
|
||||
visibilityState: event.originalTarget.visibilityState,
|
||||
hidden: event.originalTarget.hidden,
|
||||
},
|
||||
},
|
||||
originalTargetIsHTMLDocument: HTMLDocument.isInstance(
|
||||
event.originalTarget
|
||||
),
|
||||
});
|
||||
}
|
||||
observe(subject, topic) {
|
||||
if (Window.isInstance(subject) && subject.document.isInitialDocument) {
|
||||
dump(`TEST: ignoring a topic notification for an initial about:blank\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendAsyncMessage("docshell_helpers:observe", { topic });
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
onload="startup();"
|
||||
title="bug 311007 test">
|
||||
|
||||
<script src="chrome://mochikit/content/chrome-harness.js" />
|
||||
<script type="application/javascript" src="docshell_helpers.js"></script>
|
||||
<script type="application/javascript"><![CDATA[
|
||||
// `content` is the id of the browser element used for the test.
|
||||
|
@ -8,7 +8,7 @@
|
||||
onload="nextTestAsync();"
|
||||
title="bug 582176 test">
|
||||
|
||||
<script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
|
||||
<script type="application/javascript" src="docshell_helpers.js" />
|
||||
<script type="application/javascript"><![CDATA[
|
||||
// Define the generator-iterator for the tests.
|
||||
|
@ -8,10 +8,8 @@
|
||||
onload="setTimeout(nextTest, 0);"
|
||||
title="bug 662200 test">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="docshell_helpers.js">
|
||||
</script>
|
||||
<script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
|
||||
<script type="application/javascript" src="docshell_helpers.js" />
|
||||
<script type="application/javascript"><![CDATA[
|
||||
Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
|
||||
|
||||
|
@ -43,6 +43,7 @@ support-files =
|
||||
bug909218.js
|
||||
bug92598_window.xhtml
|
||||
docshell_helpers.js
|
||||
DocShellHelpers.jsm
|
||||
file_viewsource_forbidden_in_iframe.html
|
||||
generic.html
|
||||
mozFrameType_window.xhtml
|
||||
|
@ -23,6 +23,9 @@ const { BrowserTestUtils } = ChromeUtils.import(
|
||||
);
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const ACTOR_MODULE_URI =
|
||||
"chrome://mochitests/content/chrome/docshell/test/chrome/DocShellHelpers.jsm";
|
||||
const { DocShellHelpersParent } = ChromeUtils.import(ACTOR_MODULE_URI);
|
||||
// Some functions assume chrome-harness.js has been loaded.
|
||||
/* import-globals-from ../../../testing/mochitest/chrome-harness.js */
|
||||
|
||||
@ -32,8 +35,9 @@ var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const NAV_NONE = 0;
|
||||
const NAV_BACK = 1;
|
||||
const NAV_FORWARD = 2;
|
||||
const NAV_URI = 3;
|
||||
const NAV_RELOAD = 4;
|
||||
const NAV_GOTOINDEX = 3;
|
||||
const NAV_URI = 4;
|
||||
const NAV_RELOAD = 5;
|
||||
|
||||
var gExpectedEvents; // an array of events which are expected to
|
||||
// be triggered by this navigation
|
||||
@ -61,6 +65,9 @@ var gExtractedPath = null; // used to cache file path for extracting files from
|
||||
*
|
||||
* forward: if true, the browser will execute goForward()
|
||||
*
|
||||
* gotoIndex: if a number, the browser will execute gotoIndex() with
|
||||
* the number as index
|
||||
*
|
||||
* reload: if true, the browser will execute reload()
|
||||
*
|
||||
* eventsToListenFor: an array containing one or more of the following event
|
||||
@ -91,13 +98,16 @@ var gExtractedPath = null; // used to cache file path for extracting files from
|
||||
* This property is ignored if eventsToListenFor is
|
||||
* undefined or [].
|
||||
*
|
||||
* preventBFCache: if true, an unload handler will be added to the loaded
|
||||
* preventBFCache: if true, an RTCPeerConnection will be added to the loaded
|
||||
* page to prevent it from being bfcached. This property
|
||||
* has no effect when eventsToListenFor is [].
|
||||
*
|
||||
* onNavComplete: a callback which is notified after all expected events
|
||||
* have occurred, or after a timeout has elapsed. This
|
||||
* callback is not notified if eventsToListenFor is [].
|
||||
* onGlobalCreation: a callback which is notified when a DOMWindow is created
|
||||
* (implemented by observing
|
||||
* "content-document-global-created")
|
||||
*
|
||||
* There must be an expectedEvent object for each event of the types in
|
||||
* eventsToListenFor which is triggered by this navigation. For example, if
|
||||
@ -110,6 +120,7 @@ function doPageNavigation(params) {
|
||||
// Parse the parameters.
|
||||
let back = params.back ? params.back : false;
|
||||
let forward = params.forward ? params.forward : false;
|
||||
let gotoIndex = params.gotoIndex ? params.gotoIndex : false;
|
||||
let reload = params.reload ? params.reload : false;
|
||||
let uri = params.uri ? params.uri : false;
|
||||
let eventsToListenFor =
|
||||
@ -134,20 +145,15 @@ function doPageNavigation(params) {
|
||||
typeof params.waitForEventsOnly == "boolean" && params.waitForEventsOnly;
|
||||
|
||||
// Do some sanity checking on arguments.
|
||||
if (back && forward) {
|
||||
throw new Error("Can't specify both back and forward");
|
||||
}
|
||||
if (back && uri) {
|
||||
throw new Error("Can't specify both back and a uri");
|
||||
}
|
||||
if (forward && uri) {
|
||||
throw new Error("Can't specify both forward and a uri");
|
||||
}
|
||||
if (reload && (forward || back || uri)) {
|
||||
throw new Error("Can't specify reload and another navigation type");
|
||||
}
|
||||
if (!back && !forward && !uri && !reload && !waitOnly) {
|
||||
throw new Error("Must specify back or foward or reload or uri");
|
||||
let navigation = ["back", "forward", "gotoIndex", "reload", "uri"].filter(k =>
|
||||
params.hasOwnProperty(k)
|
||||
);
|
||||
if (navigation.length > 1) {
|
||||
throw new Error(`Can't specify both ${navigation[0]} and ${navigation[1]}`);
|
||||
} else if (navigation.length == 0 && !waitOnly) {
|
||||
throw new Error(
|
||||
"Must specify back or forward or gotoIndex or reload or uri"
|
||||
);
|
||||
}
|
||||
if (params.onNavComplete && eventsToListenFor.length == 0) {
|
||||
throw new Error("Can't use onNavComplete when eventsToListenFor == []");
|
||||
@ -163,7 +169,7 @@ function doPageNavigation(params) {
|
||||
"Must specify onNavComplete when specifying waitForEventsOnly"
|
||||
);
|
||||
}
|
||||
if (waitOnly && (back || forward || reload || uri)) {
|
||||
if (waitOnly && navigation.length > 0) {
|
||||
throw new Error(
|
||||
"Can't specify a navigation type when using waitForEventsOnly"
|
||||
);
|
||||
@ -199,15 +205,83 @@ function doPageNavigation(params) {
|
||||
// events.
|
||||
gFinalEvent = eventsToListenFor.length == 0;
|
||||
|
||||
// Add observers as needed.
|
||||
let observers = new Map();
|
||||
if (params.hasOwnProperty("onGlobalCreation")) {
|
||||
observers.set("content-document-global-created", params.onGlobalCreation);
|
||||
}
|
||||
|
||||
// Add an event listener for each type of event in the .eventsToListenFor
|
||||
// property of the input parameters.
|
||||
for (let eventType of eventsToListenFor) {
|
||||
dump("TEST: registering a listener for " + eventType + " events\n");
|
||||
TestWindow.getBrowser().addEventListener(
|
||||
eventType,
|
||||
pageEventListener,
|
||||
true
|
||||
);
|
||||
// property of the input parameters, and add an observer for all the topics
|
||||
// in the observers map.
|
||||
let cleanup;
|
||||
let useActor = TestWindow.getBrowser().isRemoteBrowser;
|
||||
if (useActor) {
|
||||
ChromeUtils.registerWindowActor("DocShellHelpers", {
|
||||
parent: {
|
||||
moduleURI: ACTOR_MODULE_URI,
|
||||
},
|
||||
child: {
|
||||
moduleURI: ACTOR_MODULE_URI,
|
||||
events: {
|
||||
pageshow: { createActor: true, capture: true },
|
||||
pagehide: { createActor: true, capture: true },
|
||||
load: { createActor: true, capture: true },
|
||||
unload: { createActor: true, capture: true },
|
||||
visibilitychange: { createActor: true, capture: true },
|
||||
},
|
||||
observers: observers.keys(),
|
||||
},
|
||||
allFrames: true,
|
||||
});
|
||||
DocShellHelpersParent.eventsToListenFor = eventsToListenFor;
|
||||
DocShellHelpersParent.observers = observers;
|
||||
|
||||
cleanup = () => {
|
||||
DocShellHelpersParent.eventsToListenFor = null;
|
||||
DocShellHelpersParent.observers = null;
|
||||
ChromeUtils.unregisterWindowActor("DocShellHelpers");
|
||||
};
|
||||
} else {
|
||||
for (let eventType of eventsToListenFor) {
|
||||
dump("TEST: registering a listener for " + eventType + " events\n");
|
||||
TestWindow.getBrowser().addEventListener(
|
||||
eventType,
|
||||
pageEventListener,
|
||||
true
|
||||
);
|
||||
}
|
||||
if (observers.size > 0) {
|
||||
let observer = (_, topic) => {
|
||||
observers.get(topic).call();
|
||||
};
|
||||
for (let topic of observers.keys()) {
|
||||
Services.obs.addObserver(observer, topic);
|
||||
}
|
||||
|
||||
// We only need to do cleanup for the observer, the event listeners will
|
||||
// go away with the window.
|
||||
cleanup = () => {
|
||||
for (let topic of observers.keys()) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (cleanup) {
|
||||
// Register a cleanup function on domwindowclosed, to avoid contaminating
|
||||
// other tests if we bail out early because of an error.
|
||||
Services.ww.registerNotification(function windowClosed(
|
||||
subject,
|
||||
topic,
|
||||
data
|
||||
) {
|
||||
if (topic == "domwindowclosed" && subject == window) {
|
||||
Services.ww.unregisterNotification(windowClosed);
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Perform the specified navigation.
|
||||
@ -217,6 +291,9 @@ function doPageNavigation(params) {
|
||||
} else if (forward) {
|
||||
gNavType = NAV_FORWARD;
|
||||
TestWindow.getBrowser().goForward();
|
||||
} else if (typeof gotoIndex == "number") {
|
||||
gNavType = NAV_GOTOINDEX;
|
||||
TestWindow.getBrowser().gotoIndex(gotoIndex);
|
||||
} else if (uri) {
|
||||
gNavType = NAV_URI;
|
||||
BrowserTestUtils.loadURI(TestWindow.getBrowser(), uri);
|
||||
@ -240,10 +317,14 @@ function doPageNavigation(params) {
|
||||
doPageNavigation_complete(
|
||||
eventsToListenFor,
|
||||
params.onNavComplete,
|
||||
preventBFCache
|
||||
preventBFCache,
|
||||
useActor,
|
||||
cleanup
|
||||
);
|
||||
}
|
||||
);
|
||||
} else if (cleanup) {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,33 +337,42 @@ function doPageNavigation(params) {
|
||||
function doPageNavigation_complete(
|
||||
eventsToListenFor,
|
||||
onNavComplete,
|
||||
preventBFCache
|
||||
preventBFCache,
|
||||
useActor,
|
||||
cleanup
|
||||
) {
|
||||
// Unregister our event listeners.
|
||||
dump("TEST: removing event listeners\n");
|
||||
for (let eventType of eventsToListenFor) {
|
||||
TestWindow.getBrowser().removeEventListener(
|
||||
eventType,
|
||||
pageEventListener,
|
||||
true
|
||||
);
|
||||
if (useActor) {
|
||||
if (preventBFCache) {
|
||||
let actor = TestWindow.getBrowser().browsingContext.currentWindowGlobal.getActor(
|
||||
"DocShellHelpers"
|
||||
);
|
||||
actor.sendAsyncMessage("docshell_helpers:preventBFCache");
|
||||
}
|
||||
} else {
|
||||
// Unregister our event listeners.
|
||||
dump("TEST: removing event listeners\n");
|
||||
for (let eventType of eventsToListenFor) {
|
||||
TestWindow.getBrowser().removeEventListener(
|
||||
eventType,
|
||||
pageEventListener,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// If the .preventBFCache property was set, add an RTCPeerConnection to
|
||||
// prevent the page from being bfcached.
|
||||
if (preventBFCache) {
|
||||
let win = TestWindow.getWindow();
|
||||
win.blockBFCache = new win.RTCPeerConnection();
|
||||
}
|
||||
}
|
||||
|
||||
if (cleanup) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
// If the .preventBFCache property was set, add an empty unload handler to
|
||||
// prevent the page from being bfcached.
|
||||
let uri = TestWindow.getBrowser().currentURI.spec;
|
||||
if (preventBFCache) {
|
||||
TestWindow.getWindow().addEventListener(
|
||||
"unload",
|
||||
function() {
|
||||
dump(
|
||||
"TEST: Called dummy unload function to prevent page from " +
|
||||
"being bfcached.\n"
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// Save the current uri in an array of uri's which shouldn't be
|
||||
// stored in the bfcache, for later verification.
|
||||
if (!(uri in gUrisNotInBFCache)) {
|
||||
@ -302,6 +392,18 @@ function doPageNavigation_complete(
|
||||
onNavComplete.call();
|
||||
}
|
||||
|
||||
function promisePageNavigation(params) {
|
||||
if (params.hasOwnProperty("onNavComplete")) {
|
||||
throw new Error(
|
||||
"Can't use a onNavComplete completion callback with promisePageNavigation."
|
||||
);
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
params.onNavComplete = resolve;
|
||||
doPageNavigation(params);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a test to wait for page navigation events, and notify a
|
||||
* callback when they've all been received. This works exactly the
|
||||
@ -312,10 +414,26 @@ function waitForPageEvents(params) {
|
||||
doPageNavigation(params);
|
||||
}
|
||||
|
||||
function promisePageEvents(params) {
|
||||
if (params.hasOwnProperty("onNavComplete")) {
|
||||
throw new Error(
|
||||
"Can't use a onNavComplete completion callback with promisePageEvents."
|
||||
);
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
params.waitForEventsOnly = true;
|
||||
params.onNavComplete = resolve;
|
||||
doPageNavigation(params);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The event listener which listens for expectedEvents.
|
||||
*/
|
||||
function pageEventListener(event) {
|
||||
function pageEventListener(
|
||||
event,
|
||||
originalTargetIsHTMLDocument = event.originalTarget instanceof HTMLDocument
|
||||
) {
|
||||
try {
|
||||
dump(
|
||||
"TEST: eventListener received a " +
|
||||
@ -336,7 +454,9 @@ function pageEventListener(event) {
|
||||
// for .persisted.
|
||||
if (
|
||||
event.type == "pageshow" &&
|
||||
(gNavType == NAV_BACK || gNavType == NAV_FORWARD)
|
||||
(gNavType == NAV_BACK ||
|
||||
gNavType == NAV_FORWARD ||
|
||||
gNavType == NAV_GOTOINDEX)
|
||||
) {
|
||||
let uri = TestWindow.getBrowser().currentURI.spec;
|
||||
if (uri in gUrisNotInBFCache) {
|
||||
@ -389,7 +509,7 @@ function pageEventListener(event) {
|
||||
|
||||
if (typeof expected.title != "undefined") {
|
||||
ok(
|
||||
event.originalTarget instanceof HTMLDocument,
|
||||
originalTargetIsHTMLDocument,
|
||||
"originalTarget for last " + event.type + " event not an HTMLDocument"
|
||||
);
|
||||
is(
|
||||
@ -444,21 +564,24 @@ function pageEventListener(event) {
|
||||
}
|
||||
}
|
||||
|
||||
DocShellHelpersParent.eventListener = pageEventListener;
|
||||
|
||||
/**
|
||||
* End a test.
|
||||
*/
|
||||
function finish() {
|
||||
// Work around bug 467960.
|
||||
let history;
|
||||
let historyPurged;
|
||||
if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
|
||||
history = TestWindow.getBrowser().browsingContext?.sessionHistory;
|
||||
} else {
|
||||
history = TestWindow.getBrowser().webNavigation.sessionHistory
|
||||
.legacySHistory;
|
||||
}
|
||||
|
||||
if (history) {
|
||||
let history = TestWindow.getBrowser().browsingContext?.sessionHistory;
|
||||
history.purgeHistory(history.count);
|
||||
historyPurged = Promise.resolve();
|
||||
} else {
|
||||
historyPurged = SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
|
||||
let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory
|
||||
.legacySHistory;
|
||||
history.purgeHistory(history.count);
|
||||
});
|
||||
}
|
||||
|
||||
// If the test changed the value of max_total_viewers via a call to
|
||||
@ -482,7 +605,9 @@ function finish() {
|
||||
}
|
||||
});
|
||||
|
||||
window.close();
|
||||
historyPurged.then(_ => {
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -503,7 +628,12 @@ function finish() {
|
||||
* time out.
|
||||
*/
|
||||
function waitForTrue(fn, onWaitComplete, timeout) {
|
||||
var start = new Date().valueOf();
|
||||
promiseTrue(fn, timeout).then(() => {
|
||||
onWaitComplete.call();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseTrue(fn, timeout) {
|
||||
if (typeof timeout != "undefined") {
|
||||
// If timeoutWait is less than 500, assume it represents seconds, and
|
||||
// convert to ms.
|
||||
@ -514,27 +644,43 @@ function waitForTrue(fn, onWaitComplete, timeout) {
|
||||
|
||||
// Loop until the test function returns true, or until a timeout occurs,
|
||||
// if a timeout is defined.
|
||||
var intervalid;
|
||||
intervalid = setInterval(function() {
|
||||
var timeoutHit = false;
|
||||
if (typeof timeout != "undefined") {
|
||||
timeoutHit = new Date().valueOf() - start >= timeout;
|
||||
if (timeoutHit) {
|
||||
ok(false, "Timed out waiting for condition");
|
||||
let intervalid, timeoutid;
|
||||
let condition = new Promise(resolve => {
|
||||
intervalid = setInterval(async () => {
|
||||
if (await fn.call()) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
if (timeoutHit || fn.call()) {
|
||||
// Stop calling the test function and notify the callback.
|
||||
}, 20);
|
||||
});
|
||||
if (typeof timeout != "undefined") {
|
||||
condition = Promise.race([
|
||||
condition,
|
||||
new Promise((_, reject) => {
|
||||
timeoutid = setTimeout(() => {
|
||||
reject();
|
||||
}, timeout);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
return condition
|
||||
.finally(() => {
|
||||
clearInterval(intervalid);
|
||||
onWaitComplete.call();
|
||||
}
|
||||
}, 20);
|
||||
})
|
||||
.then(() => {
|
||||
clearTimeout(timeoutid);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForNextPaint(cb) {
|
||||
requestAnimationFrame(_ => requestAnimationFrame(cb));
|
||||
}
|
||||
|
||||
function promiseNextPaint() {
|
||||
return new Promise(resolve => {
|
||||
waitForNextPaint(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the bfcache.
|
||||
*
|
||||
|
@ -9,7 +9,6 @@
|
||||
<html:iframe id="normalFrame"/>
|
||||
<html:iframe id="typeContentFrame" mozframetype="content"/>
|
||||
|
||||
<script type="application/javascript" src="docshell_helpers.js" />
|
||||
<script type="application/javascript"><![CDATA[
|
||||
function runTests() {
|
||||
let opener = window.arguments[0];
|
||||
|
@ -12,6 +12,7 @@
|
||||
window.opener = window.arguments[0];
|
||||
]]></script>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/docshell_helpers.js">
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user