1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/tabview/test/head.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,451 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 1.8 + 1.9 +// Some tests here assume that all restored tabs are loaded without waiting for 1.10 +// the user to bring them to the foreground. We ensure this by resetting the 1.11 +// related preference (see the "firefox.js" defaults file for details). 1.12 +Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", false); 1.13 +registerCleanupFunction(function () { 1.14 + Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand"); 1.15 +}); 1.16 + 1.17 +// ---------- 1.18 +function createEmptyGroupItem(contentWindow, width, height, padding, animate) { 1.19 + let pageBounds = contentWindow.Items.getPageBounds(); 1.20 + pageBounds.inset(padding, padding); 1.21 + 1.22 + let box = new contentWindow.Rect(pageBounds); 1.23 + box.width = width; 1.24 + box.height = height; 1.25 + 1.26 + let emptyGroupItem = 1.27 + new contentWindow.GroupItem([], { bounds: box, immediately: !animate }); 1.28 + 1.29 + return emptyGroupItem; 1.30 +} 1.31 + 1.32 +// ---------- 1.33 +function createGroupItemWithTabs(win, width, height, padding, urls, animate) { 1.34 + let contentWindow = win.TabView.getContentWindow(); 1.35 + let groupItemCount = contentWindow.GroupItems.groupItems.length; 1.36 + // create empty group item 1.37 + let groupItem = createEmptyGroupItem(contentWindow, width, height, padding, animate); 1.38 + ok(groupItem.isEmpty(), "This group is empty"); 1.39 + is(contentWindow.GroupItems.groupItems.length, ++groupItemCount, 1.40 + "The number of groups is increased by 1"); 1.41 + // add blank items 1.42 + contentWindow.UI.setActive(groupItem); 1.43 + let t = 0; 1.44 + urls.forEach( function(url) { 1.45 + let newItem = win.gBrowser.loadOneTab(url)._tabViewTabItem; 1.46 + ok(newItem.container, "Created element "+t+":"+newItem.container); 1.47 + ++t; 1.48 + }); 1.49 + // to set one of tabItem to be active since we load tabs into a group 1.50 + // in a non-standard flow. 1.51 + contentWindow.UI.setActive(groupItem); 1.52 + return groupItem; 1.53 +} 1.54 + 1.55 +// ---------- 1.56 +function createGroupItemWithBlankTabs(win, width, height, padding, numNewTabs, animate) { 1.57 + let urls = []; 1.58 + while(numNewTabs--) 1.59 + urls.push("about:blank"); 1.60 + return createGroupItemWithTabs(win, width, height, padding, urls, animate); 1.61 +} 1.62 + 1.63 +// ---------- 1.64 +function closeGroupItem(groupItem, callback) { 1.65 + if (callback) { 1.66 + groupItem.addSubscriber("close", function onClose() { 1.67 + groupItem.removeSubscriber("close", onClose); 1.68 + executeSoon(callback); 1.69 + }); 1.70 + } 1.71 + 1.72 + if (groupItem.getChildren().length) { 1.73 + groupItem.addSubscriber("groupHidden", function onHide() { 1.74 + groupItem.removeSubscriber("groupHidden", onHide); 1.75 + groupItem.closeHidden(); 1.76 + }); 1.77 + } 1.78 + 1.79 + groupItem.closeAll(); 1.80 +} 1.81 + 1.82 +// ---------- 1.83 +function afterAllTabItemsUpdated(callback, win) { 1.84 + win = win || window; 1.85 + let tabItems = win.document.getElementById("tab-view").contentWindow.TabItems; 1.86 + let counter = 0; 1.87 + 1.88 + for (let a = 0; a < win.gBrowser.tabs.length; a++) { 1.89 + let tabItem = win.gBrowser.tabs[a]._tabViewTabItem; 1.90 + if (tabItem) { 1.91 + let tab = win.gBrowser.tabs[a]; 1.92 + counter++; 1.93 + tabItem.addSubscriber("updated", function onUpdated() { 1.94 + tabItem.removeSubscriber("updated", onUpdated); 1.95 + if (--counter == 0) 1.96 + callback(); 1.97 + }); 1.98 + tabItems.update(tab); 1.99 + } 1.100 + } 1.101 + if (counter == 0) 1.102 + callback(); 1.103 +} 1.104 + 1.105 +// --------- 1.106 +function newWindowWithTabView(shownCallback, loadCallback, width, height) { 1.107 + let winWidth = width || 800; 1.108 + let winHeight = height || 800; 1.109 + let win = window.openDialog(getBrowserURL(), "_blank", 1.110 + "chrome,all,dialog=no,height=" + winHeight + 1.111 + ",width=" + winWidth, "about:blank"); 1.112 + 1.113 + whenWindowLoaded(win, function () { 1.114 + if (loadCallback) 1.115 + loadCallback(win); 1.116 + }); 1.117 + 1.118 + whenDelayedStartupFinished(win, function () { 1.119 + showTabView(function () shownCallback(win), win); 1.120 + }); 1.121 +} 1.122 + 1.123 +// ---------- 1.124 +function afterAllTabsLoaded(callback, win) { 1.125 + const TAB_STATE_NEEDS_RESTORE = 1; 1.126 + 1.127 + win = win || window; 1.128 + 1.129 + let stillToLoad = 0; 1.130 + let restoreHiddenTabs = Services.prefs.getBoolPref( 1.131 + "browser.sessionstore.restore_hidden_tabs"); 1.132 + 1.133 + function onLoad() { 1.134 + this.removeEventListener("load", onLoad, true); 1.135 + stillToLoad--; 1.136 + if (!stillToLoad) 1.137 + executeSoon(callback); 1.138 + } 1.139 + 1.140 + for (let a = 0; a < win.gBrowser.tabs.length; a++) { 1.141 + let tab = win.gBrowser.tabs[a]; 1.142 + let browser = tab.linkedBrowser; 1.143 + 1.144 + let isRestorable = !(tab.hidden && !restoreHiddenTabs && 1.145 + browser.__SS_restoreState && 1.146 + browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE); 1.147 + 1.148 + if (isRestorable && browser.webProgress.isLoadingDocument) { 1.149 + stillToLoad++; 1.150 + browser.addEventListener("load", onLoad, true); 1.151 + } 1.152 + } 1.153 + 1.154 + if (!stillToLoad) 1.155 + executeSoon(callback); 1.156 +} 1.157 + 1.158 +// ---------- 1.159 +function showTabView(callback, win) { 1.160 + win = win || window; 1.161 + 1.162 + if (win.TabView.isVisible()) { 1.163 + waitForFocus(callback, win); 1.164 + return; 1.165 + } 1.166 + 1.167 + whenTabViewIsShown(function () { 1.168 + waitForFocus(callback, win); 1.169 + }, win); 1.170 + 1.171 + win.TabView.show(); 1.172 +} 1.173 + 1.174 +// ---------- 1.175 +function hideTabView(callback, win) { 1.176 + win = win || window; 1.177 + 1.178 + if (!win.TabView.isVisible()) { 1.179 + if (callback) 1.180 + callback(); 1.181 + return; 1.182 + } 1.183 + 1.184 + if (callback) 1.185 + whenTabViewIsHidden(callback, win); 1.186 + 1.187 + win.TabView.hide(); 1.188 +} 1.189 + 1.190 +// ---------- 1.191 +function whenTabViewIsHidden(callback, win) { 1.192 + win = win || window; 1.193 + 1.194 + if (!win.TabView.isVisible()) { 1.195 + callback(); 1.196 + return; 1.197 + } 1.198 + 1.199 + win.addEventListener('tabviewhidden', function onHidden() { 1.200 + win.removeEventListener('tabviewhidden', onHidden, false); 1.201 + callback(); 1.202 + }, false); 1.203 +} 1.204 + 1.205 +// ---------- 1.206 +function whenTabViewIsShown(callback, win) { 1.207 + win = win || window; 1.208 + 1.209 + if (win.TabView.isVisible()) { 1.210 + callback(); 1.211 + return; 1.212 + } 1.213 + 1.214 + win.addEventListener('tabviewshown', function onShown() { 1.215 + win.removeEventListener('tabviewshown', onShown, false); 1.216 + callback(); 1.217 + }, false); 1.218 +} 1.219 + 1.220 +// ---------- 1.221 +function hideSearch(callback, win) { 1.222 + win = win || window; 1.223 + 1.224 + let contentWindow = win.TabView.getContentWindow(); 1.225 + if (!contentWindow.Search.isEnabled()) { 1.226 + if (callback) 1.227 + callback(); 1.228 + return; 1.229 + } 1.230 + 1.231 + if (callback) 1.232 + whenSearchIsDisabled(callback, win); 1.233 + 1.234 + contentWindow.Search.hide(); 1.235 +} 1.236 + 1.237 +// ---------- 1.238 +function whenSearchIsEnabled(callback, win) { 1.239 + win = win || window; 1.240 + 1.241 + let contentWindow = win.TabView.getContentWindow(); 1.242 + if (contentWindow.Search.isEnabled()) { 1.243 + callback(); 1.244 + return; 1.245 + } 1.246 + 1.247 + contentWindow.addEventListener("tabviewsearchenabled", function onSearchEnabled() { 1.248 + contentWindow.removeEventListener("tabviewsearchenabled", onSearchEnabled, false); 1.249 + callback(); 1.250 + }, false); 1.251 +} 1.252 + 1.253 +// ---------- 1.254 +function whenSearchIsDisabled(callback, win) { 1.255 + win = win || window; 1.256 + 1.257 + let contentWindow = win.TabView.getContentWindow(); 1.258 + if (!contentWindow.Search.isEnabled()) { 1.259 + callback(); 1.260 + return; 1.261 + } 1.262 + 1.263 + contentWindow.addEventListener("tabviewsearchdisabled", function onSearchDisabled() { 1.264 + contentWindow.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false); 1.265 + callback(); 1.266 + }, false); 1.267 +} 1.268 + 1.269 +// ---------- 1.270 +function hideGroupItem(groupItem, callback) { 1.271 + if (groupItem.hidden) { 1.272 + if (callback) 1.273 + callback(); 1.274 + return; 1.275 + } 1.276 + 1.277 + if (callback) { 1.278 + groupItem.addSubscriber("groupHidden", function onHide() { 1.279 + groupItem.removeSubscriber("groupHidden", onHide); 1.280 + callback(); 1.281 + }); 1.282 + } 1.283 + 1.284 + groupItem.closeAll(); 1.285 +} 1.286 + 1.287 +// ---------- 1.288 +function unhideGroupItem(groupItem, callback) { 1.289 + if (!groupItem.hidden) { 1.290 + if (callback) 1.291 + callback(); 1.292 + return; 1.293 + } 1.294 + 1.295 + if (callback) { 1.296 + groupItem.addSubscriber("groupShown", function onShown() { 1.297 + groupItem.removeSubscriber("groupShown", onShown); 1.298 + callback(); 1.299 + }); 1.300 + } 1.301 + 1.302 + groupItem._unhide(); 1.303 +} 1.304 + 1.305 +// ---------- 1.306 +function whenWindowLoaded(win, callback) { 1.307 + win.addEventListener("load", function onLoad() { 1.308 + win.removeEventListener("load", onLoad, false); 1.309 + executeSoon(callback); 1.310 + }, false); 1.311 +} 1.312 + 1.313 +// ---------- 1.314 +function whenWindowStateReady(win, callback) { 1.315 + win.addEventListener("SSWindowStateReady", function onReady() { 1.316 + win.removeEventListener("SSWindowStateReady", onReady, false); 1.317 + executeSoon(callback); 1.318 + }, false); 1.319 +} 1.320 + 1.321 +// ---------- 1.322 +function whenDelayedStartupFinished(win, callback) { 1.323 + let topic = "browser-delayed-startup-finished"; 1.324 + Services.obs.addObserver(function onStartup(aSubject) { 1.325 + if (win != aSubject) 1.326 + return; 1.327 + 1.328 + Services.obs.removeObserver(onStartup, topic); 1.329 + executeSoon(callback); 1.330 + }, topic, false); 1.331 +} 1.332 + 1.333 +// ---------- 1.334 +function newWindowWithState(state, callback) { 1.335 + const ss = Cc["@mozilla.org/browser/sessionstore;1"] 1.336 + .getService(Ci.nsISessionStore); 1.337 + 1.338 + let opts = "chrome,all,dialog=no,height=800,width=800"; 1.339 + let win = window.openDialog(getBrowserURL(), "_blank", opts, "about:blank"); 1.340 + 1.341 + let numConditions = 2; 1.342 + let check = function () { 1.343 + if (!--numConditions) 1.344 + callback(win); 1.345 + }; 1.346 + 1.347 + whenDelayedStartupFinished(win, function () { 1.348 + ss.setWindowState(win, JSON.stringify(state), true); 1.349 + win.close(); 1.350 + // Give it time to close 1.351 + executeSoon(function() { 1.352 + win = ss.undoCloseWindow(0); 1.353 + 1.354 + whenWindowLoaded(win, function () { 1.355 + afterAllTabsLoaded(check, win); 1.356 + }); 1.357 + 1.358 + whenDelayedStartupFinished(win, check); 1.359 + }); 1.360 + }); 1.361 +} 1.362 + 1.363 +// ---------- 1.364 +function restoreTab(callback, index, win) { 1.365 + win = win || window; 1.366 + 1.367 + let tab = win.undoCloseTab(index || 0); 1.368 + let tabItem = tab._tabViewTabItem; 1.369 + 1.370 + let finalize = function () { 1.371 + afterAllTabsLoaded(function () callback(tab), win); 1.372 + }; 1.373 + 1.374 + if (tabItem._reconnected) { 1.375 + finalize(); 1.376 + return; 1.377 + } 1.378 + 1.379 + tab._tabViewTabItem.addSubscriber("reconnected", function onReconnected() { 1.380 + tab._tabViewTabItem.removeSubscriber("reconnected", onReconnected); 1.381 + finalize(); 1.382 + }); 1.383 +} 1.384 + 1.385 +// ---------- 1.386 +function goToNextGroup(win) { 1.387 + win = win || window; 1.388 + 1.389 + let utils = 1.390 + win.QueryInterface(Ci.nsIInterfaceRequestor). 1.391 + getInterface(Ci.nsIDOMWindowUtils); 1.392 + 1.393 + const masks = Ci.nsIDOMNSEvent; 1.394 + let mval = 0; 1.395 + mval |= masks.CONTROL_MASK; 1.396 + 1.397 + utils.sendKeyEvent("keypress", 0, 96, mval); 1.398 +} 1.399 + 1.400 +// ---------- 1.401 +function whenAppTabIconAdded(groupItem, callback) { 1.402 + groupItem.addSubscriber("appTabIconAdded", function onAppTabIconAdded() { 1.403 + groupItem.removeSubscriber("appTabIconAdded", onAppTabIconAdded); 1.404 + executeSoon(callback); 1.405 + }); 1.406 +} 1.407 + 1.408 +/** 1.409 + * Chrome windows aren't closed synchronously. Provide a helper method to close 1.410 + * a window and wait until we received the "domwindowclosed" notification for it. 1.411 + */ 1.412 +function promiseWindowClosed(win) { 1.413 + let deferred = Promise.defer(); 1.414 + 1.415 + Services.obs.addObserver(function obs(subject, topic) { 1.416 + if (subject == win) { 1.417 + Services.obs.removeObserver(obs, topic); 1.418 + deferred.resolve(); 1.419 + } 1.420 + }, "domwindowclosed", false); 1.421 + 1.422 + win.close(); 1.423 + return deferred.promise; 1.424 +} 1.425 + 1.426 +// ---------- 1.427 +function waitForOnBeforeUnloadDialog(browser, callback) { 1.428 + browser.addEventListener("DOMWillOpenModalDialog", function onModalDialog() { 1.429 + browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true); 1.430 + 1.431 + executeSoon(() => { 1.432 + let stack = browser.parentNode; 1.433 + let dialogs = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt"); 1.434 + let {button0, button1} = dialogs[0].ui; 1.435 + callback(button0, button1); 1.436 + }); 1.437 + }, true); 1.438 +} 1.439 + 1.440 +/** 1.441 + * Overrides browser.js' OpenBrowserWindow() function to enforce an initial 1.442 + * tab different from about:home to not hit the network. 1.443 + */ 1.444 +function OpenBrowserWindow(aOptions) { 1.445 + let features = ""; 1.446 + let url = "about:blank"; 1.447 + 1.448 + if (aOptions && aOptions.private || false) { 1.449 + features = ",private"; 1.450 + url = "about:privatebrowsing"; 1.451 + } 1.452 + 1.453 + return openDialog(getBrowserURL(), "", "chrome,all,dialog=no" + features, url); 1.454 +}