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);