// Utilities for running tests in an e10s environment. // There are some tricks/shortcuts that test code takes that we don't see // in the real browser code. These include setting content.location.href // (which doesn't work in test code with e10s enabled as the document object // is yet to be created), waiting for certain events the main browser doesn't // care about and so doesn't normally get special support, eg, the "pageshow" // or "load" events). // So we make some hacks to pretend these work in the test suite. // Ideally all these hacks could be removed, but this can only happen when // the tests are refactored to not use these tricks. But this would be a huge // amount of work and is unlikely to happen anytime soon... const CONTENT_URL = "chrome://mochikit/content/mochitest-e10s-utils-content.js"; // This is an object that is used as the "location" on a remote document or // window. It will be overwritten as the real document and window are made // available. let locationStub = function(browser) { this.browser = browser; }; locationStub.prototype = { get href() { return this.browser.webNavigation.currentURI.spec; }, set href(val) { this.browser.loadURI(val); }, assign: function(url) { this.href = url; } }; // This object is used in place of contentWindow while we wait for it to be // overwritten as the real window becomes available. let TemporaryWindowStub = function(browser) { this._locationStub = new locationStub(browser); }; TemporaryWindowStub.prototype = { // save poor developers from getting confused about why the window isn't // working like a window should.. toString: function() { return "[Window Stub for e10s tests]"; }, get location() { return this._locationStub; }, set location(val) { this._locationStub.href = val; }, get document() { // so tests can say: document.location.... return this; } }; // An observer called when a new remote browser element is created. We replace // the _contentWindow in new browsers with our TemporaryWindowStub object. function observeNewFrameloader(subject, topic, data) { let browser = subject.QueryInterface(Ci.nsIFrameLoader).ownerElement; browser._contentWindow = new TemporaryWindowStub(browser); } function e10s_init() { // Use the global message manager to inject a content script into all browsers. let globalMM = Cc["@mozilla.org/globalmessagemanager;1"] .getService(Ci.nsIMessageListenerManager); globalMM.loadFrameScript(CONTENT_URL, true); globalMM.addMessageListener("Test:Event", function(message) { let event = document.createEvent('HTMLEvents'); event.initEvent(message.data.name, true, true, {}); message.target.dispatchEvent(event); }); // We add an observer so we can notice new elements created Services.obs.addObserver(observeNewFrameloader, "remote-browser-shown", false); // Listen for an 'oop-browser-crashed' event and log it so people analysing // test logs have a clue about what is going on. window.addEventListener("oop-browser-crashed", (event) => { let uri = event.target.currentURI; Cu.reportError("remote browser crashed while on " + (uri ? uri.spec : "") + "\n"); }, true); }