addon-sdk/source/test/windows/test-firefox-windows.js

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 'use strict';
michael@0 5
michael@0 6 const { Cc, Ci } = require('chrome');
michael@0 7 const { setTimeout } = require('sdk/timers');
michael@0 8 const { Loader } = require('sdk/test/loader');
michael@0 9 const { onFocus, getMostRecentWindow, windows, isBrowser, getWindowTitle } = require('sdk/window/utils');
michael@0 10 const { open, close, focus } = require('sdk/window/helpers');
michael@0 11 const { browserWindows } = require("sdk/windows");
michael@0 12 const tabs = require("sdk/tabs");
michael@0 13 const winUtils = require("sdk/deprecated/window-utils");
michael@0 14 const { WindowTracker } = winUtils;
michael@0 15 const { isPrivate } = require('sdk/private-browsing');
michael@0 16 const { isWindowPBSupported } = require('sdk/private-browsing/utils');
michael@0 17 const { viewFor } = require("sdk/view/core");
michael@0 18 const { defer } = require("sdk/lang/functional");
michael@0 19
michael@0 20 // TEST: open & close window
michael@0 21 exports.testOpenAndCloseWindow = function(assert, done) {
michael@0 22 assert.equal(browserWindows.length, 1, "Only one window open");
michael@0 23 let title = 'testOpenAndCloseWindow';
michael@0 24
michael@0 25 browserWindows.open({
michael@0 26 url: "data:text/html;charset=utf-8,<title>" + title + "</title>",
michael@0 27 onOpen: function(window) {
michael@0 28 assert.equal(this, browserWindows, "The 'this' object is the windows object.");
michael@0 29 assert.equal(window.tabs.length, 1, "Only one tab open");
michael@0 30 assert.equal(browserWindows.length, 2, "Two windows open");
michael@0 31
michael@0 32 window.tabs.activeTab.once('ready', function onReady(tab) {
michael@0 33 assert.pass(RegExp(title).test(window.title), "URL correctly loaded");
michael@0 34 window.close();
michael@0 35 });
michael@0 36 },
michael@0 37 onClose: function(window) {
michael@0 38 assert.equal(window.tabs.length, 0, "Tabs were cleared");
michael@0 39 assert.equal(browserWindows.length, 1, "Only one window open");
michael@0 40 done();
michael@0 41 }
michael@0 42 });
michael@0 43 };
michael@0 44
michael@0 45 exports.testAutomaticDestroy = function(assert, done) {
michael@0 46 let windows = browserWindows;
michael@0 47
michael@0 48 // Create a second windows instance that we will unload
michael@0 49 let called = false;
michael@0 50 let loader = Loader(module);
michael@0 51 let windows2 = loader.require("sdk/windows").browserWindows;
michael@0 52
michael@0 53 windows2.on("open", function() {
michael@0 54 called = true;
michael@0 55 });
michael@0 56
michael@0 57 loader.unload();
michael@0 58
michael@0 59 // Fire a windows event and check that this unloaded instance is inactive
michael@0 60 windows.open({
michael@0 61 url: "data:text/html;charset=utf-8,foo",
michael@0 62 onOpen: function(window) {
michael@0 63 setTimeout(function () {
michael@0 64 assert.ok(!called, "Unloaded windows instance is destroyed and inactive");
michael@0 65
michael@0 66 window.close(done);
michael@0 67 });
michael@0 68 }
michael@0 69 });
michael@0 70 };
michael@0 71
michael@0 72 exports.testWindowTabsObject = function(assert, done) {
michael@0 73 let window, count = 0;
michael@0 74 function runTest() {
michael@0 75 if (++count != 2)
michael@0 76 return;
michael@0 77
michael@0 78 assert.equal(window.tabs.length, 1, "Only 1 tab open");
michael@0 79 assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
michael@0 80
michael@0 81 window.tabs.open({
michael@0 82 url: "data:text/html;charset=utf-8,<title>tab 2</title>",
michael@0 83 inBackground: true,
michael@0 84 onReady: function onReady(newTab) {
michael@0 85 assert.equal(window.tabs.length, 2, "New tab open");
michael@0 86 assert.equal(newTab.title, "tab 2", "Correct new tab title");
michael@0 87 assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
michael@0 88
michael@0 89 let i = 1;
michael@0 90 for (let tab of window.tabs)
michael@0 91 assert.equal(tab.title, "tab " + i++, "Correct title");
michael@0 92
michael@0 93 window.close();
michael@0 94 }
michael@0 95 });
michael@0 96 }
michael@0 97
michael@0 98 tabs.once("ready", runTest);
michael@0 99
michael@0 100 browserWindows.open({
michael@0 101 url: "data:text/html;charset=utf-8,<title>tab 1</title>",
michael@0 102 onActivate: function onActivate(win) {
michael@0 103 window = win;
michael@0 104 runTest();
michael@0 105 },
michael@0 106 onClose: function onClose(window) {
michael@0 107 assert.equal(window.tabs.length, 0, "No more tabs on closed window");
michael@0 108 done();
michael@0 109 }
michael@0 110 });
michael@0 111 };
michael@0 112
michael@0 113 exports.testOnOpenOnCloseListeners = function(assert, done) {
michael@0 114 let windows = browserWindows;
michael@0 115
michael@0 116 assert.equal(browserWindows.length, 1, "Only one window open");
michael@0 117
michael@0 118 let received = {
michael@0 119 listener1: false,
michael@0 120 listener2: false,
michael@0 121 listener3: false,
michael@0 122 listener4: false
michael@0 123 }
michael@0 124
michael@0 125 function listener1() {
michael@0 126 assert.equal(this, windows, "The 'this' object is the windows object.");
michael@0 127
michael@0 128 if (received.listener1)
michael@0 129 assert.fail("Event received twice");
michael@0 130 received.listener1 = true;
michael@0 131 }
michael@0 132
michael@0 133 function listener2() {
michael@0 134 if (received.listener2)
michael@0 135 assert.fail("Event received twice");
michael@0 136 received.listener2 = true;
michael@0 137 }
michael@0 138
michael@0 139 function listener3() {
michael@0 140 assert.equal(this, windows, "The 'this' object is the windows object.");
michael@0 141 if (received.listener3)
michael@0 142 assert.fail("Event received twice");
michael@0 143 received.listener3 = true;
michael@0 144 }
michael@0 145
michael@0 146 function listener4() {
michael@0 147 if (received.listener4)
michael@0 148 assert.fail("Event received twice");
michael@0 149 received.listener4 = true;
michael@0 150 }
michael@0 151
michael@0 152 windows.on('open', listener1);
michael@0 153 windows.on('open', listener2);
michael@0 154 windows.on('close', listener3);
michael@0 155 windows.on('close', listener4);
michael@0 156
michael@0 157 windows.open({
michael@0 158 url: "data:text/html;charset=utf-8,foo",
michael@0 159 onOpen: function(window) {
michael@0 160 window.close(function() {
michael@0 161 assert.ok(received.listener1, "onOpen handler called");
michael@0 162 assert.ok(received.listener2, "onOpen handler called");
michael@0 163 assert.ok(received.listener3, "onClose handler called");
michael@0 164 assert.ok(received.listener4, "onClose handler called");
michael@0 165
michael@0 166 windows.removeListener('open', listener1);
michael@0 167 windows.removeListener('open', listener2);
michael@0 168 windows.removeListener('close', listener3);
michael@0 169 windows.removeListener('close', listener4);
michael@0 170
michael@0 171 done();
michael@0 172 });
michael@0 173 }
michael@0 174 });
michael@0 175 };
michael@0 176
michael@0 177 exports.testActiveWindow = function(assert, done) {
michael@0 178 let windows = browserWindows;
michael@0 179
michael@0 180 // API window objects
michael@0 181 let window2, window3;
michael@0 182
michael@0 183 // Raw window objects
michael@0 184 let rawWindow2, rawWindow3;
michael@0 185
michael@0 186 let testSteps = [
michael@0 187 function() {
michael@0 188 assert.equal(windows.length, 3, "Correct number of browser windows");
michael@0 189
michael@0 190 let count = 0;
michael@0 191 for (let window in windows)
michael@0 192 count++;
michael@0 193 assert.equal(count, 3, "Correct number of windows returned by iterator");
michael@0 194
michael@0 195 assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3");
michael@0 196
michael@0 197 continueAfterFocus(rawWindow2);
michael@0 198 rawWindow2.focus();
michael@0 199 },
michael@0 200 function() {
michael@0 201 assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2");
michael@0 202
michael@0 203 continueAfterFocus(rawWindow2);
michael@0 204 window2.activate();
michael@0 205 },
michael@0 206 function() {
michael@0 207 assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2");
michael@0 208
michael@0 209 continueAfterFocus(rawWindow3);
michael@0 210 window3.activate();
michael@0 211 },
michael@0 212 function() {
michael@0 213 assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3");
michael@0 214 finishTest();
michael@0 215 }
michael@0 216 ];
michael@0 217
michael@0 218 let newWindow = null;
michael@0 219 let tracker = new WindowTracker({
michael@0 220 onTrack: function(window) {
michael@0 221 newWindow = window;
michael@0 222 }
michael@0 223 });
michael@0 224
michael@0 225 windows.open({
michael@0 226 url: "data:text/html;charset=utf-8,<title>window 2</title>",
michael@0 227 onOpen: function(window) {
michael@0 228 assert.pass('window 2 open');
michael@0 229
michael@0 230 window.tabs.activeTab.on('ready', function() {
michael@0 231 assert.pass('window 2 tab activated');
michael@0 232
michael@0 233 window2 = window;
michael@0 234 assert.ok(newWindow, "A new window was opened");
michael@0 235 rawWindow2 = newWindow;
michael@0 236 newWindow = null;
michael@0 237
michael@0 238 assert.equal(rawWindow2.content.document.title, "window 2", "Got correct raw window 2");
michael@0 239 assert.equal(rawWindow2.document.title, window2.title, "Saw correct title on window 2");
michael@0 240
michael@0 241 windows.open({
michael@0 242 url: "data:text/html;charset=utf-8,<title>window 3</title>",
michael@0 243 onOpen: function(window) {
michael@0 244 assert.pass('window 3 open');
michael@0 245
michael@0 246 window.tabs.activeTab.on('ready', function onReady() {
michael@0 247 assert.pass('window 3 tab activated');
michael@0 248
michael@0 249 window3 = window;
michael@0 250 assert.ok(newWindow, "A new window was opened");
michael@0 251 rawWindow3 = newWindow;
michael@0 252 tracker.unload();
michael@0 253
michael@0 254 assert.equal(rawWindow3.content.document.title, "window 3", "Got correct raw window 3");
michael@0 255 assert.equal(rawWindow3.document.title, window3.title, "Saw correct title on window 3");
michael@0 256
michael@0 257 continueAfterFocus(rawWindow3);
michael@0 258 rawWindow3.focus();
michael@0 259 });
michael@0 260 }
michael@0 261 });
michael@0 262 });
michael@0 263 }
michael@0 264 });
michael@0 265
michael@0 266 function nextStep() {
michael@0 267 if (testSteps.length) {
michael@0 268 setTimeout(testSteps.shift())
michael@0 269 }
michael@0 270 }
michael@0 271
michael@0 272 let continueAfterFocus = function(w) onFocus(w).then(nextStep);
michael@0 273
michael@0 274 function finishTest() {
michael@0 275 // close unactive window first to avoid unnecessary focus changing
michael@0 276 window2.close(function() {
michael@0 277 window3.close(function() {
michael@0 278 assert.equal(rawWindow2.closed, true, 'window 2 is closed');
michael@0 279 assert.equal(rawWindow3.closed, true, 'window 3 is closed');
michael@0 280
michael@0 281 done();
michael@0 282 });
michael@0 283 });
michael@0 284 }
michael@0 285 };
michael@0 286
michael@0 287 exports.testTrackWindows = function(assert, done) {
michael@0 288 let windows = [];
michael@0 289 let actions = [];
michael@0 290
michael@0 291 let expects = [
michael@0 292 "activate 0", "global activate 0", "deactivate 0", "global deactivate 0",
michael@0 293 "activate 1", "global activate 1", "deactivate 1", "global deactivate 1",
michael@0 294 "activate 2", "global activate 2"
michael@0 295 ];
michael@0 296
michael@0 297 function windowsActivation(window) {
michael@0 298 let index = windows.indexOf(window);
michael@0 299 // only concerned with windows opened for this test
michael@0 300 if (index < 0)
michael@0 301 return;
michael@0 302
michael@0 303 assert.equal(actions.join(), expects.slice(0, index*4 + 1).join(), expects[index*4 + 1]);
michael@0 304 actions.push("global activate " + index)
michael@0 305 }
michael@0 306
michael@0 307 function windowsDeactivation(window) {
michael@0 308 let index = windows.indexOf(window);
michael@0 309 // only concerned with windows opened for this test
michael@0 310 if (index < 0)
michael@0 311 return;
michael@0 312
michael@0 313 assert.equal(actions.join(), expects.slice(0, index*4 + 3).join(), expects[index*4 + 3]);
michael@0 314 actions.push("global deactivate " + index)
michael@0 315 }
michael@0 316
michael@0 317 // listen to global activate events
michael@0 318 browserWindows.on("activate", windowsActivation);
michael@0 319
michael@0 320 // listen to global deactivate events
michael@0 321 browserWindows.on("deactivate", windowsDeactivation);
michael@0 322
michael@0 323
michael@0 324 function openWindow() {
michael@0 325 windows.push(browserWindows.open({
michael@0 326 url: "data:text/html;charset=utf-8,<i>testTrackWindows</i>",
michael@0 327 onActivate: function(window) {
michael@0 328 let index = windows.indexOf(window);
michael@0 329
michael@0 330 // Guard against windows that have already been removed.
michael@0 331 // See bug 874502 comment 32.
michael@0 332 if (index == -1)
michael@0 333 return;
michael@0 334
michael@0 335 assert.equal(actions.join(),
michael@0 336 expects.slice(0, index*4).join(),
michael@0 337 "expecting " + expects[index*4]);
michael@0 338 actions.push("activate " + index);
michael@0 339
michael@0 340 if (windows.length < 3) {
michael@0 341 openWindow()
michael@0 342 }
michael@0 343 else {
michael@0 344 (function closeWindows(windows) {
michael@0 345 if (!windows.length) {
michael@0 346 browserWindows.removeListener("activate", windowsActivation);
michael@0 347 browserWindows.removeListener("deactivate", windowsDeactivation);
michael@0 348 return done();
michael@0 349 }
michael@0 350
michael@0 351 return windows.pop().close(function() {
michael@0 352 assert.pass('window was closed');
michael@0 353 closeWindows(windows);
michael@0 354 });
michael@0 355 })(windows)
michael@0 356 }
michael@0 357 },
michael@0 358 onDeactivate: function(window) {
michael@0 359 let index = windows.indexOf(window);
michael@0 360
michael@0 361 // Guard against windows that have already been removed.
michael@0 362 // See bug 874502 comment 32.
michael@0 363 if (index == -1)
michael@0 364 return;
michael@0 365
michael@0 366 assert.equal(actions.join(),
michael@0 367 expects.slice(0, index*4 + 2).join(),
michael@0 368 "expecting " + expects[index*4 + 2]);
michael@0 369 actions.push("deactivate " + index)
michael@0 370 }
michael@0 371 }));
michael@0 372 }
michael@0 373 openWindow();
michael@0 374 }
michael@0 375
michael@0 376 // test that it is not possible to open a private window by default
michael@0 377 exports.testWindowOpenPrivateDefault = function(assert, done) {
michael@0 378 browserWindows.open({
michael@0 379 url: 'about:mozilla',
michael@0 380 isPrivate: true,
michael@0 381 onOpen: function(window) {
michael@0 382 let tab = window.tabs[0];
michael@0 383
michael@0 384 tab.once('ready', function() {
michael@0 385 assert.equal(tab.url, 'about:mozilla', 'opened correct tab');
michael@0 386 assert.equal(isPrivate(tab), false, 'tab is not private');
michael@0 387
michael@0 388 window.close(done);
michael@0 389 });
michael@0 390 }
michael@0 391 });
michael@0 392 }
michael@0 393
michael@0 394 // test that it is not possible to find a private window in
michael@0 395 // windows module's iterator
michael@0 396 exports.testWindowIteratorPrivateDefault = function(assert, done) {
michael@0 397 assert.equal(browserWindows.length, 1, 'only one window open');
michael@0 398
michael@0 399 open('chrome://browser/content/browser.xul', {
michael@0 400 features: {
michael@0 401 private: true,
michael@0 402 chrome: true
michael@0 403 }
michael@0 404 }).then(focus).then(function(window) {
michael@0 405 // test that there is a private window opened
michael@0 406 assert.equal(isPrivate(window), isWindowPBSupported, 'there is a private window open');
michael@0 407 assert.strictEqual(window, winUtils.activeWindow);
michael@0 408 assert.strictEqual(window, getMostRecentWindow());
michael@0 409
michael@0 410 assert.ok(!isPrivate(browserWindows.activeWindow));
michael@0 411
michael@0 412 assert.equal(browserWindows.length, 1, 'only one window in browserWindows');
michael@0 413 assert.equal(windows().length, 1, 'only one window in windows()');
michael@0 414
michael@0 415 assert.equal(windows(null, { includePrivate: true }).length, 2);
michael@0 416
michael@0 417 // test that all windows in iterator are not private
michael@0 418 for (let window of browserWindows)
michael@0 419 assert.ok(!isPrivate(window), 'no window in browserWindows is private');
michael@0 420
michael@0 421 close(window).then(done);
michael@0 422 });
michael@0 423 };
michael@0 424
michael@0 425 exports["test getView(window)"] = function(assert, done) {
michael@0 426 browserWindows.once("open", window => {
michael@0 427 const view = viewFor(window);
michael@0 428
michael@0 429 assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
michael@0 430 assert.ok(isBrowser(view), "view is a browser window");
michael@0 431 assert.equal(getWindowTitle(view), window.title,
michael@0 432 "window has a right title");
michael@0 433
michael@0 434 window.close();
michael@0 435 // Defer handler cause window is destroyed after event is dispatched.
michael@0 436 browserWindows.once("close", defer(_ => {
michael@0 437 assert.equal(viewFor(window), null, "window view is gone");
michael@0 438 done();
michael@0 439 }));
michael@0 440 });
michael@0 441
michael@0 442 browserWindows.open({ url: "data:text/html,<title>yo</title>" });
michael@0 443 };
michael@0 444
michael@0 445 require('sdk/test').run(exports);

mercurial