|
1 // Utilities for running tests in an e10s environment. |
|
2 |
|
3 // There are some tricks/shortcuts that test code takes that we don't see |
|
4 // in the real browser code. These include setting content.location.href |
|
5 // (which doesn't work in test code with e10s enabled as the document object |
|
6 // is yet to be created), waiting for certain events the main browser doesn't |
|
7 // care about and so doesn't normally get special support, eg, the "pageshow" |
|
8 // or "load" events). |
|
9 // So we make some hacks to pretend these work in the test suite. |
|
10 |
|
11 // Ideally all these hacks could be removed, but this can only happen when |
|
12 // the tests are refactored to not use these tricks. But this would be a huge |
|
13 // amount of work and is unlikely to happen anytime soon... |
|
14 |
|
15 const CONTENT_URL = "chrome://mochikit/content/mochitest-e10s-utils-content.js"; |
|
16 |
|
17 // This is an object that is used as the "location" on a remote document or |
|
18 // window. It will be overwritten as the real document and window are made |
|
19 // available. |
|
20 let locationStub = function(browser) { |
|
21 this.browser = browser; |
|
22 }; |
|
23 locationStub.prototype = { |
|
24 get href() { |
|
25 return this.browser.webNavigation.currentURI.spec; |
|
26 }, |
|
27 set href(val) { |
|
28 this.browser.loadURI(val); |
|
29 }, |
|
30 assign: function(url) { |
|
31 this.href = url; |
|
32 } |
|
33 }; |
|
34 |
|
35 // This object is used in place of contentWindow while we wait for it to be |
|
36 // overwritten as the real window becomes available. |
|
37 let TemporaryWindowStub = function(browser) { |
|
38 this._locationStub = new locationStub(browser); |
|
39 }; |
|
40 |
|
41 TemporaryWindowStub.prototype = { |
|
42 // save poor developers from getting confused about why the window isn't |
|
43 // working like a window should.. |
|
44 toString: function() { |
|
45 return "[Window Stub for e10s tests]"; |
|
46 }, |
|
47 get location() { |
|
48 return this._locationStub; |
|
49 }, |
|
50 set location(val) { |
|
51 this._locationStub.href = val; |
|
52 }, |
|
53 get document() { |
|
54 // so tests can say: document.location.... |
|
55 return this; |
|
56 } |
|
57 }; |
|
58 |
|
59 // An observer called when a new remote browser element is created. We replace |
|
60 // the _contentWindow in new browsers with our TemporaryWindowStub object. |
|
61 function observeNewFrameloader(subject, topic, data) { |
|
62 let browser = subject.QueryInterface(Ci.nsIFrameLoader).ownerElement; |
|
63 browser._contentWindow = new TemporaryWindowStub(browser); |
|
64 } |
|
65 |
|
66 function e10s_init() { |
|
67 // Use the global message manager to inject a content script into all browsers. |
|
68 let globalMM = Cc["@mozilla.org/globalmessagemanager;1"] |
|
69 .getService(Ci.nsIMessageListenerManager); |
|
70 globalMM.loadFrameScript(CONTENT_URL, true); |
|
71 globalMM.addMessageListener("Test:Event", function(message) { |
|
72 let event = document.createEvent('HTMLEvents'); |
|
73 event.initEvent(message.data.name, true, true, {}); |
|
74 message.target.dispatchEvent(event); |
|
75 }); |
|
76 |
|
77 // We add an observer so we can notice new <browser> elements created |
|
78 Services.obs.addObserver(observeNewFrameloader, "remote-browser-shown", false); |
|
79 |
|
80 // Listen for an 'oop-browser-crashed' event and log it so people analysing |
|
81 // test logs have a clue about what is going on. |
|
82 window.addEventListener("oop-browser-crashed", (event) => { |
|
83 let uri = event.target.currentURI; |
|
84 Cu.reportError("remote browser crashed while on " + |
|
85 (uri ? uri.spec : "<unknown>") + "\n"); |
|
86 }, true); |
|
87 } |