|
1 const Cu = Components.utils; |
|
2 |
|
3 const { Services } = Cu.import("resource://gre/modules/Services.jsm"); |
|
4 |
|
5 // Load a duplicated copy of the jsm to prevent messing with the currently running one |
|
6 let scope = {}; |
|
7 Services.scriptloader.loadSubScript("resource://gre/modules/SystemAppProxy.jsm", scope); |
|
8 const { SystemAppProxy } = scope; |
|
9 |
|
10 let frame; |
|
11 |
|
12 let index = -1; |
|
13 function next() { |
|
14 index++; |
|
15 if (index >= steps.length) { |
|
16 assert.ok(false, "Shouldn't get here!"); |
|
17 return; |
|
18 } |
|
19 try { |
|
20 steps[index](); |
|
21 } catch(ex) { |
|
22 assert.ok(false, "Caught exception: " + ex); |
|
23 } |
|
24 } |
|
25 |
|
26 // Listen for events received by the system app document |
|
27 // to ensure that we receive all of them, in an expected order and time |
|
28 let isLoaded = false; |
|
29 let n = 0; |
|
30 function listener(event) { |
|
31 if (!isLoaded) { |
|
32 assert.ok(false, "Received event before the iframe is ready"); |
|
33 return; |
|
34 } |
|
35 n++; |
|
36 if (n == 1) { |
|
37 assert.equal(event.type, "mozChromeEvent"); |
|
38 assert.equal(event.detail.name, "first"); |
|
39 } else if (n == 2) { |
|
40 assert.equal(event.type, "custom"); |
|
41 assert.equal(event.detail.name, "second"); |
|
42 |
|
43 next(); // call checkEventDispatching |
|
44 } else if (n == 3) { |
|
45 assert.equal(event.type, "custom"); |
|
46 assert.equal(event.detail.name, "third"); |
|
47 } else if (n == 4) { |
|
48 assert.equal(event.type, "mozChromeEvent"); |
|
49 assert.equal(event.detail.name, "fourth"); |
|
50 |
|
51 next(); // call checkEventListening(); |
|
52 } else { |
|
53 assert.ok(false, "Unexpected event of type " + event.type); |
|
54 } |
|
55 } |
|
56 |
|
57 |
|
58 let steps = [ |
|
59 function waitForWebapps() { |
|
60 // We are using webapps API later in this test and we need to ensure |
|
61 // it is fully initialized before trying to use it |
|
62 let { DOMApplicationRegistry } = Cu.import('resource://gre/modules/Webapps.jsm', {}); |
|
63 DOMApplicationRegistry.registryReady.then(function () { |
|
64 next(); |
|
65 }); |
|
66 }, |
|
67 |
|
68 function earlyEvents() { |
|
69 // Immediately try to send events |
|
70 SystemAppProxy.dispatchEvent({ name: "first" }); |
|
71 SystemAppProxy._sendCustomEvent("custom", { name: "second" }); |
|
72 next(); |
|
73 }, |
|
74 |
|
75 function createFrame() { |
|
76 // Create a fake system app frame |
|
77 let win = Services.wm.getMostRecentWindow("navigator:browser"); |
|
78 let doc = win.document; |
|
79 frame = doc.createElement("iframe"); |
|
80 doc.documentElement.appendChild(frame); |
|
81 |
|
82 // Ensure that events are correctly sent to the frame. |
|
83 // `listener` is going to call next() |
|
84 frame.contentWindow.addEventListener("mozChromeEvent", listener); |
|
85 frame.contentWindow.addEventListener("custom", listener); |
|
86 |
|
87 // Ensure that listener being registered before the system app is ready |
|
88 // are correctly removed from the pending list |
|
89 function removedListener() { |
|
90 assert(false, "Listener isn't correctly removed from the pending list"); |
|
91 } |
|
92 SystemAppProxy.addEventListener("mozChromeEvent", removedListener); |
|
93 SystemAppProxy.removeEventListener("mozChromeEvent", removedListener); |
|
94 |
|
95 // Register it to the JSM |
|
96 SystemAppProxy.registerFrame(frame); |
|
97 assert.ok(true, "Frame created and registered"); |
|
98 |
|
99 frame.contentWindow.addEventListener("load", function onload() { |
|
100 frame.contentWindow.removeEventListener("load", onload); |
|
101 assert.ok(true, "Frame document loaded"); |
|
102 |
|
103 // Declare that the iframe is now loaded. |
|
104 // That should dispatch early events |
|
105 isLoaded = true; |
|
106 SystemAppProxy.setIsReady(); |
|
107 assert.ok(true, "Frame declared as loaded"); |
|
108 |
|
109 // Once pending events are received, |
|
110 // we will run checkEventDispatching from `listener` function |
|
111 }); |
|
112 |
|
113 frame.setAttribute("src", "data:text/html,system app"); |
|
114 }, |
|
115 |
|
116 function checkEventDispatching() { |
|
117 // Send events after the iframe is ready, |
|
118 // they should be dispatched right away |
|
119 SystemAppProxy._sendCustomEvent("custom", { name: "third" }); |
|
120 SystemAppProxy.dispatchEvent({ name: "fourth" }); |
|
121 // Once this 4th event is received, we will run checkEventListening |
|
122 }, |
|
123 |
|
124 function checkEventListening() { |
|
125 SystemAppProxy.addEventListener("mozContentEvent", function onContentEvent(event) { |
|
126 assert.equal(event.detail.name, "first-content", "received a system app event"); |
|
127 SystemAppProxy.removeEventListener("mozContentEvent", onContentEvent); |
|
128 |
|
129 next(); |
|
130 }); |
|
131 let win = frame.contentWindow; |
|
132 win.dispatchEvent(new win.CustomEvent("mozContentEvent", { detail: {name: "first-content"} })); |
|
133 }, |
|
134 |
|
135 function endOfTest() { |
|
136 frame.remove(); |
|
137 sendAsyncMessage("finish"); |
|
138 } |
|
139 ]; |
|
140 |
|
141 next(); |