summaryrefslogtreecommitdiffstats
path: root/browser/modules/test/browser_SelfSupportBackend.js
blob: 9e2c1d1813735e534076d48c23e7ed0d4987956d (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

// Pass an empty scope object to the import to prevent "leaked window property"
// errors in tests.
var Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
var PromiseUtils = Cu.import("resource://gre/modules/PromiseUtils.jsm", {}).PromiseUtils;
var SelfSupportBackend =
  Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackend;

const PREF_SELFSUPPORT_ENABLED = "browser.selfsupport.enabled";
const PREF_SELFSUPPORT_URL = "browser.selfsupport.url";
const PREF_UITOUR_ENABLED = "browser.uitour.enabled";

const TEST_WAIT_RETRIES = 60;

const TEST_PAGE_URL = getRootDirectory(gTestPath) + "uitour.html";
const TEST_PAGE_URL_HTTPS = TEST_PAGE_URL.replace("chrome://mochitests/content/", "https://example.com/");

function sendSessionRestoredNotification() {
  let selfSupportBackendImpl =
    Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
  selfSupportBackendImpl.observe(null, "sessionstore-windows-restored", null);
}

/**
 * Find a browser, with an IFRAME as parent, who has aURL as the source attribute.
 *
 * @param aURL The URL to look for to identify the browser.
 *
 * @returns {Object} The browser element or null on failure.
 */
function findSelfSupportBrowser(aURL) {
  let frames = Services.appShell.hiddenDOMWindow.document.querySelectorAll('iframe');
  for (let frame of frames) {
    try {
      let browser = frame.contentDocument.getElementById("win").querySelectorAll('browser')[0];
      let url = browser.getAttribute("src");
      if (url == aURL) {
        return browser;
      }
    } catch (e) {
      continue;
    }
  }
  return null;
}

/**
 * Wait for self support page to load.
 *
 * @param aURL The URL to look for to identify the browser.
 *
 * @returns {Promise} Return a promise which is resolved when SelfSupport page is fully
 *          loaded.
 */
function promiseSelfSupportLoad(aURL) {
  return new Promise((resolve, reject) => {
    // Find the SelfSupport browser.
    let browserPromise = waitForConditionPromise(() => !!findSelfSupportBrowser(aURL),
                                                 "SelfSupport browser not found.",
                                                 TEST_WAIT_RETRIES);

    // Once found, append a "load" listener to catch page loads.
    browserPromise.then(() => {
      let browser = findSelfSupportBrowser(aURL);
      if (browser.contentDocument.readyState === "complete") {
        resolve(browser);
      } else {
        let handler = () => {
          browser.removeEventListener("load", handler, true);
          resolve(browser);
        };
        browser.addEventListener("load", handler, true);
      }
    }, reject);
  });
}

/**
 * Wait for self support to close.
 *
 * @param aURL The URL to look for to identify the browser.
 *
 * @returns {Promise} Return a promise which is resolved when SelfSupport browser cannot
 *          be found anymore.
 */
function promiseSelfSupportClose(aURL) {
  return waitForConditionPromise(() => !findSelfSupportBrowser(aURL),
                                 "SelfSupport browser is still open.", TEST_WAIT_RETRIES);
}

/**
 * Prepare the test environment.
 */
add_task(function* setupEnvironment() {
  // We always run the SelfSupportBackend in tests to check for weird behaviours.
  // Disable it to test its start-up.
  SelfSupportBackend.uninit();

  // Testing prefs are set via |user_pref|, so we need to get their value in order
  // to restore them.
  let selfSupportEnabled = Preferences.get(PREF_SELFSUPPORT_ENABLED, true);
  let uitourEnabled = Preferences.get(PREF_UITOUR_ENABLED, false);
  let selfSupportURL = Preferences.get(PREF_SELFSUPPORT_URL, "");

  // Enable the SelfSupport backend and set the page URL. We also make sure UITour
  // is enabled.
  Preferences.set(PREF_SELFSUPPORT_ENABLED, true);
  Preferences.set(PREF_UITOUR_ENABLED, true);
  Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL_HTTPS);

  // Whitelist the HTTPS page to use UITour.
  let pageURI = Services.io.newURI(TEST_PAGE_URL_HTTPS, null, null);
  Services.perms.add(pageURI, "uitour", Services.perms.ALLOW_ACTION);

  registerCleanupFunction(() => {
    Services.perms.remove(pageURI, "uitour");
    Preferences.set(PREF_SELFSUPPORT_ENABLED, selfSupportEnabled);
    Preferences.set(PREF_UITOUR_ENABLED, uitourEnabled);
    Preferences.set(PREF_SELFSUPPORT_URL, selfSupportURL);
  });
});

/**
 * Test that the self support page can use the UITour API and close itself.
 */
add_task(function* test_selfSupport() {
  // Initialise the SelfSupport backend and trigger the load.
  SelfSupportBackend.init();

  // SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
  info("Sending sessionstore-windows-restored");
  sendSessionRestoredNotification();

  // Wait for the SelfSupport page to load.
  info("Waiting for the SelfSupport local page to load.");
  let selfSupportBrowser = yield promiseSelfSupportLoad(TEST_PAGE_URL_HTTPS);
  Assert.ok(!!selfSupportBrowser, "SelfSupport browser must exist.");

  // Get a reference to the UITour API.
  info("Testing access to the UITour API.");
  let contentWindow =
    Cu.waiveXrays(selfSupportBrowser.contentDocument.defaultView);
  let uitourAPI = contentWindow.Mozilla.UITour;

  // Test the UITour API with a ping.
  let pingPromise = new Promise((resolve) => {
    uitourAPI.ping(resolve);
  });
  yield pingPromise;
  info("Ping succeeded");

  let observePromise = ContentTask.spawn(selfSupportBrowser, null, function* checkObserve() {
    yield new Promise(resolve => {
      let win = Cu.waiveXrays(content);
      win.Mozilla.UITour.observe((event, data) => {
        if (event != "Heartbeat:Engaged") {
          return;
        }
        Assert.equal(data.flowId, "myFlowID", "Check flowId");
        Assert.ok(!!data.timestamp, "Check timestamp");
        resolve(data);
      }, () => {});
    });
  });

  info("Notifying Heartbeat:Engaged");
  UITour.notify("Heartbeat:Engaged", {
    flowId: "myFlowID",
    timestamp: Date.now(),
  });
  yield observePromise;
  info("Observed in the hidden frame");

  // Close SelfSupport from content.
  contentWindow.close();

  // Wait until SelfSupport closes.
  info("Waiting for the SelfSupport to close.");
  yield promiseSelfSupportClose(TEST_PAGE_URL_HTTPS);

  // Find the SelfSupport browser, again. We don't expect to find it.
  selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL_HTTPS);
  Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");

  // We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
  // doesn't create any problem.
  SelfSupportBackend.uninit();
});

/**
 * Test that SelfSupportBackend only allows HTTPS.
 */
add_task(function* test_selfSupport_noHTTPS() {
  Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL);

  SelfSupportBackend.init();

  // SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
  info("Sending sessionstore-windows-restored");
  sendSessionRestoredNotification();

  // Find the SelfSupport browser. We don't expect to find it since we are not using https.
  let selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL);
  Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");

  // We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
  // doesn't create any problem.
  SelfSupportBackend.uninit();
})