1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/test/general/head.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,467 @@ 1.4 +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 1.5 + 1.6 +XPCOMUtils.defineLazyModuleGetter(this, "Promise", 1.7 + "resource://gre/modules/Promise.jsm"); 1.8 +XPCOMUtils.defineLazyModuleGetter(this, "Task", 1.9 + "resource://gre/modules/Task.jsm"); 1.10 +XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", 1.11 + "resource://gre/modules/PlacesUtils.jsm"); 1.12 + 1.13 +function whenDelayedStartupFinished(aWindow, aCallback) { 1.14 + Services.obs.addObserver(function observer(aSubject, aTopic) { 1.15 + if (aWindow == aSubject) { 1.16 + Services.obs.removeObserver(observer, aTopic); 1.17 + executeSoon(aCallback); 1.18 + } 1.19 + }, "browser-delayed-startup-finished", false); 1.20 +} 1.21 + 1.22 +function findChromeWindowByURI(aURI) { 1.23 + let windows = Services.wm.getEnumerator(null); 1.24 + while (windows.hasMoreElements()) { 1.25 + let win = windows.getNext(); 1.26 + if (win.location.href == aURI) 1.27 + return win; 1.28 + } 1.29 + return null; 1.30 +} 1.31 + 1.32 +function updateTabContextMenu(tab) { 1.33 + let menu = document.getElementById("tabContextMenu"); 1.34 + if (!tab) 1.35 + tab = gBrowser.selectedTab; 1.36 + var evt = new Event(""); 1.37 + tab.dispatchEvent(evt); 1.38 + menu.openPopup(tab, "end_after", 0, 0, true, false, evt); 1.39 + is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab"); 1.40 + menu.hidePopup(); 1.41 +} 1.42 + 1.43 +function openToolbarCustomizationUI(aCallback, aBrowserWin) { 1.44 + if (!aBrowserWin) 1.45 + aBrowserWin = window; 1.46 + 1.47 + aBrowserWin.gCustomizeMode.enter(); 1.48 + 1.49 + aBrowserWin.gNavToolbox.addEventListener("customizationready", function UI_loaded() { 1.50 + aBrowserWin.gNavToolbox.removeEventListener("customizationready", UI_loaded); 1.51 + executeSoon(function() { 1.52 + aCallback(aBrowserWin) 1.53 + }); 1.54 + }); 1.55 +} 1.56 + 1.57 +function closeToolbarCustomizationUI(aCallback, aBrowserWin) { 1.58 + aBrowserWin.gNavToolbox.addEventListener("aftercustomization", function unloaded() { 1.59 + aBrowserWin.gNavToolbox.removeEventListener("aftercustomization", unloaded); 1.60 + executeSoon(aCallback); 1.61 + }); 1.62 + 1.63 + aBrowserWin.gCustomizeMode.exit(); 1.64 +} 1.65 + 1.66 +function waitForCondition(condition, nextTest, errorMsg) { 1.67 + var tries = 0; 1.68 + var interval = setInterval(function() { 1.69 + if (tries >= 30) { 1.70 + ok(false, errorMsg); 1.71 + moveOn(); 1.72 + } 1.73 + var conditionPassed; 1.74 + try { 1.75 + conditionPassed = condition(); 1.76 + } catch (e) { 1.77 + ok(false, e + "\n" + e.stack); 1.78 + conditionPassed = false; 1.79 + } 1.80 + if (conditionPassed) { 1.81 + moveOn(); 1.82 + } 1.83 + tries++; 1.84 + }, 100); 1.85 + var moveOn = function() { clearInterval(interval); nextTest(); }; 1.86 +} 1.87 + 1.88 +function getTestPlugin(aName) { 1.89 + var pluginName = aName || "Test Plug-in"; 1.90 + var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); 1.91 + var tags = ph.getPluginTags(); 1.92 + 1.93 + // Find the test plugin 1.94 + for (var i = 0; i < tags.length; i++) { 1.95 + if (tags[i].name == pluginName) 1.96 + return tags[i]; 1.97 + } 1.98 + ok(false, "Unable to find plugin"); 1.99 + return null; 1.100 +} 1.101 + 1.102 +// call this to set the test plugin(s) initially expected enabled state. 1.103 +// it will automatically be reset to it's previous value after the test 1.104 +// ends 1.105 +function setTestPluginEnabledState(newEnabledState, pluginName) { 1.106 + var plugin = getTestPlugin(pluginName); 1.107 + var oldEnabledState = plugin.enabledState; 1.108 + plugin.enabledState = newEnabledState; 1.109 + SimpleTest.registerCleanupFunction(function() { 1.110 + getTestPlugin(pluginName).enabledState = oldEnabledState; 1.111 + }); 1.112 +} 1.113 + 1.114 +// after a test is done using the plugin doorhanger, we should just clear 1.115 +// any permissions that may have crept in 1.116 +function clearAllPluginPermissions() { 1.117 + let perms = Services.perms.enumerator; 1.118 + while (perms.hasMoreElements()) { 1.119 + let perm = perms.getNext(); 1.120 + if (perm.type.startsWith('plugin')) { 1.121 + Services.perms.remove(perm.host, perm.type); 1.122 + } 1.123 + } 1.124 +} 1.125 + 1.126 +function updateBlocklist(aCallback) { 1.127 + var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] 1.128 + .getService(Ci.nsITimerCallback); 1.129 + var observer = function() { 1.130 + Services.obs.removeObserver(observer, "blocklist-updated"); 1.131 + SimpleTest.executeSoon(aCallback); 1.132 + }; 1.133 + Services.obs.addObserver(observer, "blocklist-updated", false); 1.134 + blocklistNotifier.notify(null); 1.135 +} 1.136 + 1.137 +var _originalTestBlocklistURL = null; 1.138 +function setAndUpdateBlocklist(aURL, aCallback) { 1.139 + if (!_originalTestBlocklistURL) 1.140 + _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url"); 1.141 + Services.prefs.setCharPref("extensions.blocklist.url", aURL); 1.142 + updateBlocklist(aCallback); 1.143 +} 1.144 + 1.145 +function resetBlocklist() { 1.146 + Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL); 1.147 +} 1.148 + 1.149 +function whenNewWindowLoaded(aOptions, aCallback) { 1.150 + let win = OpenBrowserWindow(aOptions); 1.151 + win.addEventListener("load", function onLoad() { 1.152 + win.removeEventListener("load", onLoad, false); 1.153 + aCallback(win); 1.154 + }, false); 1.155 +} 1.156 + 1.157 +/** 1.158 + * Waits for all pending async statements on the default connection, before 1.159 + * proceeding with aCallback. 1.160 + * 1.161 + * @param aCallback 1.162 + * Function to be called when done. 1.163 + * @param aScope 1.164 + * Scope for the callback. 1.165 + * @param aArguments 1.166 + * Arguments array for the callback. 1.167 + * 1.168 + * @note The result is achieved by asynchronously executing a query requiring 1.169 + * a write lock. Since all statements on the same connection are 1.170 + * serialized, the end of this write operation means that all writes are 1.171 + * complete. Note that WAL makes so that writers don't block readers, but 1.172 + * this is a problem only across different connections. 1.173 + */ 1.174 +function waitForAsyncUpdates(aCallback, aScope, aArguments) { 1.175 + let scope = aScope || this; 1.176 + let args = aArguments || []; 1.177 + let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) 1.178 + .DBConnection; 1.179 + let begin = db.createAsyncStatement("BEGIN EXCLUSIVE"); 1.180 + begin.executeAsync(); 1.181 + begin.finalize(); 1.182 + 1.183 + let commit = db.createAsyncStatement("COMMIT"); 1.184 + commit.executeAsync({ 1.185 + handleResult: function() {}, 1.186 + handleError: function() {}, 1.187 + handleCompletion: function(aReason) { 1.188 + aCallback.apply(scope, args); 1.189 + } 1.190 + }); 1.191 + commit.finalize(); 1.192 +} 1.193 + 1.194 +/** 1.195 + * Asynchronously check a url is visited. 1.196 + 1.197 + * @param aURI The URI. 1.198 + * @param aExpectedValue The expected value. 1.199 + * @return {Promise} 1.200 + * @resolves When the check has been added successfully. 1.201 + * @rejects JavaScript exception. 1.202 + */ 1.203 +function promiseIsURIVisited(aURI, aExpectedValue) { 1.204 + let deferred = Promise.defer(); 1.205 + PlacesUtils.asyncHistory.isURIVisited(aURI, function(aURI, aIsVisited) { 1.206 + deferred.resolve(aIsVisited); 1.207 + }); 1.208 + 1.209 + return deferred.promise; 1.210 +} 1.211 + 1.212 +function whenNewTabLoaded(aWindow, aCallback) { 1.213 + aWindow.BrowserOpenTab(); 1.214 + 1.215 + let browser = aWindow.gBrowser.selectedBrowser; 1.216 + if (browser.contentDocument.readyState === "complete") { 1.217 + aCallback(); 1.218 + return; 1.219 + } 1.220 + 1.221 + whenTabLoaded(aWindow.gBrowser.selectedTab, aCallback); 1.222 +} 1.223 + 1.224 +function whenTabLoaded(aTab, aCallback) { 1.225 + let browser = aTab.linkedBrowser; 1.226 + browser.addEventListener("load", function onLoad() { 1.227 + browser.removeEventListener("load", onLoad, true); 1.228 + executeSoon(aCallback); 1.229 + }, true); 1.230 +} 1.231 + 1.232 +function addVisits(aPlaceInfo, aCallback) { 1.233 + let places = []; 1.234 + if (aPlaceInfo instanceof Ci.nsIURI) { 1.235 + places.push({ uri: aPlaceInfo }); 1.236 + } else if (Array.isArray(aPlaceInfo)) { 1.237 + places = places.concat(aPlaceInfo); 1.238 + } else { 1.239 + places.push(aPlaceInfo); 1.240 + } 1.241 + 1.242 + // Create mozIVisitInfo for each entry. 1.243 + let now = Date.now(); 1.244 + for (let i = 0; i < places.length; i++) { 1.245 + if (!places[i].title) { 1.246 + places[i].title = "test visit for " + places[i].uri.spec; 1.247 + } 1.248 + places[i].visits = [{ 1.249 + transitionType: places[i].transition === undefined ? Ci.nsINavHistoryService.TRANSITION_LINK 1.250 + : places[i].transition, 1.251 + visitDate: places[i].visitDate || (now++) * 1000, 1.252 + referrerURI: places[i].referrer 1.253 + }]; 1.254 + } 1.255 + 1.256 + PlacesUtils.asyncHistory.updatePlaces( 1.257 + places, 1.258 + { 1.259 + handleError: function AAV_handleError() { 1.260 + throw("Unexpected error in adding visit."); 1.261 + }, 1.262 + handleResult: function () {}, 1.263 + handleCompletion: function UP_handleCompletion() { 1.264 + if (aCallback) 1.265 + aCallback(); 1.266 + } 1.267 + } 1.268 + ); 1.269 +} 1.270 + 1.271 +/** 1.272 + * Ensures that the specified URIs are either cleared or not. 1.273 + * 1.274 + * @param aURIs 1.275 + * Array of page URIs 1.276 + * @param aShouldBeCleared 1.277 + * True if each visit to the URI should be cleared, false otherwise 1.278 + */ 1.279 +function promiseHistoryClearedState(aURIs, aShouldBeCleared) { 1.280 + let deferred = Promise.defer(); 1.281 + let callbackCount = 0; 1.282 + let niceStr = aShouldBeCleared ? "no longer" : "still"; 1.283 + function callbackDone() { 1.284 + if (++callbackCount == aURIs.length) 1.285 + deferred.resolve(); 1.286 + } 1.287 + aURIs.forEach(function (aURI) { 1.288 + PlacesUtils.asyncHistory.isURIVisited(aURI, function(aURI, aIsVisited) { 1.289 + is(aIsVisited, !aShouldBeCleared, 1.290 + "history visit " + aURI.spec + " should " + niceStr + " exist"); 1.291 + callbackDone(); 1.292 + }); 1.293 + }); 1.294 + 1.295 + return deferred.promise; 1.296 +} 1.297 + 1.298 +/** 1.299 + * Allows waiting for an observer notification once. 1.300 + * 1.301 + * @param topic 1.302 + * Notification topic to observe. 1.303 + * 1.304 + * @return {Promise} 1.305 + * @resolves The array [subject, data] from the observed notification. 1.306 + * @rejects Never. 1.307 + */ 1.308 +function promiseTopicObserved(topic) 1.309 +{ 1.310 + let deferred = Promise.defer(); 1.311 + Services.obs.addObserver(function PTO_observe(subject, topic, data) { 1.312 + Services.obs.removeObserver(PTO_observe, topic); 1.313 + deferred.resolve([subject, data]); 1.314 + }, topic, false); 1.315 + return deferred.promise; 1.316 +} 1.317 + 1.318 +/** 1.319 + * Clears history asynchronously. 1.320 + * 1.321 + * @return {Promise} 1.322 + * @resolves When history has been cleared. 1.323 + * @rejects Never. 1.324 + */ 1.325 +function promiseClearHistory() { 1.326 + let promise = promiseTopicObserved(PlacesUtils.TOPIC_EXPIRATION_FINISHED); 1.327 + PlacesUtils.bhistory.removeAllPages(); 1.328 + return promise; 1.329 +} 1.330 + 1.331 +/** 1.332 + * Waits for the next top-level document load in the current browser. The URI 1.333 + * of the document is compared against aExpectedURL. The load is then stopped 1.334 + * before it actually starts. 1.335 + * 1.336 + * @param aExpectedURL 1.337 + * The URL of the document that is expected to load. 1.338 + * @return promise 1.339 + */ 1.340 +function waitForDocLoadAndStopIt(aExpectedURL) { 1.341 + let deferred = Promise.defer(); 1.342 + let progressListener = { 1.343 + onStateChange: function (webProgress, req, flags, status) { 1.344 + info("waitForDocLoadAndStopIt: onStateChange: " + req.name); 1.345 + let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | 1.346 + Ci.nsIWebProgressListener.STATE_START; 1.347 + if ((flags & docStart) && webProgress.isTopLevel) { 1.348 + info("waitForDocLoadAndStopIt: Document start: " + 1.349 + req.QueryInterface(Ci.nsIChannel).URI.spec); 1.350 + is(req.originalURI.spec, aExpectedURL, 1.351 + "waitForDocLoadAndStopIt: The expected URL was loaded"); 1.352 + req.cancel(Components.results.NS_ERROR_FAILURE); 1.353 + gBrowser.removeProgressListener(progressListener); 1.354 + deferred.resolve(); 1.355 + } 1.356 + }, 1.357 + }; 1.358 + gBrowser.addProgressListener(progressListener); 1.359 + info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL); 1.360 + return deferred.promise; 1.361 +} 1.362 + 1.363 +let FullZoomHelper = { 1.364 + 1.365 + selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(tab) { 1.366 + if (!tab) 1.367 + throw new Error("tab must be given."); 1.368 + if (gBrowser.selectedTab == tab) 1.369 + return Promise.resolve(); 1.370 + gBrowser.selectedTab = tab; 1.371 + return this.waitForLocationChange(); 1.372 + }, 1.373 + 1.374 + removeTabAndWaitForLocationChange: function removeTabAndWaitForLocationChange(tab) { 1.375 + tab = tab || gBrowser.selectedTab; 1.376 + let selected = gBrowser.selectedTab == tab; 1.377 + gBrowser.removeTab(tab); 1.378 + if (selected) 1.379 + return this.waitForLocationChange(); 1.380 + return Promise.resolve(); 1.381 + }, 1.382 + 1.383 + waitForLocationChange: function waitForLocationChange() { 1.384 + let deferred = Promise.defer(); 1.385 + Services.obs.addObserver(function obs(subj, topic, data) { 1.386 + Services.obs.removeObserver(obs, topic); 1.387 + deferred.resolve(); 1.388 + }, "browser-fullZoom:location-change", false); 1.389 + return deferred.promise; 1.390 + }, 1.391 + 1.392 + load: function load(tab, url) { 1.393 + let deferred = Promise.defer(); 1.394 + let didLoad = false; 1.395 + let didZoom = false; 1.396 + 1.397 + tab.linkedBrowser.addEventListener("load", function (event) { 1.398 + event.currentTarget.removeEventListener("load", arguments.callee, true); 1.399 + didLoad = true; 1.400 + if (didZoom) 1.401 + deferred.resolve(); 1.402 + }, true); 1.403 + 1.404 + this.waitForLocationChange().then(function () { 1.405 + didZoom = true; 1.406 + if (didLoad) 1.407 + deferred.resolve(); 1.408 + }); 1.409 + 1.410 + tab.linkedBrowser.loadURI(url); 1.411 + 1.412 + return deferred.promise; 1.413 + }, 1.414 + 1.415 + zoomTest: function zoomTest(tab, val, msg) { 1.416 + is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg); 1.417 + }, 1.418 + 1.419 + enlarge: function enlarge() { 1.420 + let deferred = Promise.defer(); 1.421 + FullZoom.enlarge(function () deferred.resolve()); 1.422 + return deferred.promise; 1.423 + }, 1.424 + 1.425 + reduce: function reduce() { 1.426 + let deferred = Promise.defer(); 1.427 + FullZoom.reduce(function () deferred.resolve()); 1.428 + return deferred.promise; 1.429 + }, 1.430 + 1.431 + reset: function reset() { 1.432 + let deferred = Promise.defer(); 1.433 + FullZoom.reset(function () deferred.resolve()); 1.434 + return deferred.promise; 1.435 + }, 1.436 + 1.437 + BACK: 0, 1.438 + FORWARD: 1, 1.439 + navigate: function navigate(direction) { 1.440 + let deferred = Promise.defer(); 1.441 + let didPs = false; 1.442 + let didZoom = false; 1.443 + 1.444 + gBrowser.addEventListener("pageshow", function (event) { 1.445 + gBrowser.removeEventListener("pageshow", arguments.callee, true); 1.446 + didPs = true; 1.447 + if (didZoom) 1.448 + deferred.resolve(); 1.449 + }, true); 1.450 + 1.451 + if (direction == this.BACK) 1.452 + gBrowser.goBack(); 1.453 + else if (direction == this.FORWARD) 1.454 + gBrowser.goForward(); 1.455 + 1.456 + this.waitForLocationChange().then(function () { 1.457 + didZoom = true; 1.458 + if (didPs) 1.459 + deferred.resolve(); 1.460 + }); 1.461 + return deferred.promise; 1.462 + }, 1.463 + 1.464 + failAndContinue: function failAndContinue(func) { 1.465 + return function (err) { 1.466 + ok(false, err); 1.467 + func(); 1.468 + }; 1.469 + }, 1.470 +};