/* 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/. */
const {Cc, Ci} = require("chrome");
const { setTimeout } = require("timer");
const { Loader } = require('./helpers');
const wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
let browserWindows;
function getTestRunnerWindow() wm.getMostRecentWindow("test:runner")
exports.testOpenAndCloseWindow = function(test) {
test.waitUntilDone();
test.assertEqual(browserWindows.length, 1, "Only one window open");
browserWindows.open({
url: "data:text/html,
windows API test",
onOpen: function(window) {
test.assertEqual(this, browserWindows,
"The 'this' object is the windows object.");
test.assertEqual(window.tabs.length, 1, "Only one tab open");
test.assertEqual(browserWindows.length, 2, "Two windows open");
window.tabs.activeTab.on('ready', function onReady(tab) {
tab.removeListener('ready', onReady);
test.assert(window.title.indexOf("windows API test") != -1,
"URL correctly loaded");
window.close();
});
},
onClose: function(window) {
test.assertEqual(window.tabs.length, 0, "Tabs were cleared");
test.assertEqual(browserWindows.length, 1, "Only one window open");
test.done();
}
});
};
exports.testAutomaticDestroy = function(test) {
test.waitUntilDone();
let windows = browserWindows;
// Create a second windows instance that we will unload
let called = false;
let loader = Loader(module);
let windows2 = loader.require("windows").browserWindows;
windows2.on("open", function() {
called = true;
});
loader.unload();
// Fire a windows event and check that this unloaded instance is inactive
windows.open({
url: "data:text/html,foo",
onOpen: function(window) {
setTimeout(function () {
test.assert(!called,
"Unloaded windows instance is destroyed and inactive");
window.close(function () {
test.done();
});
});
}
});
};
exports.testOnOpenOnCloseListeners = function(test) {
test.waitUntilDone();
let windows = browserWindows;
test.assertEqual(browserWindows.length, 1, "Only one window open");
let received = {
listener1: false,
listener2: false,
listener3: false,
listener4: false
}
function listener1() {
test.assertEqual(this, windows, "The 'this' object is the windows object.");
if (received.listener1)
test.fail("Event received twice");
received.listener1 = true;
}
function listener2() {
if (received.listener2)
test.fail("Event received twice");
received.listener2 = true;
}
function listener3() {
test.assertEqual(this, windows, "The 'this' object is the windows object.");
if (received.listener3)
test.fail("Event received twice");
received.listener3 = true;
}
function listener4() {
if (received.listener4)
test.fail("Event received twice");
received.listener4 = true;
}
windows.on('open', listener1);
windows.on('open', listener2);
windows.on('close', listener3);
windows.on('close', listener4);
function verify() {
test.assert(received.listener1, "onOpen handler called");
test.assert(received.listener2, "onOpen handler called");
test.assert(received.listener3, "onClose handler called");
test.assert(received.listener4, "onClose handler called");
windows.removeListener('open', listener1);
windows.removeListener('open', listener2);
windows.removeListener('close', listener3);
windows.removeListener('close', listener4);
test.done();
}
windows.open({
url: "data:text/html,foo",
onOpen: function(window) {
window.close(verify);
}
});
};
exports.testWindowTabsObject = function(test) {
test.waitUntilDone();
browserWindows.open({
url: "data:text/html,tab 1",
onOpen: function onOpen(window) {
test.assertEqual(window.tabs.length, 1, "Only 1 tab open");
window.tabs.open({
url: "data:text/html,tab 2",
inBackground: true,
onReady: function onReady(newTab) {
test.assertEqual(window.tabs.length, 2, "New tab open");
test.assertEqual(newTab.title, "tab 2", "Correct new tab title");
test.assertEqual(window.tabs.activeTab.title, "tab 1", "Correct active tab");
let i = 1;
for each (let tab in window.tabs)
test.assertEqual(tab.title, "tab " + i++, "Correct title");
window.close();
}
});
},
onClose: function onClose(window) {
test.assertEqual(window.tabs.length, 0, "No more tabs on closed window");
test.done();
}
});
};
exports.testActiveWindow = function(test) {
const xulApp = require("xul-app");
if (xulApp.versionInRange(xulApp.platformVersion, "1.9.2", "1.9.2.*")) {
test.pass("This test is disabled on 3.6. For more information, see bug 598525");
return;
}
let windows = browserWindows;
// API window objects
let window2, window3;
// Raw window objects
let nonBrowserWindow = getTestRunnerWindow(), rawWindow2, rawWindow3;
test.waitUntilDone();
let testSteps = [
function() {
test.assertEqual(windows.length, 3, "Correct number of browser windows");
let count = 0;
for (let window in windows)
count++;
test.assertEqual(count, 3, "Correct number of windows returned by iterator");
rawWindow2.focus();
continueAfterFocus(rawWindow2);
},
function() {
nonBrowserWindow.focus();
continueAfterFocus(nonBrowserWindow);
},
function() {
/**
* Bug 614079: This test fails intermittently on some specific linux
* environnements, without being able to reproduce it in same
* distribution with same window manager.
* Disable it until being able to reproduce it easily.
// On linux, focus is not consistent, so we can't be sure
// what window will be on top.
// Here when we focus "non-browser" window,
// Any Browser window may be selected as "active".
test.assert(windows.activeWindow == window2 || windows.activeWindow == window3,
"Non-browser windows aren't handled by this module");
*/
window2.activate();
continueAfterFocus(rawWindow2);
},
function() {
test.assertEqual(windows.activeWindow.title, window2.title, "Correct active window - 2");
window3.activate();
continueAfterFocus(rawWindow3);
},
function() {
test.assertEqual(windows.activeWindow.title, window3.title, "Correct active window - 3");
nonBrowserWindow.focus();
finishTest();
}
];
windows.open({
url: "data:text/html,window 2",
onOpen: function(window) {
window2 = window;
rawWindow2 = wm.getMostRecentWindow("navigator:browser");
windows.open({
url: "data:text/html,window 3",
onOpen: function(window) {
window.tabs.activeTab.on('ready', function onReady() {
window3 = window;
rawWindow3 = wm.getMostRecentWindow("navigator:browser");
nextStep()
});
}
});
}
});
function nextStep() {
if (testSteps.length > 0)
testSteps.shift()();
}
function continueAfterFocus(targetWindow) {
// Based on SimpleTest.waitForFocus
var fm = Cc["@mozilla.org/focus-manager;1"].
getService(Ci.nsIFocusManager);
var childTargetWindow = {};
fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
childTargetWindow = childTargetWindow.value;
var focusedChildWindow = {};
if (fm.activeWindow) {
fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
focusedChildWindow = focusedChildWindow.value;
}
var focused = (focusedChildWindow == childTargetWindow);
if (focused) {
nextStep();
} else {
childTargetWindow.addEventListener("focus", function focusListener() {
childTargetWindow.removeEventListener("focus", focusListener, true);
nextStep();
}, true);
}
}
function finishTest() {
window3.close(function() {
window2.close(function() {
test.done();
});
});
}
};
// If the module doesn't support the app we're being run in, require() will
// throw. In that case, remove all tests above from exports, and add one dummy
// test that passes.
try {
browserWindows = require("windows").browserWindows;
}
catch (err) {
// This bug should be mentioned in the error message.
let bug = "https://bugzilla.mozilla.org/show_bug.cgi?id=571449";
if (err.message.indexOf(bug) < 0)
throw err;
for (let [prop, val] in Iterator(exports)) {
if (/^test/.test(prop) && typeof(val) === "function")
delete exports[prop];
}
exports.testAppNotSupported = function (test) {
test.pass("the windows module does not support this application.");
};
}