summaryrefslogtreecommitdiffstats
path: root/b2g/components/test/mochitest/systemapp_helper.js
blob: 768b221fef36d85b837fe326e30471f57496ff35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
var Cu = Components.utils;

const { Services } = Cu.import("resource://gre/modules/Services.jsm");

// Load a duplicated copy of the jsm to prevent messing with the currently running one
var scope = {};
Services.scriptloader.loadSubScript("resource://gre/modules/SystemAppProxy.jsm", scope);
const { SystemAppProxy } = scope;

var frame;
var customEventTarget;

var index = -1;
function next() {
  index++;
  if (index >= steps.length) {
    assert.ok(false, "Shouldn't get here!");
    return;
  }
  try {
    steps[index]();
  } catch(ex) {
    assert.ok(false, "Caught exception: " + ex);
  }
}

// Listen for events received by the system app document
// to ensure that we receive all of them, in an expected order and time
var isLoaded = false;
var isReady = false;
var n = 0;
function listener(event) {
  if (!isLoaded) {
    assert.ok(false, "Received event before the iframe is loaded");
    return;
  }
  n++;
  if (n == 1) {
    assert.equal(event.type, "mozChromeEvent");
    assert.equal(event.detail.name, "first");
  } else if (n == 2) {
    assert.equal(event.type, "custom");
    assert.equal(event.detail.name, "second");

    next(); // call checkEventPendingBeforeLoad
  } else if (n == 3) {
    if (!isReady) {
      assert.ok(false, "Received event before the iframe is loaded");
      return;
    }

    assert.equal(event.type, "custom");
    assert.equal(event.detail.name, "third");
  } else if (n == 4) {
    if (!isReady) {
      assert.ok(false, "Received event before the iframe is loaded");
      return;
    }

    assert.equal(event.type, "mozChromeEvent");
    assert.equal(event.detail.name, "fourth");

    next(); // call checkEventDispatching
  } else if (n == 5) {
    assert.equal(event.type, "custom");
    assert.equal(event.detail.name, "fifth");
  } else if (n === 6) {
    assert.equal(event.type, "mozChromeEvent");
    assert.equal(event.detail.name, "sixth");
  } else if (n === 7) {
    assert.equal(event.type, "custom");
    assert.equal(event.detail.name, "seventh");
    assert.equal(event.target, customEventTarget);

    next(); // call checkEventListening();
  } else {
    assert.ok(false, "Unexpected event of type " + event.type);
  }
}


var steps = [
  function earlyEvents() {
    // Immediately try to send events
    SystemAppProxy._sendCustomEvent("mozChromeEvent", { name: "first" }, true);
    SystemAppProxy._sendCustomEvent("custom", { name: "second" }, true);
    next();
  },

  function createFrame() {
    // Create a fake system app frame
    let win = Services.wm.getMostRecentWindow("navigator:browser");
    let doc = win.document;
    frame = doc.createElement("iframe");
    doc.documentElement.appendChild(frame);

    customEventTarget = frame.contentDocument.body;

    // Ensure that events are correctly sent to the frame.
    // `listener` is going to call next()
    frame.contentWindow.addEventListener("mozChromeEvent", listener);
    frame.contentWindow.addEventListener("custom", listener);

    // Ensure that listener being registered before the system app is ready
    // are correctly removed from the pending list
    function removedListener() {
      assert.ok(false, "Listener isn't correctly removed from the pending list");
    }
    SystemAppProxy.addEventListener("mozChromeEvent", removedListener);
    SystemAppProxy.removeEventListener("mozChromeEvent", removedListener);

    // Register it to the JSM
    SystemAppProxy.registerFrame(frame);
    assert.ok(true, "Frame created and registered");

    frame.contentWindow.addEventListener("load", function onload() {
      frame.contentWindow.removeEventListener("load", onload);
      assert.ok(true, "Frame document loaded");

      // Declare that the iframe is now loaded.
      // That should dispatch early events
      isLoaded = true;
      SystemAppProxy.setIsLoaded();
      assert.ok(true, "Frame declared as loaded");

      let gotFrame = SystemAppProxy.getFrame();
      assert.equal(gotFrame, frame, "getFrame returns the frame we passed");

      // Once pending events are received,
      // we will run checkEventDispatching from `listener` function
    });

    frame.setAttribute("src", "data:text/html,system app");
  },

  function checkEventPendingBeforeLoad() {
    // Frame is loaded but not ready,
    // these events should queue before the System app is ready.
    SystemAppProxy._sendCustomEvent("custom", { name: "third" });
    SystemAppProxy.dispatchEvent({ name: "fourth" });

    isReady = true;
    SystemAppProxy.setIsReady();
    // Once this 4th event is received, we will run checkEventDispatching
  },

  function checkEventDispatching() {
    // Send events after the iframe is ready,
    // they should be dispatched right away
    SystemAppProxy._sendCustomEvent("custom", { name: "fifth" });
    SystemAppProxy.dispatchEvent({ name: "sixth" });
    SystemAppProxy._sendCustomEvent("custom", { name: "seventh" }, false, customEventTarget);
    // Once this 7th event is received, we will run checkEventListening
  },

  function checkEventListening() {
    SystemAppProxy.addEventListener("mozContentEvent", function onContentEvent(event) {
      assert.equal(event.detail.name, "first-content", "received a system app event");
      SystemAppProxy.removeEventListener("mozContentEvent", onContentEvent);

      next();
    });
    let win = frame.contentWindow;
    win.dispatchEvent(new win.CustomEvent("mozContentEvent", { detail: {name: "first-content"} }));
  },

  function endOfTest() {
    frame.remove();
    sendAsyncMessage("finish");
  }
];

next();