diff -r 000000000000 -r 6474c204b198 testing/mochitest/mochitest-e10s-utils.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testing/mochitest/mochitest-e10s-utils.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,87 @@ +// 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); +}