michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0: 'use strict';
michael@0:
michael@0: const { Cc, Ci } = require('chrome');
michael@0: const { setTimeout } = require('sdk/timers');
michael@0: const { Loader } = require('sdk/test/loader');
michael@0: const { onFocus, getMostRecentWindow, windows, isBrowser, getWindowTitle } = require('sdk/window/utils');
michael@0: const { open, close, focus } = require('sdk/window/helpers');
michael@0: const { browserWindows } = require("sdk/windows");
michael@0: const tabs = require("sdk/tabs");
michael@0: const winUtils = require("sdk/deprecated/window-utils");
michael@0: const { WindowTracker } = winUtils;
michael@0: const { isPrivate } = require('sdk/private-browsing');
michael@0: const { isWindowPBSupported } = require('sdk/private-browsing/utils');
michael@0: const { viewFor } = require("sdk/view/core");
michael@0: const { defer } = require("sdk/lang/functional");
michael@0:
michael@0: // TEST: open & close window
michael@0: exports.testOpenAndCloseWindow = function(assert, done) {
michael@0: assert.equal(browserWindows.length, 1, "Only one window open");
michael@0: let title = 'testOpenAndCloseWindow';
michael@0:
michael@0: browserWindows.open({
michael@0: url: "data:text/html;charset=utf-8,
" + title + "",
michael@0: onOpen: function(window) {
michael@0: assert.equal(this, browserWindows, "The 'this' object is the windows object.");
michael@0: assert.equal(window.tabs.length, 1, "Only one tab open");
michael@0: assert.equal(browserWindows.length, 2, "Two windows open");
michael@0:
michael@0: window.tabs.activeTab.once('ready', function onReady(tab) {
michael@0: assert.pass(RegExp(title).test(window.title), "URL correctly loaded");
michael@0: window.close();
michael@0: });
michael@0: },
michael@0: onClose: function(window) {
michael@0: assert.equal(window.tabs.length, 0, "Tabs were cleared");
michael@0: assert.equal(browserWindows.length, 1, "Only one window open");
michael@0: done();
michael@0: }
michael@0: });
michael@0: };
michael@0:
michael@0: exports.testAutomaticDestroy = function(assert, done) {
michael@0: let windows = browserWindows;
michael@0:
michael@0: // Create a second windows instance that we will unload
michael@0: let called = false;
michael@0: let loader = Loader(module);
michael@0: let windows2 = loader.require("sdk/windows").browserWindows;
michael@0:
michael@0: windows2.on("open", function() {
michael@0: called = true;
michael@0: });
michael@0:
michael@0: loader.unload();
michael@0:
michael@0: // Fire a windows event and check that this unloaded instance is inactive
michael@0: windows.open({
michael@0: url: "data:text/html;charset=utf-8,foo",
michael@0: onOpen: function(window) {
michael@0: setTimeout(function () {
michael@0: assert.ok(!called, "Unloaded windows instance is destroyed and inactive");
michael@0:
michael@0: window.close(done);
michael@0: });
michael@0: }
michael@0: });
michael@0: };
michael@0:
michael@0: exports.testWindowTabsObject = function(assert, done) {
michael@0: let window, count = 0;
michael@0: function runTest() {
michael@0: if (++count != 2)
michael@0: return;
michael@0:
michael@0: assert.equal(window.tabs.length, 1, "Only 1 tab open");
michael@0: assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
michael@0:
michael@0: window.tabs.open({
michael@0: url: "data:text/html;charset=utf-8,tab 2",
michael@0: inBackground: true,
michael@0: onReady: function onReady(newTab) {
michael@0: assert.equal(window.tabs.length, 2, "New tab open");
michael@0: assert.equal(newTab.title, "tab 2", "Correct new tab title");
michael@0: assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
michael@0:
michael@0: let i = 1;
michael@0: for (let tab of window.tabs)
michael@0: assert.equal(tab.title, "tab " + i++, "Correct title");
michael@0:
michael@0: window.close();
michael@0: }
michael@0: });
michael@0: }
michael@0:
michael@0: tabs.once("ready", runTest);
michael@0:
michael@0: browserWindows.open({
michael@0: url: "data:text/html;charset=utf-8,tab 1",
michael@0: onActivate: function onActivate(win) {
michael@0: window = win;
michael@0: runTest();
michael@0: },
michael@0: onClose: function onClose(window) {
michael@0: assert.equal(window.tabs.length, 0, "No more tabs on closed window");
michael@0: done();
michael@0: }
michael@0: });
michael@0: };
michael@0:
michael@0: exports.testOnOpenOnCloseListeners = function(assert, done) {
michael@0: let windows = browserWindows;
michael@0:
michael@0: assert.equal(browserWindows.length, 1, "Only one window open");
michael@0:
michael@0: let received = {
michael@0: listener1: false,
michael@0: listener2: false,
michael@0: listener3: false,
michael@0: listener4: false
michael@0: }
michael@0:
michael@0: function listener1() {
michael@0: assert.equal(this, windows, "The 'this' object is the windows object.");
michael@0:
michael@0: if (received.listener1)
michael@0: assert.fail("Event received twice");
michael@0: received.listener1 = true;
michael@0: }
michael@0:
michael@0: function listener2() {
michael@0: if (received.listener2)
michael@0: assert.fail("Event received twice");
michael@0: received.listener2 = true;
michael@0: }
michael@0:
michael@0: function listener3() {
michael@0: assert.equal(this, windows, "The 'this' object is the windows object.");
michael@0: if (received.listener3)
michael@0: assert.fail("Event received twice");
michael@0: received.listener3 = true;
michael@0: }
michael@0:
michael@0: function listener4() {
michael@0: if (received.listener4)
michael@0: assert.fail("Event received twice");
michael@0: received.listener4 = true;
michael@0: }
michael@0:
michael@0: windows.on('open', listener1);
michael@0: windows.on('open', listener2);
michael@0: windows.on('close', listener3);
michael@0: windows.on('close', listener4);
michael@0:
michael@0: windows.open({
michael@0: url: "data:text/html;charset=utf-8,foo",
michael@0: onOpen: function(window) {
michael@0: window.close(function() {
michael@0: assert.ok(received.listener1, "onOpen handler called");
michael@0: assert.ok(received.listener2, "onOpen handler called");
michael@0: assert.ok(received.listener3, "onClose handler called");
michael@0: assert.ok(received.listener4, "onClose handler called");
michael@0:
michael@0: windows.removeListener('open', listener1);
michael@0: windows.removeListener('open', listener2);
michael@0: windows.removeListener('close', listener3);
michael@0: windows.removeListener('close', listener4);
michael@0:
michael@0: done();
michael@0: });
michael@0: }
michael@0: });
michael@0: };
michael@0:
michael@0: exports.testActiveWindow = function(assert, done) {
michael@0: let windows = browserWindows;
michael@0:
michael@0: // API window objects
michael@0: let window2, window3;
michael@0:
michael@0: // Raw window objects
michael@0: let rawWindow2, rawWindow3;
michael@0:
michael@0: let testSteps = [
michael@0: function() {
michael@0: assert.equal(windows.length, 3, "Correct number of browser windows");
michael@0:
michael@0: let count = 0;
michael@0: for (let window in windows)
michael@0: count++;
michael@0: assert.equal(count, 3, "Correct number of windows returned by iterator");
michael@0:
michael@0: assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3");
michael@0:
michael@0: continueAfterFocus(rawWindow2);
michael@0: rawWindow2.focus();
michael@0: },
michael@0: function() {
michael@0: assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2");
michael@0:
michael@0: continueAfterFocus(rawWindow2);
michael@0: window2.activate();
michael@0: },
michael@0: function() {
michael@0: assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2");
michael@0:
michael@0: continueAfterFocus(rawWindow3);
michael@0: window3.activate();
michael@0: },
michael@0: function() {
michael@0: assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3");
michael@0: finishTest();
michael@0: }
michael@0: ];
michael@0:
michael@0: let newWindow = null;
michael@0: let tracker = new WindowTracker({
michael@0: onTrack: function(window) {
michael@0: newWindow = window;
michael@0: }
michael@0: });
michael@0:
michael@0: windows.open({
michael@0: url: "data:text/html;charset=utf-8,window 2",
michael@0: onOpen: function(window) {
michael@0: assert.pass('window 2 open');
michael@0:
michael@0: window.tabs.activeTab.on('ready', function() {
michael@0: assert.pass('window 2 tab activated');
michael@0:
michael@0: window2 = window;
michael@0: assert.ok(newWindow, "A new window was opened");
michael@0: rawWindow2 = newWindow;
michael@0: newWindow = null;
michael@0:
michael@0: assert.equal(rawWindow2.content.document.title, "window 2", "Got correct raw window 2");
michael@0: assert.equal(rawWindow2.document.title, window2.title, "Saw correct title on window 2");
michael@0:
michael@0: windows.open({
michael@0: url: "data:text/html;charset=utf-8,window 3",
michael@0: onOpen: function(window) {
michael@0: assert.pass('window 3 open');
michael@0:
michael@0: window.tabs.activeTab.on('ready', function onReady() {
michael@0: assert.pass('window 3 tab activated');
michael@0:
michael@0: window3 = window;
michael@0: assert.ok(newWindow, "A new window was opened");
michael@0: rawWindow3 = newWindow;
michael@0: tracker.unload();
michael@0:
michael@0: assert.equal(rawWindow3.content.document.title, "window 3", "Got correct raw window 3");
michael@0: assert.equal(rawWindow3.document.title, window3.title, "Saw correct title on window 3");
michael@0:
michael@0: continueAfterFocus(rawWindow3);
michael@0: rawWindow3.focus();
michael@0: });
michael@0: }
michael@0: });
michael@0: });
michael@0: }
michael@0: });
michael@0:
michael@0: function nextStep() {
michael@0: if (testSteps.length) {
michael@0: setTimeout(testSteps.shift())
michael@0: }
michael@0: }
michael@0:
michael@0: let continueAfterFocus = function(w) onFocus(w).then(nextStep);
michael@0:
michael@0: function finishTest() {
michael@0: // close unactive window first to avoid unnecessary focus changing
michael@0: window2.close(function() {
michael@0: window3.close(function() {
michael@0: assert.equal(rawWindow2.closed, true, 'window 2 is closed');
michael@0: assert.equal(rawWindow3.closed, true, 'window 3 is closed');
michael@0:
michael@0: done();
michael@0: });
michael@0: });
michael@0: }
michael@0: };
michael@0:
michael@0: exports.testTrackWindows = function(assert, done) {
michael@0: let windows = [];
michael@0: let actions = [];
michael@0:
michael@0: let expects = [
michael@0: "activate 0", "global activate 0", "deactivate 0", "global deactivate 0",
michael@0: "activate 1", "global activate 1", "deactivate 1", "global deactivate 1",
michael@0: "activate 2", "global activate 2"
michael@0: ];
michael@0:
michael@0: function windowsActivation(window) {
michael@0: let index = windows.indexOf(window);
michael@0: // only concerned with windows opened for this test
michael@0: if (index < 0)
michael@0: return;
michael@0:
michael@0: assert.equal(actions.join(), expects.slice(0, index*4 + 1).join(), expects[index*4 + 1]);
michael@0: actions.push("global activate " + index)
michael@0: }
michael@0:
michael@0: function windowsDeactivation(window) {
michael@0: let index = windows.indexOf(window);
michael@0: // only concerned with windows opened for this test
michael@0: if (index < 0)
michael@0: return;
michael@0:
michael@0: assert.equal(actions.join(), expects.slice(0, index*4 + 3).join(), expects[index*4 + 3]);
michael@0: actions.push("global deactivate " + index)
michael@0: }
michael@0:
michael@0: // listen to global activate events
michael@0: browserWindows.on("activate", windowsActivation);
michael@0:
michael@0: // listen to global deactivate events
michael@0: browserWindows.on("deactivate", windowsDeactivation);
michael@0:
michael@0:
michael@0: function openWindow() {
michael@0: windows.push(browserWindows.open({
michael@0: url: "data:text/html;charset=utf-8,testTrackWindows",
michael@0: onActivate: function(window) {
michael@0: let index = windows.indexOf(window);
michael@0:
michael@0: // Guard against windows that have already been removed.
michael@0: // See bug 874502 comment 32.
michael@0: if (index == -1)
michael@0: return;
michael@0:
michael@0: assert.equal(actions.join(),
michael@0: expects.slice(0, index*4).join(),
michael@0: "expecting " + expects[index*4]);
michael@0: actions.push("activate " + index);
michael@0:
michael@0: if (windows.length < 3) {
michael@0: openWindow()
michael@0: }
michael@0: else {
michael@0: (function closeWindows(windows) {
michael@0: if (!windows.length) {
michael@0: browserWindows.removeListener("activate", windowsActivation);
michael@0: browserWindows.removeListener("deactivate", windowsDeactivation);
michael@0: return done();
michael@0: }
michael@0:
michael@0: return windows.pop().close(function() {
michael@0: assert.pass('window was closed');
michael@0: closeWindows(windows);
michael@0: });
michael@0: })(windows)
michael@0: }
michael@0: },
michael@0: onDeactivate: function(window) {
michael@0: let index = windows.indexOf(window);
michael@0:
michael@0: // Guard against windows that have already been removed.
michael@0: // See bug 874502 comment 32.
michael@0: if (index == -1)
michael@0: return;
michael@0:
michael@0: assert.equal(actions.join(),
michael@0: expects.slice(0, index*4 + 2).join(),
michael@0: "expecting " + expects[index*4 + 2]);
michael@0: actions.push("deactivate " + index)
michael@0: }
michael@0: }));
michael@0: }
michael@0: openWindow();
michael@0: }
michael@0:
michael@0: // test that it is not possible to open a private window by default
michael@0: exports.testWindowOpenPrivateDefault = function(assert, done) {
michael@0: browserWindows.open({
michael@0: url: 'about:mozilla',
michael@0: isPrivate: true,
michael@0: onOpen: function(window) {
michael@0: let tab = window.tabs[0];
michael@0:
michael@0: tab.once('ready', function() {
michael@0: assert.equal(tab.url, 'about:mozilla', 'opened correct tab');
michael@0: assert.equal(isPrivate(tab), false, 'tab is not private');
michael@0:
michael@0: window.close(done);
michael@0: });
michael@0: }
michael@0: });
michael@0: }
michael@0:
michael@0: // test that it is not possible to find a private window in
michael@0: // windows module's iterator
michael@0: exports.testWindowIteratorPrivateDefault = function(assert, done) {
michael@0: assert.equal(browserWindows.length, 1, 'only one window open');
michael@0:
michael@0: open('chrome://browser/content/browser.xul', {
michael@0: features: {
michael@0: private: true,
michael@0: chrome: true
michael@0: }
michael@0: }).then(focus).then(function(window) {
michael@0: // test that there is a private window opened
michael@0: assert.equal(isPrivate(window), isWindowPBSupported, 'there is a private window open');
michael@0: assert.strictEqual(window, winUtils.activeWindow);
michael@0: assert.strictEqual(window, getMostRecentWindow());
michael@0:
michael@0: assert.ok(!isPrivate(browserWindows.activeWindow));
michael@0:
michael@0: assert.equal(browserWindows.length, 1, 'only one window in browserWindows');
michael@0: assert.equal(windows().length, 1, 'only one window in windows()');
michael@0:
michael@0: assert.equal(windows(null, { includePrivate: true }).length, 2);
michael@0:
michael@0: // test that all windows in iterator are not private
michael@0: for (let window of browserWindows)
michael@0: assert.ok(!isPrivate(window), 'no window in browserWindows is private');
michael@0:
michael@0: close(window).then(done);
michael@0: });
michael@0: };
michael@0:
michael@0: exports["test getView(window)"] = function(assert, done) {
michael@0: browserWindows.once("open", window => {
michael@0: const view = viewFor(window);
michael@0:
michael@0: assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
michael@0: assert.ok(isBrowser(view), "view is a browser window");
michael@0: assert.equal(getWindowTitle(view), window.title,
michael@0: "window has a right title");
michael@0:
michael@0: window.close();
michael@0: // Defer handler cause window is destroyed after event is dispatched.
michael@0: browserWindows.once("close", defer(_ => {
michael@0: assert.equal(viewFor(window), null, "window view is gone");
michael@0: done();
michael@0: }));
michael@0: });
michael@0:
michael@0: browserWindows.open({ url: "data:text/html,yo" });
michael@0: };
michael@0:
michael@0: require('sdk/test').run(exports);