Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | * http://creativecommons.org/publicdomain/zero/1.0/ |
michael@0 | 3 | */ |
michael@0 | 4 | |
michael@0 | 5 | /** |
michael@0 | 6 | * Test Definition |
michael@0 | 7 | * |
michael@0 | 8 | * Most tests can use an array named TESTS that will perform most if not all of |
michael@0 | 9 | * the necessary checks. Each element in the array must be an object with the |
michael@0 | 10 | * following possible properties. Additional properties besides the ones listed |
michael@0 | 11 | * below can be added as needed. |
michael@0 | 12 | * |
michael@0 | 13 | * overrideCallback (optional) |
michael@0 | 14 | * The function to call for the next test. This is typically called when the |
michael@0 | 15 | * wizard page changes but can also be called for other events by the previous |
michael@0 | 16 | * test. If this property isn't defined then the defailtCallback function will |
michael@0 | 17 | * be called. If this property is defined then all other properties are |
michael@0 | 18 | * optional. |
michael@0 | 19 | * |
michael@0 | 20 | * pageid (required unless overrideCallback is specified) |
michael@0 | 21 | * The expected pageid for the wizard. This property is required unless the |
michael@0 | 22 | * overrideCallback property is defined. |
michael@0 | 23 | * |
michael@0 | 24 | * extraStartFunction (optional) |
michael@0 | 25 | * The function to call at the beginning of the defaultCallback function. If |
michael@0 | 26 | * the function returns true the defaultCallback function will return early |
michael@0 | 27 | * which allows waiting for a specific condition to be evaluated in the |
michael@0 | 28 | * function specified in the extraStartFunction property before continuing |
michael@0 | 29 | * with the test. |
michael@0 | 30 | * |
michael@0 | 31 | * extraCheckFunction (optional) |
michael@0 | 32 | * The function to call to perform extra checks in the defaultCallback |
michael@0 | 33 | * function. |
michael@0 | 34 | * |
michael@0 | 35 | * extraDelayedCheckFunction (optional) |
michael@0 | 36 | * The function to call to perform extra checks in the delayedDefaultCallback |
michael@0 | 37 | * function. |
michael@0 | 38 | * |
michael@0 | 39 | * buttonStates (optional) |
michael@0 | 40 | * A javascript object representing the expected hidden and disabled attribute |
michael@0 | 41 | * values for the buttons of the current wizard page. The values are checked |
michael@0 | 42 | * in the delayedDefaultCallback function. For information about the structure |
michael@0 | 43 | * of this object refer to the getExpectedButtonStates and checkButtonStates |
michael@0 | 44 | * functions. |
michael@0 | 45 | * |
michael@0 | 46 | * buttonClick (optional) |
michael@0 | 47 | * The current wizard page button to click at the end of the |
michael@0 | 48 | * delayedDefaultCallback function. If the buttonClick property is defined |
michael@0 | 49 | * then the extraDelayedFinishFunction property can't be specified due to race |
michael@0 | 50 | * conditions in some of the tests and if both of them are specified the test |
michael@0 | 51 | * will intentionally throw. |
michael@0 | 52 | * |
michael@0 | 53 | * extraDelayedFinishFunction (optional) |
michael@0 | 54 | * The function to call at the end of the delayedDefaultCallback function. |
michael@0 | 55 | * If the extraDelayedFinishFunction property is defined then the buttonClick |
michael@0 | 56 | * property can't be specified due to race conditions in some of the tests and |
michael@0 | 57 | * if both of them are specified the test will intentionally throw. |
michael@0 | 58 | * |
michael@0 | 59 | * ranTest (should not be specified) |
michael@0 | 60 | * When delayedDefaultCallback is called a property named ranTest is added to |
michael@0 | 61 | * the current test so it is possible to verify that each test in the TESTS |
michael@0 | 62 | * array has ran. |
michael@0 | 63 | * |
michael@0 | 64 | * prefHasUserValue (optional) |
michael@0 | 65 | * For comparing the expected value defined by this property with the return |
michael@0 | 66 | * value of prefHasUserValue using gPrefToCheck for the preference name in the |
michael@0 | 67 | * checkPrefHasUserValue function. |
michael@0 | 68 | * |
michael@0 | 69 | * expectedRadioGroupSelectedIndex (optional) |
michael@0 | 70 | * For comparing the expected selectedIndex attribute value of the wizard's |
michael@0 | 71 | * license page radiogroup selectedIndex attribute in the |
michael@0 | 72 | * checkRadioGroupSelectedIndex function. |
michael@0 | 73 | * |
michael@0 | 74 | * expectedRemoteContentState (optional) |
michael@0 | 75 | * For comparing the expected remotecontent state attribute value of the |
michael@0 | 76 | * wizard's billboard and license pages in the checkRemoteContentState and |
michael@0 | 77 | * waitForRemoteContentLoaded functions. |
michael@0 | 78 | * |
michael@0 | 79 | * |
michael@0 | 80 | * Test Add-ons |
michael@0 | 81 | * |
michael@0 | 82 | * All tests include the test add-ons specified in the TEST_ADDONS array and |
michael@0 | 83 | * the only thing that can be configured is whether the noupdate test add-on is |
michael@0 | 84 | * disabled (see below). The add-on names are in the format of typename_X where |
michael@0 | 85 | * X is a number to make the add-on ID unique and typename is one of the values |
michael@0 | 86 | * specified below: |
michael@0 | 87 | * |
michael@0 | 88 | * appdisabled |
michael@0 | 89 | * disabled by the application due to being incompatible with the current |
michael@0 | 90 | * toolkit version. |
michael@0 | 91 | * |
michael@0 | 92 | * compatible |
michael@0 | 93 | * compatible with the current toolkit version and the update's toolkit |
michael@0 | 94 | * version. |
michael@0 | 95 | * |
michael@0 | 96 | * noupdate |
michael@0 | 97 | * the add-on is compatible with the current toolkit version and does not have |
michael@0 | 98 | * an update to make it compatible with the update's toolkit version. Tests |
michael@0 | 99 | * that need to have all add-ons compatible for the application update can |
michael@0 | 100 | * disable this add-on by setting the gDisableNoUpdateAddon variable to true. |
michael@0 | 101 | * |
michael@0 | 102 | * updatecompatibility |
michael@0 | 103 | * the add-on is compatible with the current toolkit version and has a |
michael@0 | 104 | * compatibility update to make it compatible with the update's toolkit |
michael@0 | 105 | * version. |
michael@0 | 106 | * |
michael@0 | 107 | * updateversion |
michael@0 | 108 | * the add-on is compatible with the current toolkit version and has a version |
michael@0 | 109 | * update to make it compatible with the update's toolkit version. |
michael@0 | 110 | * |
michael@0 | 111 | * userdisabled |
michael@0 | 112 | * disabled by the user and compatible with the current toolkit version but |
michael@0 | 113 | * not the update's toolkit version. This add-on will be disabled after its |
michael@0 | 114 | * install completes. |
michael@0 | 115 | */ |
michael@0 | 116 | |
michael@0 | 117 | Components.utils.import("resource://gre/modules/AddonManager.jsm"); |
michael@0 | 118 | |
michael@0 | 119 | // The tests have to use the pageid instead of the pageIndex due to the |
michael@0 | 120 | // app update wizard's access method being random. |
michael@0 | 121 | const PAGEID_DUMMY = "dummy"; // Done |
michael@0 | 122 | const PAGEID_CHECKING = "checking"; // Done |
michael@0 | 123 | const PAGEID_PLUGIN_UPDATES = "pluginupdatesfound"; |
michael@0 | 124 | const PAGEID_NO_UPDATES_FOUND = "noupdatesfound"; // Done |
michael@0 | 125 | const PAGEID_MANUAL_UPDATE = "manualUpdate"; // Tested on license load failure |
michael@0 | 126 | const PAGEID_UNSUPPORTED = "unsupported"; // Done |
michael@0 | 127 | const PAGEID_INCOMPAT_CHECK = "incompatibleCheck"; // Done |
michael@0 | 128 | const PAGEID_FOUND_BASIC = "updatesfoundbasic"; // Done |
michael@0 | 129 | const PAGEID_FOUND_BILLBOARD = "updatesfoundbillboard"; // Done |
michael@0 | 130 | const PAGEID_LICENSE = "license"; // Done |
michael@0 | 131 | const PAGEID_INCOMPAT_LIST = "incompatibleList"; // Done |
michael@0 | 132 | const PAGEID_DOWNLOADING = "downloading"; // Done |
michael@0 | 133 | const PAGEID_ERRORS = "errors"; // Done |
michael@0 | 134 | const PAGEID_ERROR_EXTRA = "errorextra"; // Done |
michael@0 | 135 | const PAGEID_ERROR_PATCHING = "errorpatching"; // Done |
michael@0 | 136 | const PAGEID_FINISHED = "finished"; // Done |
michael@0 | 137 | const PAGEID_FINISHED_BKGRD = "finishedBackground"; // Done |
michael@0 | 138 | const PAGEID_INSTALLED = "installed"; // Done |
michael@0 | 139 | |
michael@0 | 140 | const UPDATE_WINDOW_NAME = "Update:Wizard"; |
michael@0 | 141 | |
michael@0 | 142 | const URL_HOST = "http://example.com"; |
michael@0 | 143 | const URL_PATH_UPDATE_XML = "/chrome/toolkit/mozapps/update/tests/chrome/update.sjs"; |
michael@0 | 144 | const REL_PATH_DATA = "chrome/toolkit/mozapps/update/tests/data"; |
michael@0 | 145 | |
michael@0 | 146 | const URL_HTTP_UPDATE_XML = URL_HOST + URL_PATH_UPDATE_XML; |
michael@0 | 147 | const URL_HTTPS_UPDATE_XML = "https://example.com" + URL_PATH_UPDATE_XML; |
michael@0 | 148 | |
michael@0 | 149 | const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul"; |
michael@0 | 150 | |
michael@0 | 151 | const ADDON_ID_SUFFIX = "@appupdatetest.mozilla.org"; |
michael@0 | 152 | const ADDON_PREP_DIR = "appupdateprep"; |
michael@0 | 153 | // Preference for storing add-ons that are disabled by the tests to prevent them |
michael@0 | 154 | // from interefering with the tests. |
michael@0 | 155 | const PREF_DISABLEDADDONS = "app.update.test.disabledAddons"; |
michael@0 | 156 | const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; |
michael@0 | 157 | const TEST_ADDONS = [ "appdisabled_1", "appdisabled_2", |
michael@0 | 158 | "compatible_1", "compatible_2", |
michael@0 | 159 | "noupdate_1", "noupdate_2", |
michael@0 | 160 | "updatecompatibility_1", "updatecompatibility_2", |
michael@0 | 161 | "updateversion_1", "updateversion_2", |
michael@0 | 162 | "userdisabled_1", "userdisabled_2", "hotfix" ]; |
michael@0 | 163 | |
michael@0 | 164 | var gURLData = URL_HOST + "/" + REL_PATH_DATA + "/"; |
michael@0 | 165 | |
michael@0 | 166 | var gTestTimeout = 240000; // 4 minutes |
michael@0 | 167 | var gTimeoutTimer; |
michael@0 | 168 | |
michael@0 | 169 | // The number of SimpleTest.executeSoon calls to perform when waiting on an |
michael@0 | 170 | // update window to close before giving up. |
michael@0 | 171 | const CLOSE_WINDOW_TIMEOUT_MAXCOUNT = 10; |
michael@0 | 172 | // Counter for the SimpleTest.executeSoon when waiting on an update window to |
michael@0 | 173 | // close before giving up. |
michael@0 | 174 | var gCloseWindowTimeoutCounter = 0; |
michael@0 | 175 | |
michael@0 | 176 | // The following vars are for restoring previous preference values (if present) |
michael@0 | 177 | // when the test finishes. |
michael@0 | 178 | var gAppUpdateEnabled; // app.update.enabled |
michael@0 | 179 | var gAppUpdateMetroEnabled; // app.update.metro.enabled |
michael@0 | 180 | var gAppUpdateServiceEnabled; // app.update.service.enabled |
michael@0 | 181 | var gAppUpdateStagingEnabled; // app.update.staging.enabled |
michael@0 | 182 | var gAppUpdateURLDefault; // app.update.url (default prefbranch) |
michael@0 | 183 | var gAppUpdateURL; // app.update.url.override |
michael@0 | 184 | var gExtUpdateURL; // extensions.update.url |
michael@0 | 185 | |
michael@0 | 186 | var gTestCounter = -1; |
michael@0 | 187 | var gWin; |
michael@0 | 188 | var gDocElem; |
michael@0 | 189 | var gPrefToCheck; |
michael@0 | 190 | var gDisableNoUpdateAddon = false; |
michael@0 | 191 | |
michael@0 | 192 | // Set to true to log additional information for debugging. To log additional |
michael@0 | 193 | // information for an individual test set DEBUG_AUS_TEST to true in the test's |
michael@0 | 194 | // onload function. |
michael@0 | 195 | var DEBUG_AUS_TEST = true; |
michael@0 | 196 | |
michael@0 | 197 | #include ../shared.js |
michael@0 | 198 | |
michael@0 | 199 | /** |
michael@0 | 200 | * The current test in TESTS array. |
michael@0 | 201 | */ |
michael@0 | 202 | this.__defineGetter__("gTest", function() { |
michael@0 | 203 | return TESTS[gTestCounter]; |
michael@0 | 204 | }); |
michael@0 | 205 | |
michael@0 | 206 | /** |
michael@0 | 207 | * The current test's callback. This will either return the callback defined in |
michael@0 | 208 | * the test's overrideCallback property or defaultCallback if the |
michael@0 | 209 | * overrideCallback property is undefined. |
michael@0 | 210 | */ |
michael@0 | 211 | this.__defineGetter__("gCallback", function() { |
michael@0 | 212 | return gTest.overrideCallback ? gTest.overrideCallback |
michael@0 | 213 | : defaultCallback; |
michael@0 | 214 | }); |
michael@0 | 215 | |
michael@0 | 216 | /** |
michael@0 | 217 | * The remotecontent element for the current page if one exists or null if a |
michael@0 | 218 | * remotecontent element doesn't exist. |
michael@0 | 219 | */ |
michael@0 | 220 | this.__defineGetter__("gRemoteContent", function() { |
michael@0 | 221 | switch (gTest.pageid) { |
michael@0 | 222 | case PAGEID_FOUND_BILLBOARD: |
michael@0 | 223 | return gWin.document.getElementById("updateMoreInfoContent"); |
michael@0 | 224 | case PAGEID_LICENSE: |
michael@0 | 225 | return gWin.document.getElementById("licenseContent"); |
michael@0 | 226 | } |
michael@0 | 227 | return null; |
michael@0 | 228 | }); |
michael@0 | 229 | |
michael@0 | 230 | /** |
michael@0 | 231 | * The state for the remotecontent element if one exists or null if a |
michael@0 | 232 | * remotecontent element doesn't exist. |
michael@0 | 233 | */ |
michael@0 | 234 | this.__defineGetter__("gRemoteContentState", function() { |
michael@0 | 235 | if (gRemoteContent) { |
michael@0 | 236 | return gRemoteContent.getAttribute("state"); |
michael@0 | 237 | } |
michael@0 | 238 | return null; |
michael@0 | 239 | }); |
michael@0 | 240 | |
michael@0 | 241 | /** |
michael@0 | 242 | * The radiogroup for the license page. |
michael@0 | 243 | */ |
michael@0 | 244 | this.__defineGetter__("gAcceptDeclineLicense", function() { |
michael@0 | 245 | return gWin.document.getElementById("acceptDeclineLicense"); |
michael@0 | 246 | }); |
michael@0 | 247 | |
michael@0 | 248 | /** |
michael@0 | 249 | * The listbox for the incompatibleList page. |
michael@0 | 250 | */ |
michael@0 | 251 | this.__defineGetter__("gIncompatibleListbox", function() { |
michael@0 | 252 | return gWin.document.getElementById("incompatibleListbox"); |
michael@0 | 253 | }); |
michael@0 | 254 | |
michael@0 | 255 | /** |
michael@0 | 256 | * Default test run function that can be used by most tests. This function uses |
michael@0 | 257 | * protective measures to prevent the test from failing provided by |
michael@0 | 258 | * |runTestDefaultWaitForWindowClosed| helper functions to prevent failure due |
michael@0 | 259 | * to a previous test failure. |
michael@0 | 260 | */ |
michael@0 | 261 | function runTestDefault() { |
michael@0 | 262 | debugDump("entering"); |
michael@0 | 263 | |
michael@0 | 264 | if (!("@mozilla.org/zipwriter;1" in AUS_Cc)) { |
michael@0 | 265 | ok(false, "nsIZipWriter is required to run these tests"); |
michael@0 | 266 | return; |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 270 | |
michael@0 | 271 | runTestDefaultWaitForWindowClosed(); |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | /** |
michael@0 | 275 | * If an update window is found SimpleTest.executeSoon can callback before the |
michael@0 | 276 | * update window is fully closed especially with debug builds. If an update |
michael@0 | 277 | * window is found this function will call itself using SimpleTest.executeSoon |
michael@0 | 278 | * up to the amount declared in CLOSE_WINDOW_TIMEOUT_MAXCOUNT until the update |
michael@0 | 279 | * window has closed before continuing the test. |
michael@0 | 280 | */ |
michael@0 | 281 | function runTestDefaultWaitForWindowClosed() { |
michael@0 | 282 | gCloseWindowTimeoutCounter++; |
michael@0 | 283 | if (gCloseWindowTimeoutCounter > CLOSE_WINDOW_TIMEOUT_MAXCOUNT) { |
michael@0 | 284 | try { |
michael@0 | 285 | finishTest(); |
michael@0 | 286 | } |
michael@0 | 287 | catch (e) { |
michael@0 | 288 | finishTestDefault(); |
michael@0 | 289 | } |
michael@0 | 290 | return; |
michael@0 | 291 | } |
michael@0 | 292 | |
michael@0 | 293 | // The update window should not be open at this time. If it is the call to |
michael@0 | 294 | // |closeUpdateWindow| will close it and cause the test to fail. |
michael@0 | 295 | if (closeUpdateWindow()) { |
michael@0 | 296 | SimpleTest.executeSoon(runTestDefaultWaitForWindowClosed); |
michael@0 | 297 | } |
michael@0 | 298 | else { |
michael@0 | 299 | Services.ww.registerNotification(gWindowObserver); |
michael@0 | 300 | |
michael@0 | 301 | gCloseWindowTimeoutCounter = 0; |
michael@0 | 302 | |
michael@0 | 303 | setupFiles(); |
michael@0 | 304 | setupPrefs(); |
michael@0 | 305 | removeUpdateDirsAndFiles(); |
michael@0 | 306 | reloadUpdateManagerData(); |
michael@0 | 307 | setupAddons(runTest); |
michael@0 | 308 | } |
michael@0 | 309 | } |
michael@0 | 310 | |
michael@0 | 311 | /** |
michael@0 | 312 | * Default test finish function that can be used by most tests. This function |
michael@0 | 313 | * uses protective measures to prevent the next test from failing provided by |
michael@0 | 314 | * |finishTestDefaultWaitForWindowClosed| helper functions to prevent failure |
michael@0 | 315 | * due to an update window being left open. |
michael@0 | 316 | */ |
michael@0 | 317 | function finishTestDefault() { |
michael@0 | 318 | debugDump("entering"); |
michael@0 | 319 | if (gTimeoutTimer) { |
michael@0 | 320 | gTimeoutTimer.cancel(); |
michael@0 | 321 | gTimeoutTimer = null; |
michael@0 | 322 | } |
michael@0 | 323 | |
michael@0 | 324 | if (gChannel) { |
michael@0 | 325 | debugDump("channel = " + gChannel); |
michael@0 | 326 | gChannel = null; |
michael@0 | 327 | gPrefRoot.removeObserver(PREF_APP_UPDATE_CHANNEL, observer); |
michael@0 | 328 | } |
michael@0 | 329 | |
michael@0 | 330 | verifyTestsRan(); |
michael@0 | 331 | |
michael@0 | 332 | resetPrefs(); |
michael@0 | 333 | resetFiles(); |
michael@0 | 334 | removeUpdateDirsAndFiles(); |
michael@0 | 335 | reloadUpdateManagerData(); |
michael@0 | 336 | |
michael@0 | 337 | Services.ww.unregisterNotification(gWindowObserver); |
michael@0 | 338 | if (gDocElem) { |
michael@0 | 339 | gDocElem.removeEventListener("pageshow", onPageShowDefault, false); |
michael@0 | 340 | } |
michael@0 | 341 | |
michael@0 | 342 | finishTestDefaultWaitForWindowClosed(); |
michael@0 | 343 | } |
michael@0 | 344 | |
michael@0 | 345 | /** |
michael@0 | 346 | * nsITimerCallback for the timeout timer to cleanly finish a test if the Update |
michael@0 | 347 | * Window doesn't close for a test. This allows the next test to run properly if |
michael@0 | 348 | * a previous test fails. |
michael@0 | 349 | * |
michael@0 | 350 | * @param aTimer |
michael@0 | 351 | * The nsITimer that fired. |
michael@0 | 352 | */ |
michael@0 | 353 | function finishTestTimeout(aTimer) { |
michael@0 | 354 | ok(false, "Test timed out. Maximum time allowed is " + (gTestTimeout / 1000) + |
michael@0 | 355 | " seconds"); |
michael@0 | 356 | |
michael@0 | 357 | try { |
michael@0 | 358 | finishTest(); |
michael@0 | 359 | } |
michael@0 | 360 | catch (e) { |
michael@0 | 361 | finishTestDefault(); |
michael@0 | 362 | } |
michael@0 | 363 | } |
michael@0 | 364 | |
michael@0 | 365 | /** |
michael@0 | 366 | * If an update window is found SimpleTest.executeSoon can callback before the |
michael@0 | 367 | * update window is fully closed especially with debug builds. If an update |
michael@0 | 368 | * window is found this function will call itself using SimpleTest.executeSoon |
michael@0 | 369 | * up to the amount declared in CLOSE_WINDOW_TIMEOUT_MAXCOUNT until the update |
michael@0 | 370 | * window has closed before finishing the test. |
michael@0 | 371 | */ |
michael@0 | 372 | function finishTestDefaultWaitForWindowClosed() { |
michael@0 | 373 | gCloseWindowTimeoutCounter++; |
michael@0 | 374 | if (gCloseWindowTimeoutCounter > CLOSE_WINDOW_TIMEOUT_MAXCOUNT) { |
michael@0 | 375 | SimpleTest.finish(); |
michael@0 | 376 | return; |
michael@0 | 377 | } |
michael@0 | 378 | |
michael@0 | 379 | // The update window should not be open at this time. If it is the call to |
michael@0 | 380 | // |closeUpdateWindow| will close it and cause the test to fail. |
michael@0 | 381 | if (closeUpdateWindow()) { |
michael@0 | 382 | SimpleTest.executeSoon(finishTestDefaultWaitForWindowClosed); |
michael@0 | 383 | } |
michael@0 | 384 | else { |
michael@0 | 385 | SimpleTest.finish(); |
michael@0 | 386 | } |
michael@0 | 387 | } |
michael@0 | 388 | |
michael@0 | 389 | /** |
michael@0 | 390 | * Default callback for the wizard's documentElement pageshow listener. This |
michael@0 | 391 | * will return early for event's where the originalTarget's nodeName is not |
michael@0 | 392 | * wizardpage. |
michael@0 | 393 | */ |
michael@0 | 394 | function onPageShowDefault(aEvent) { |
michael@0 | 395 | if (!gTimeoutTimer) { |
michael@0 | 396 | debugDump("gTimeoutTimer is null... returning early"); |
michael@0 | 397 | return; |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | // Return early if the event's original target isn't for a wizardpage element. |
michael@0 | 401 | // This check is necessary due to the remotecontent element firing pageshow. |
michael@0 | 402 | if (aEvent.originalTarget.nodeName != "wizardpage") { |
michael@0 | 403 | debugDump("only handles events with an originalTarget nodeName of " + |
michael@0 | 404 | "|wizardpage|. aEvent.originalTarget.nodeName = " + |
michael@0 | 405 | aEvent.originalTarget.nodeName + "... returning early"); |
michael@0 | 406 | return; |
michael@0 | 407 | } |
michael@0 | 408 | |
michael@0 | 409 | gTestCounter++; |
michael@0 | 410 | gCallback(aEvent); |
michael@0 | 411 | } |
michael@0 | 412 | |
michael@0 | 413 | /** |
michael@0 | 414 | * Default callback that can be used by most tests. |
michael@0 | 415 | */ |
michael@0 | 416 | function defaultCallback(aEvent) { |
michael@0 | 417 | if (!gTimeoutTimer) { |
michael@0 | 418 | debugDump("gTimeoutTimer is null... returning early"); |
michael@0 | 419 | return; |
michael@0 | 420 | } |
michael@0 | 421 | |
michael@0 | 422 | debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid + |
michael@0 | 423 | ", aEvent.originalTarget.nodeName: " + |
michael@0 | 424 | aEvent.originalTarget.nodeName); |
michael@0 | 425 | |
michael@0 | 426 | if (gTest && gTest.extraStartFunction) { |
michael@0 | 427 | debugDump("calling extraStartFunction " + gTest.extraStartFunction.name); |
michael@0 | 428 | if (gTest.extraStartFunction(aEvent)) { |
michael@0 | 429 | debugDump("extraStartFunction early return"); |
michael@0 | 430 | return; |
michael@0 | 431 | } |
michael@0 | 432 | } |
michael@0 | 433 | |
michael@0 | 434 | is(gDocElem.currentPage.pageid, gTest.pageid, |
michael@0 | 435 | "Checking currentPage.pageid equals " + gTest.pageid + " in pageshow"); |
michael@0 | 436 | |
michael@0 | 437 | // Perform extra checks if specified by the test |
michael@0 | 438 | if (gTest.extraCheckFunction) { |
michael@0 | 439 | debugDump("calling extraCheckFunction " + gTest.extraCheckFunction.name); |
michael@0 | 440 | gTest.extraCheckFunction(); |
michael@0 | 441 | } |
michael@0 | 442 | |
michael@0 | 443 | // The wizard page buttons' disabled and hidden attributes are set after the |
michael@0 | 444 | // pageshow event so use executeSoon to allow them to be set so their disabled |
michael@0 | 445 | // and hidden attribute values can be checked. |
michael@0 | 446 | SimpleTest.executeSoon(delayedDefaultCallback); |
michael@0 | 447 | } |
michael@0 | 448 | |
michael@0 | 449 | /** |
michael@0 | 450 | * Delayed default callback called using executeSoon in defaultCallback which |
michael@0 | 451 | * allows the wizard page buttons' disabled and hidden attributes to be set |
michael@0 | 452 | * before checking their values. |
michael@0 | 453 | */ |
michael@0 | 454 | function delayedDefaultCallback() { |
michael@0 | 455 | if (!gTimeoutTimer) { |
michael@0 | 456 | debugDump("gTimeoutTimer is null... returning early"); |
michael@0 | 457 | return; |
michael@0 | 458 | } |
michael@0 | 459 | |
michael@0 | 460 | if (!gTest) { |
michael@0 | 461 | debugDump("gTest is null... returning early"); |
michael@0 | 462 | return; |
michael@0 | 463 | } |
michael@0 | 464 | |
michael@0 | 465 | debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid); |
michael@0 | 466 | |
michael@0 | 467 | // Verify the pageid hasn't changed after executeSoon was called. |
michael@0 | 468 | is(gDocElem.currentPage.pageid, gTest.pageid, |
michael@0 | 469 | "Checking currentPage.pageid equals " + gTest.pageid + " after " + |
michael@0 | 470 | "executeSoon"); |
michael@0 | 471 | |
michael@0 | 472 | checkButtonStates(); |
michael@0 | 473 | |
michael@0 | 474 | // Perform delayed extra checks if specified by the test |
michael@0 | 475 | if (gTest.extraDelayedCheckFunction) { |
michael@0 | 476 | debugDump("calling extraDelayedCheckFunction " + |
michael@0 | 477 | gTest.extraDelayedCheckFunction.name); |
michael@0 | 478 | gTest.extraDelayedCheckFunction(); |
michael@0 | 479 | } |
michael@0 | 480 | |
michael@0 | 481 | // Used to verify that this test has been performed |
michael@0 | 482 | gTest.ranTest = true; |
michael@0 | 483 | |
michael@0 | 484 | if (gTest.buttonClick) { |
michael@0 | 485 | debugDump("clicking " + gTest.buttonClick + " button"); |
michael@0 | 486 | if(gTest.extraDelayedFinishFunction) { |
michael@0 | 487 | throw("Tests cannot have a buttonClick and an extraDelayedFinishFunction property"); |
michael@0 | 488 | } |
michael@0 | 489 | gDocElem.getButton(gTest.buttonClick).click(); |
michael@0 | 490 | } |
michael@0 | 491 | else if (gTest.extraDelayedFinishFunction) { |
michael@0 | 492 | debugDump("calling extraDelayedFinishFunction " + |
michael@0 | 493 | gTest.extraDelayedFinishFunction.name); |
michael@0 | 494 | gTest.extraDelayedFinishFunction(); |
michael@0 | 495 | } |
michael@0 | 496 | } |
michael@0 | 497 | |
michael@0 | 498 | /** |
michael@0 | 499 | * Checks the wizard page buttons' disabled and hidden attributes values are |
michael@0 | 500 | * correct. If an expected button id is not specified then the expected disabled |
michael@0 | 501 | * and hidden attribute value is true. |
michael@0 | 502 | */ |
michael@0 | 503 | function checkButtonStates() { |
michael@0 | 504 | debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid); |
michael@0 | 505 | |
michael@0 | 506 | const buttonNames = ["extra1", "extra2", "back", "next", "finish", "cancel"]; |
michael@0 | 507 | let buttonStates = getExpectedButtonStates(); |
michael@0 | 508 | buttonNames.forEach(function(aButtonName) { |
michael@0 | 509 | let button = gDocElem.getButton(aButtonName); |
michael@0 | 510 | let hasHidden = aButtonName in buttonStates && |
michael@0 | 511 | "hidden" in buttonStates[aButtonName]; |
michael@0 | 512 | let hidden = hasHidden ? buttonStates[aButtonName].hidden : true; |
michael@0 | 513 | let hasDisabled = aButtonName in buttonStates && |
michael@0 | 514 | "disabled" in buttonStates[aButtonName]; |
michael@0 | 515 | let disabled = hasDisabled ? buttonStates[aButtonName].disabled : true; |
michael@0 | 516 | is(button.hidden, hidden, "Checking " + aButtonName + " button " + |
michael@0 | 517 | "hidden attribute value equals " + (hidden ? "true" : "false")); |
michael@0 | 518 | is(button.disabled, disabled, "Checking " + aButtonName + " button " + |
michael@0 | 519 | "disabled attribute value equals " + (disabled ? "true" : "false")); |
michael@0 | 520 | }); |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | /** |
michael@0 | 524 | * Returns the expected disabled and hidden attribute values for the buttons of |
michael@0 | 525 | * the current wizard page. |
michael@0 | 526 | */ |
michael@0 | 527 | function getExpectedButtonStates() { |
michael@0 | 528 | // Allow individual tests to override the expected button states. |
michael@0 | 529 | if (gTest.buttonStates) { |
michael@0 | 530 | return gTest.buttonStates; |
michael@0 | 531 | } |
michael@0 | 532 | |
michael@0 | 533 | switch (gTest.pageid) { |
michael@0 | 534 | case PAGEID_CHECKING: |
michael@0 | 535 | case PAGEID_INCOMPAT_CHECK: |
michael@0 | 536 | return { cancel: { disabled: false, hidden: false } }; |
michael@0 | 537 | case PAGEID_FOUND_BASIC: |
michael@0 | 538 | case PAGEID_FOUND_BILLBOARD: |
michael@0 | 539 | if (gTest.neverButton) { |
michael@0 | 540 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 541 | extra2: { disabled: false, hidden: false }, |
michael@0 | 542 | next : { disabled: false, hidden: false } } |
michael@0 | 543 | } |
michael@0 | 544 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 545 | next : { disabled: false, hidden: false } }; |
michael@0 | 546 | case PAGEID_LICENSE: |
michael@0 | 547 | if (gRemoteContentState != "loaded" || |
michael@0 | 548 | gAcceptDeclineLicense.selectedIndex != 0) { |
michael@0 | 549 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 550 | next : { disabled: true, hidden: false } }; |
michael@0 | 551 | } |
michael@0 | 552 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 553 | next : { disabled: false, hidden: false } }; |
michael@0 | 554 | case PAGEID_INCOMPAT_LIST: |
michael@0 | 555 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 556 | next : { disabled: false, hidden: false } }; |
michael@0 | 557 | case PAGEID_DOWNLOADING: |
michael@0 | 558 | return { extra1: { disabled: false, hidden: false } }; |
michael@0 | 559 | case PAGEID_NO_UPDATES_FOUND: |
michael@0 | 560 | case PAGEID_MANUAL_UPDATE: |
michael@0 | 561 | case PAGEID_UNSUPPORTED: |
michael@0 | 562 | case PAGEID_ERRORS: |
michael@0 | 563 | case PAGEID_ERROR_EXTRA: |
michael@0 | 564 | case PAGEID_INSTALLED: |
michael@0 | 565 | return { finish: { disabled: false, hidden: false } }; |
michael@0 | 566 | case PAGEID_ERROR_PATCHING: |
michael@0 | 567 | return { next : { disabled: false, hidden: false } }; |
michael@0 | 568 | case PAGEID_FINISHED: |
michael@0 | 569 | case PAGEID_FINISHED_BKGRD: |
michael@0 | 570 | return { extra1: { disabled: false, hidden: false }, |
michael@0 | 571 | finish: { disabled: false, hidden: false } }; |
michael@0 | 572 | } |
michael@0 | 573 | return null; |
michael@0 | 574 | } |
michael@0 | 575 | |
michael@0 | 576 | /** |
michael@0 | 577 | * Adds a load event listener to the current remotecontent element. |
michael@0 | 578 | */ |
michael@0 | 579 | function addRemoteContentLoadListener() { |
michael@0 | 580 | debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid); |
michael@0 | 581 | |
michael@0 | 582 | gRemoteContent.addEventListener("load", remoteContentLoadListener, false); |
michael@0 | 583 | } |
michael@0 | 584 | |
michael@0 | 585 | /** |
michael@0 | 586 | * The nsIDOMEventListener for a remotecontent load event. |
michael@0 | 587 | */ |
michael@0 | 588 | function remoteContentLoadListener(aEvent) { |
michael@0 | 589 | // Return early if the event's original target's nodeName isn't remotecontent. |
michael@0 | 590 | if (aEvent.originalTarget.nodeName != "remotecontent") { |
michael@0 | 591 | debugDump("only handles events with an originalTarget nodeName of " + |
michael@0 | 592 | "|remotecontent|. aEvent.originalTarget.nodeName = " + |
michael@0 | 593 | aEvent.originalTarget.nodeName); |
michael@0 | 594 | return; |
michael@0 | 595 | } |
michael@0 | 596 | |
michael@0 | 597 | gTestCounter++; |
michael@0 | 598 | gCallback(aEvent); |
michael@0 | 599 | } |
michael@0 | 600 | |
michael@0 | 601 | /** |
michael@0 | 602 | * Waits until a remotecontent element to finish loading which is determined |
michael@0 | 603 | * by the current test's expectedRemoteContentState property and then removes |
michael@0 | 604 | * the event listener. |
michael@0 | 605 | * |
michael@0 | 606 | * Note: tests that use this function should not test the state of the |
michael@0 | 607 | * remotecontent since this will check the expected state. |
michael@0 | 608 | * |
michael@0 | 609 | * @return false if the remotecontent has loaded and its state is the state |
michael@0 | 610 | * specified in the current test's expectedRemoteContentState |
michael@0 | 611 | * property... otherwise true. |
michael@0 | 612 | */ |
michael@0 | 613 | function waitForRemoteContentLoaded(aEvent) { |
michael@0 | 614 | // Return early until the remotecontent has loaded with the state that is |
michael@0 | 615 | // expected or isn't the event's originalTarget. |
michael@0 | 616 | if (gRemoteContentState != gTest.expectedRemoteContentState || |
michael@0 | 617 | aEvent.originalTarget != gRemoteContent) { |
michael@0 | 618 | debugDump("returning early\n" + |
michael@0 | 619 | "gRemoteContentState: " + gRemoteContentState + "\n" + |
michael@0 | 620 | "expectedRemoteContentState: " + |
michael@0 | 621 | gTest.expectedRemoteContentState + "\n" + |
michael@0 | 622 | "aEvent.originalTarget.nodeName: " + |
michael@0 | 623 | aEvent.originalTarget.nodeName); |
michael@0 | 624 | return true; |
michael@0 | 625 | } |
michael@0 | 626 | |
michael@0 | 627 | gRemoteContent.removeEventListener("load", remoteContentLoadListener, false); |
michael@0 | 628 | return false; |
michael@0 | 629 | } |
michael@0 | 630 | |
michael@0 | 631 | /** |
michael@0 | 632 | * Compares the value of the remotecontent state attribute with the value |
michael@0 | 633 | * specified in the test's expectedRemoteContentState property. |
michael@0 | 634 | */ |
michael@0 | 635 | function checkRemoteContentState() { |
michael@0 | 636 | is(gRemoteContentState, gTest.expectedRemoteContentState, "Checking remote " + |
michael@0 | 637 | "content state equals " + gTest.expectedRemoteContentState + " - pageid " + |
michael@0 | 638 | gTest.pageid); |
michael@0 | 639 | } |
michael@0 | 640 | |
michael@0 | 641 | /** |
michael@0 | 642 | * Adds a select event listener to the license radiogroup element and clicks |
michael@0 | 643 | * the radio element specified in the current test's radioClick property. |
michael@0 | 644 | */ |
michael@0 | 645 | function addRadioGroupSelectListenerAndClick() { |
michael@0 | 646 | debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid); |
michael@0 | 647 | |
michael@0 | 648 | gAcceptDeclineLicense.addEventListener("select", radioGroupSelectListener, |
michael@0 | 649 | false); |
michael@0 | 650 | gWin.document.getElementById(gTest.radioClick).click(); |
michael@0 | 651 | } |
michael@0 | 652 | |
michael@0 | 653 | /** |
michael@0 | 654 | * The nsIDOMEventListener for the license radiogroup select event. |
michael@0 | 655 | */ |
michael@0 | 656 | function radioGroupSelectListener(aEvent) { |
michael@0 | 657 | // Return early if the event's original target's nodeName isn't radiogroup. |
michael@0 | 658 | if (aEvent.originalTarget.nodeName != "radiogroup") { |
michael@0 | 659 | debugDump("only handles events with an originalTarget nodeName of " + |
michael@0 | 660 | "|radiogroup|. aEvent.originalTarget.nodeName = " + |
michael@0 | 661 | aEvent.originalTarget.nodeName); |
michael@0 | 662 | return; |
michael@0 | 663 | } |
michael@0 | 664 | |
michael@0 | 665 | gAcceptDeclineLicense.removeEventListener("select", radioGroupSelectListener, |
michael@0 | 666 | false); |
michael@0 | 667 | gTestCounter++; |
michael@0 | 668 | gCallback(aEvent); |
michael@0 | 669 | } |
michael@0 | 670 | |
michael@0 | 671 | /** |
michael@0 | 672 | * Compares the value of the License radiogroup's selectedIndex attribute with |
michael@0 | 673 | * the value specified in the test's expectedRadioGroupSelectedIndex property. |
michael@0 | 674 | */ |
michael@0 | 675 | function checkRadioGroupSelectedIndex() { |
michael@0 | 676 | is(gAcceptDeclineLicense.selectedIndex, gTest.expectedRadioGroupSelectedIndex, |
michael@0 | 677 | "Checking license radiogroup selectedIndex equals " + |
michael@0 | 678 | gTest.expectedRadioGroupSelectedIndex); |
michael@0 | 679 | } |
michael@0 | 680 | |
michael@0 | 681 | /** |
michael@0 | 682 | * Checks that only incompatible add-ons (e.g. noupdate_X add-ons) that don't |
michael@0 | 683 | * have an update are listed in the add-ons incompatible list. |
michael@0 | 684 | */ |
michael@0 | 685 | function checkIncompatbleList() { |
michael@0 | 686 | for (let i = 0; i < gIncompatibleListbox.itemCount; i++) { |
michael@0 | 687 | let label = gIncompatibleListbox.getItemAtIndex(i).label; |
michael@0 | 688 | // Use indexOf since locales can change the text displayed |
michael@0 | 689 | ok(label.indexOf("noupdate") != -1, "Checking that only incompatible " + |
michael@0 | 690 | "add-ons that don't have an update are listed in the incompatible list"); |
michael@0 | 691 | } |
michael@0 | 692 | } |
michael@0 | 693 | |
michael@0 | 694 | /** |
michael@0 | 695 | * Compares the return value of prefHasUserValue for the preference specified in |
michael@0 | 696 | * gPrefToCheck with the value passed in the aPrefHasValue parameter or the |
michael@0 | 697 | * value specified in the current test's prefHasUserValue property if |
michael@0 | 698 | * aPrefHasValue is undefined. |
michael@0 | 699 | * |
michael@0 | 700 | * @param aPrefHasValue (optional) |
michael@0 | 701 | * The expected value returned from prefHasUserValue for the preference |
michael@0 | 702 | * specified in gPrefToCheck. If aPrefHasValue is undefined the value |
michael@0 | 703 | * of the current test's prefHasUserValue property will be used. |
michael@0 | 704 | */ |
michael@0 | 705 | function checkPrefHasUserValue(aPrefHasValue) { |
michael@0 | 706 | let prefHasUserValue = aPrefHasValue === undefined ? gTest.prefHasUserValue |
michael@0 | 707 | : aPrefHasValue; |
michael@0 | 708 | is(Services.prefs.prefHasUserValue(gPrefToCheck), prefHasUserValue, |
michael@0 | 709 | "Checking prefHasUserValue for preference " + gPrefToCheck + " equals " + |
michael@0 | 710 | (prefHasUserValue ? "true" : "false")); |
michael@0 | 711 | } |
michael@0 | 712 | |
michael@0 | 713 | /** |
michael@0 | 714 | * Checks whether the link is hidden (general background update check error or |
michael@0 | 715 | * a certificate attribute check error with an update) or not (certificate |
michael@0 | 716 | * attribute check error without an update) on the errorextra page and that the |
michael@0 | 717 | * app.update.cert.errors and app.update.backgroundErrors preferences do not |
michael@0 | 718 | & have a user value. |
michael@0 | 719 | * |
michael@0 | 720 | * @param aShouldBeHidden (optional) |
michael@0 | 721 | * The expected value for the label's hidden attribute for the link. If |
michael@0 | 722 | * aShouldBeHidden is undefined the value of the current test's |
michael@0 | 723 | * shouldBeHidden property will be used. |
michael@0 | 724 | */ |
michael@0 | 725 | function checkErrorExtraPage(aShouldBeHidden) { |
michael@0 | 726 | let shouldBeHidden = aShouldBeHidden === undefined ? gTest.shouldBeHidden |
michael@0 | 727 | : aShouldBeHidden; |
michael@0 | 728 | is(gWin.document.getElementById("errorExtraLinkLabel").hidden, shouldBeHidden, |
michael@0 | 729 | "Checking errorExtraLinkLabel hidden attribute equals " + |
michael@0 | 730 | (shouldBeHidden ? "true" : "false")); |
michael@0 | 731 | |
michael@0 | 732 | is(gWin.document.getElementById(gTest.displayedTextElem).hidden, false, |
michael@0 | 733 | "Checking " + gTest.displayedTextElem + " should not be hidden"); |
michael@0 | 734 | |
michael@0 | 735 | ok(!Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS), |
michael@0 | 736 | "Preference " + PREF_APP_UPDATE_CERT_ERRORS + " should not have a " + |
michael@0 | 737 | "user value"); |
michael@0 | 738 | |
michael@0 | 739 | ok(!Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS), |
michael@0 | 740 | "Preference " + PREF_APP_UPDATE_BACKGROUNDERRORS + " should not have a " + |
michael@0 | 741 | "user value"); |
michael@0 | 742 | } |
michael@0 | 743 | |
michael@0 | 744 | /** |
michael@0 | 745 | * Gets the update version info for the update url parameters to send to |
michael@0 | 746 | * update.sjs. |
michael@0 | 747 | * |
michael@0 | 748 | * @param aAppVersion (optional) |
michael@0 | 749 | * The application version for the update snippet. If not specified the |
michael@0 | 750 | * current application version will be used. |
michael@0 | 751 | * @param aPlatformVersion (optional) |
michael@0 | 752 | * The platform version for the update snippet. If not specified the |
michael@0 | 753 | * current platform version will be used. |
michael@0 | 754 | * @return The url parameters for the application and platform version to send |
michael@0 | 755 | * to update.sjs. |
michael@0 | 756 | */ |
michael@0 | 757 | function getVersionParams(aAppVersion, aPlatformVersion) { |
michael@0 | 758 | let appInfo = Services.appinfo; |
michael@0 | 759 | return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version) + |
michael@0 | 760 | "&platformVersion=" + (aPlatformVersion ? aPlatformVersion |
michael@0 | 761 | : appInfo.platformVersion); |
michael@0 | 762 | } |
michael@0 | 763 | |
michael@0 | 764 | /** |
michael@0 | 765 | * Gets an application version that is greater than the current application |
michael@0 | 766 | * version. The version is created by taking the first sequence from the current |
michael@0 | 767 | * application version and adding 1 to it. |
michael@0 | 768 | * |
michael@0 | 769 | * @return A version string greater than the current application version string. |
michael@0 | 770 | */ |
michael@0 | 771 | function getNewerAppVersion() { |
michael@0 | 772 | let appVersion = Services.appinfo.version.split(".")[0]; |
michael@0 | 773 | appVersion++; |
michael@0 | 774 | return appVersion; |
michael@0 | 775 | } |
michael@0 | 776 | |
michael@0 | 777 | /** |
michael@0 | 778 | * Gets a platform version that is greater than the current platform version. |
michael@0 | 779 | * The version is created by taking the first sequence from the current platform |
michael@0 | 780 | * version and adding 1 to it. |
michael@0 | 781 | * |
michael@0 | 782 | * @return A version string greater than the current platform version string. |
michael@0 | 783 | */ |
michael@0 | 784 | function getNewerPlatformVersion() { |
michael@0 | 785 | let platformVersion = Services.appinfo.platformVersion.split(".")[0]; |
michael@0 | 786 | platformVersion++; |
michael@0 | 787 | return platformVersion; |
michael@0 | 788 | } |
michael@0 | 789 | |
michael@0 | 790 | /** |
michael@0 | 791 | * Verifies that all tests ran. |
michael@0 | 792 | */ |
michael@0 | 793 | function verifyTestsRan() { |
michael@0 | 794 | debugDump("entering"); |
michael@0 | 795 | |
michael@0 | 796 | // Return early if there are no tests defined. |
michael@0 | 797 | if (!TESTS) { |
michael@0 | 798 | return; |
michael@0 | 799 | } |
michael@0 | 800 | |
michael@0 | 801 | gTestCounter = -1; |
michael@0 | 802 | for (let i = 0; i < TESTS.length; ++i) { |
michael@0 | 803 | gTestCounter++; |
michael@0 | 804 | let test = TESTS[i]; |
michael@0 | 805 | let msg = "Checking if TESTS[" + i + "] test was performed... " + |
michael@0 | 806 | "callback function name = " + gCallback.name + ", " + |
michael@0 | 807 | "pageid = " + test.pageid; |
michael@0 | 808 | ok(test.ranTest, msg); |
michael@0 | 809 | } |
michael@0 | 810 | } |
michael@0 | 811 | |
michael@0 | 812 | /** |
michael@0 | 813 | * Creates a backup of files the tests need to modify so they can be restored to |
michael@0 | 814 | * the original file when the test has finished and then modifies the files. |
michael@0 | 815 | */ |
michael@0 | 816 | function setupFiles() { |
michael@0 | 817 | // Backup the updater-settings.ini file if it exists by moving it. |
michael@0 | 818 | let baseAppDir = getAppBaseDir(); |
michael@0 | 819 | let updateSettingsIni = baseAppDir.clone(); |
michael@0 | 820 | updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI); |
michael@0 | 821 | if (updateSettingsIni.exists()) { |
michael@0 | 822 | updateSettingsIni.moveTo(baseAppDir, FILE_UPDATE_SETTINGS_INI_BAK); |
michael@0 | 823 | } |
michael@0 | 824 | updateSettingsIni = baseAppDir.clone(); |
michael@0 | 825 | updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI); |
michael@0 | 826 | writeFile(updateSettingsIni, UPDATE_SETTINGS_CONTENTS); |
michael@0 | 827 | } |
michael@0 | 828 | |
michael@0 | 829 | /** |
michael@0 | 830 | * Sets the most common preferences used by tests to values used by the majority |
michael@0 | 831 | * of the tests and when necessary saves the preference's original values if |
michael@0 | 832 | * present so they can be set back to the original values when the test has |
michael@0 | 833 | * finished. |
michael@0 | 834 | */ |
michael@0 | 835 | function setupPrefs() { |
michael@0 | 836 | if (DEBUG_AUS_TEST) { |
michael@0 | 837 | Services.prefs.setBoolPref(PREF_APP_UPDATE_LOG, true); |
michael@0 | 838 | } |
michael@0 | 839 | |
michael@0 | 840 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) { |
michael@0 | 841 | gAppUpdateURL = Services.prefs.getCharPref(PREF_APP_UPDATE_URL_OVERRIDE); |
michael@0 | 842 | } |
michael@0 | 843 | |
michael@0 | 844 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ENABLED)) { |
michael@0 | 845 | gAppUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED); |
michael@0 | 846 | } |
michael@0 | 847 | Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true); |
michael@0 | 848 | |
michael@0 | 849 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_METRO_ENABLED)) { |
michael@0 | 850 | gAppUpdateMetroEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_METRO_ENABLED); |
michael@0 | 851 | } |
michael@0 | 852 | Services.prefs.setBoolPref(PREF_APP_UPDATE_METRO_ENABLED, true); |
michael@0 | 853 | |
michael@0 | 854 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ENABLED)) { |
michael@0 | 855 | gAppUpdateServiceEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED); |
michael@0 | 856 | } |
michael@0 | 857 | Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, false); |
michael@0 | 858 | |
michael@0 | 859 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_STAGING_ENABLED)) { |
michael@0 | 860 | gAppUpdateStagingEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED); |
michael@0 | 861 | } |
michael@0 | 862 | Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false); |
michael@0 | 863 | |
michael@0 | 864 | if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_UPDATE_URL)) { |
michael@0 | 865 | gExtUpdateURL = Services.prefs.getCharPref(PREF_EXTENSIONS_UPDATE_URL); |
michael@0 | 866 | } |
michael@0 | 867 | let extUpdateUrl = URL_HTTP_UPDATE_XML + "?addonID=%ITEM_ID%" + |
michael@0 | 868 | "&platformVersion=" + getNewerPlatformVersion(); |
michael@0 | 869 | Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, extUpdateUrl); |
michael@0 | 870 | |
michael@0 | 871 | Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0); |
michael@0 | 872 | Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0); |
michael@0 | 873 | Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true); |
michael@0 | 874 | Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix" + ADDON_ID_SUFFIX); |
michael@0 | 875 | } |
michael@0 | 876 | |
michael@0 | 877 | /** |
michael@0 | 878 | * Restores files that were backed up for the tests and general file cleanup. |
michael@0 | 879 | */ |
michael@0 | 880 | function resetFiles() { |
michael@0 | 881 | // Restore the backed up updater-settings.ini if it exists. |
michael@0 | 882 | let baseAppDir = getAppBaseDir(); |
michael@0 | 883 | let updateSettingsIni = baseAppDir.clone(); |
michael@0 | 884 | updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI_BAK); |
michael@0 | 885 | if (updateSettingsIni.exists()) { |
michael@0 | 886 | updateSettingsIni.moveTo(baseAppDir, FILE_UPDATE_SETTINGS_INI); |
michael@0 | 887 | } |
michael@0 | 888 | |
michael@0 | 889 | // Not being able to remove the "updated" directory will not adversely affect |
michael@0 | 890 | // subsequent tests so wrap it in a try block and don't test whether its |
michael@0 | 891 | // removal was successful. |
michael@0 | 892 | let updatedDir = getUpdatedDir(); |
michael@0 | 893 | if (updatedDir.exists()) { |
michael@0 | 894 | try { |
michael@0 | 895 | removeDirRecursive(updatedDir); |
michael@0 | 896 | } |
michael@0 | 897 | catch (e) { |
michael@0 | 898 | dump("Unable to remove directory\n" + |
michael@0 | 899 | "path: " + updatedDir.path + "\n" + |
michael@0 | 900 | "Exception: " + e + "\n"); |
michael@0 | 901 | } |
michael@0 | 902 | } |
michael@0 | 903 | } |
michael@0 | 904 | |
michael@0 | 905 | /** |
michael@0 | 906 | * Resets the most common preferences used by tests to their original values. |
michael@0 | 907 | */ |
michael@0 | 908 | function resetPrefs() { |
michael@0 | 909 | if (gAppUpdateURL !== undefined) { |
michael@0 | 910 | Services.prefs.setCharPref(PREF_APP_UPDATE_URL_OVERRIDE, gAppUpdateURL); |
michael@0 | 911 | } |
michael@0 | 912 | else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) { |
michael@0 | 913 | Services.prefs.clearUserPref(PREF_APP_UPDATE_URL_OVERRIDE); |
michael@0 | 914 | } |
michael@0 | 915 | |
michael@0 | 916 | if (gAppUpdateURLDefault) { |
michael@0 | 917 | gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_URL, gAppUpdateURLDefault); |
michael@0 | 918 | } |
michael@0 | 919 | |
michael@0 | 920 | if (gAppUpdateEnabled !== undefined) { |
michael@0 | 921 | Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, gAppUpdateEnabled); |
michael@0 | 922 | } |
michael@0 | 923 | else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ENABLED)) { |
michael@0 | 924 | Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED); |
michael@0 | 925 | } |
michael@0 | 926 | |
michael@0 | 927 | if (gAppUpdateMetroEnabled !== undefined) { |
michael@0 | 928 | Services.prefs.setBoolPref(PREF_APP_UPDATE_METRO_ENABLED, gAppUpdateMetroEnabled); |
michael@0 | 929 | } |
michael@0 | 930 | else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_METRO_ENABLED)) { |
michael@0 | 931 | Services.prefs.clearUserPref(PREF_APP_UPDATE_METRO_ENABLED); |
michael@0 | 932 | } |
michael@0 | 933 | |
michael@0 | 934 | if (gAppUpdateServiceEnabled !== undefined) { |
michael@0 | 935 | Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, gAppUpdateServiceEnabled); |
michael@0 | 936 | } |
michael@0 | 937 | else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ENABLED)) { |
michael@0 | 938 | Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ENABLED); |
michael@0 | 939 | } |
michael@0 | 940 | |
michael@0 | 941 | if (gAppUpdateStagingEnabled !== undefined) { |
michael@0 | 942 | Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, gAppUpdateStagingEnabled); |
michael@0 | 943 | } |
michael@0 | 944 | else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_STAGING_ENABLED)) { |
michael@0 | 945 | Services.prefs.clearUserPref(PREF_APP_UPDATE_STAGING_ENABLED); |
michael@0 | 946 | } |
michael@0 | 947 | |
michael@0 | 948 | if (gExtUpdateURL !== undefined) { |
michael@0 | 949 | Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, gExtUpdateURL); |
michael@0 | 950 | } |
michael@0 | 951 | else if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_UPDATE_URL)) { |
michael@0 | 952 | Services.prefs.clearUserPref(PREF_EXTENSIONS_UPDATE_URL); |
michael@0 | 953 | } |
michael@0 | 954 | |
michael@0 | 955 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_IDLETIME)) { |
michael@0 | 956 | Services.prefs.clearUserPref(PREF_APP_UPDATE_IDLETIME); |
michael@0 | 957 | } |
michael@0 | 958 | |
michael@0 | 959 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_PROMPTWAITTIME)) { |
michael@0 | 960 | Services.prefs.clearUserPref(PREF_APP_UPDATE_PROMPTWAITTIME); |
michael@0 | 961 | } |
michael@0 | 962 | |
michael@0 | 963 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_DETAILS)) { |
michael@0 | 964 | Services.prefs.clearUserPref(PREF_APP_UPDATE_URL_DETAILS); |
michael@0 | 965 | } |
michael@0 | 966 | |
michael@0 | 967 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SHOW_INSTALLED_UI)) { |
michael@0 | 968 | Services.prefs.clearUserPref(PREF_APP_UPDATE_SHOW_INSTALLED_UI); |
michael@0 | 969 | } |
michael@0 | 970 | |
michael@0 | 971 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED)) { |
michael@0 | 972 | Services.prefs.clearUserPref(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED); |
michael@0 | 973 | } |
michael@0 | 974 | |
michael@0 | 975 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LOG)) { |
michael@0 | 976 | Services.prefs.clearUserPref(PREF_APP_UPDATE_LOG); |
michael@0 | 977 | } |
michael@0 | 978 | |
michael@0 | 979 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS)) { |
michael@0 | 980 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_ERRORS); |
michael@0 | 981 | } |
michael@0 | 982 | |
michael@0 | 983 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_MAXERRORS)) { |
michael@0 | 984 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_MAXERRORS); |
michael@0 | 985 | } |
michael@0 | 986 | |
michael@0 | 987 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS)) { |
michael@0 | 988 | Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS); |
michael@0 | 989 | } |
michael@0 | 990 | |
michael@0 | 991 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDMAXERRORS)) { |
michael@0 | 992 | Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDMAXERRORS); |
michael@0 | 993 | } |
michael@0 | 994 | |
michael@0 | 995 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME)) { |
michael@0 | 996 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME); |
michael@0 | 997 | } |
michael@0 | 998 | |
michael@0 | 999 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_REQUIREBUILTIN)) { |
michael@0 | 1000 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_REQUIREBUILTIN); |
michael@0 | 1001 | } |
michael@0 | 1002 | |
michael@0 | 1003 | if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_CHECKATTRS)) { |
michael@0 | 1004 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_CHECKATTRS); |
michael@0 | 1005 | } |
michael@0 | 1006 | |
michael@0 | 1007 | try { |
michael@0 | 1008 | CERT_ATTRS.forEach(function(aCertAttrName) { |
michael@0 | 1009 | Services.prefs.clearUserPref(PREF_APP_UPDATE_CERTS_BRANCH + "1." + |
michael@0 | 1010 | aCertAttrName); |
michael@0 | 1011 | }); |
michael@0 | 1012 | } |
michael@0 | 1013 | catch (e) { |
michael@0 | 1014 | } |
michael@0 | 1015 | |
michael@0 | 1016 | try { |
michael@0 | 1017 | Services.prefs.deleteBranch(PREF_APP_UPDATE_NEVER_BRANCH); |
michael@0 | 1018 | } |
michael@0 | 1019 | catch(e) { |
michael@0 | 1020 | } |
michael@0 | 1021 | |
michael@0 | 1022 | if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) { |
michael@0 | 1023 | Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT); |
michael@0 | 1024 | } |
michael@0 | 1025 | |
michael@0 | 1026 | if (Services.prefs.prefHasUserValue(PREF_EM_HOTFIX_ID)) { |
michael@0 | 1027 | Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID); |
michael@0 | 1028 | } |
michael@0 | 1029 | } |
michael@0 | 1030 | |
michael@0 | 1031 | function setupTimer(aTestTimeout) { |
michael@0 | 1032 | gTestTimeout = aTestTimeout; |
michael@0 | 1033 | if (gTimeoutTimer) { |
michael@0 | 1034 | gTimeoutTimer.cancel(); |
michael@0 | 1035 | gTimeoutTimer = null; |
michael@0 | 1036 | } |
michael@0 | 1037 | gTimeoutTimer = AUS_Cc["@mozilla.org/timer;1"]. |
michael@0 | 1038 | createInstance(AUS_Ci.nsITimer); |
michael@0 | 1039 | gTimeoutTimer.initWithCallback(finishTestTimeout, gTestTimeout, |
michael@0 | 1040 | AUS_Ci.nsITimer.TYPE_ONE_SHOT); |
michael@0 | 1041 | } |
michael@0 | 1042 | |
michael@0 | 1043 | /** |
michael@0 | 1044 | * Disables pre-existing add-ons so they don't interfere with the tests, |
michael@0 | 1045 | * installs the test add-ons, sets the noupdate test add-ons' userDisabled value |
michael@0 | 1046 | * for the test, and calls the callback specified in the aCallback parameter. If |
michael@0 | 1047 | * the app.update.test.disabledAddons has a user value then setting the noupdate |
michael@0 | 1048 | * test add-ons' userDisabled value for the test is the only thing that is done. |
michael@0 | 1049 | * |
michael@0 | 1050 | * @param aCallback |
michael@0 | 1051 | * A callback to call after all operations have completed. |
michael@0 | 1052 | */ |
michael@0 | 1053 | function setupAddons(aCallback) { |
michael@0 | 1054 | debugDump("entering"); |
michael@0 | 1055 | |
michael@0 | 1056 | // Sets the appropriate userDisabled value for the noupdate test add-ons based |
michael@0 | 1057 | // on the value of gDisableNoUpdateAddon and calls the callback specified in |
michael@0 | 1058 | // setupAddons aCallback parameter. |
michael@0 | 1059 | function setNoUpdateAddonsDisabledState() { |
michael@0 | 1060 | AddonManager.getAllAddons(function(aAddons) { |
michael@0 | 1061 | aAddons.forEach(function(aAddon) { |
michael@0 | 1062 | if (aAddon.name.indexOf("noupdate") != 0) |
michael@0 | 1063 | return; |
michael@0 | 1064 | |
michael@0 | 1065 | if (gDisableNoUpdateAddon) { |
michael@0 | 1066 | if (!aAddon.userDisabled) { |
michael@0 | 1067 | aAddon.userDisabled = true; |
michael@0 | 1068 | } |
michael@0 | 1069 | } |
michael@0 | 1070 | else { |
michael@0 | 1071 | if (aAddon.userDisabled) { |
michael@0 | 1072 | aAddon.userDisabled = false; |
michael@0 | 1073 | } |
michael@0 | 1074 | } |
michael@0 | 1075 | }); |
michael@0 | 1076 | // Start the timout timer before the update window is displayed so it can |
michael@0 | 1077 | // clean up tests that don't successfully display the update window. |
michael@0 | 1078 | setupTimer(gTestTimeout); |
michael@0 | 1079 | aCallback(); |
michael@0 | 1080 | }); |
michael@0 | 1081 | } |
michael@0 | 1082 | |
michael@0 | 1083 | // If the app.update.test.disabledAddons preference exists the pre-existing |
michael@0 | 1084 | // add-ons have already been disabled so they don't interfere with the tests, |
michael@0 | 1085 | // the test add-ons have already been installed, and the only thing that needs |
michael@0 | 1086 | // to be done is setting the appropriate userDisabled value for the noupdate |
michael@0 | 1087 | // test add-ons. |
michael@0 | 1088 | if (Services.prefs.prefHasUserValue(PREF_DISABLEDADDONS)) { |
michael@0 | 1089 | setNoUpdateAddonsDisabledState(); |
michael@0 | 1090 | return; |
michael@0 | 1091 | } |
michael@0 | 1092 | |
michael@0 | 1093 | // Disable all pre-existing enabled addons so they don't interfere with the |
michael@0 | 1094 | // tests. |
michael@0 | 1095 | AddonManager.getAllAddons(function(aAddons) { |
michael@0 | 1096 | let disabledAddons = []; |
michael@0 | 1097 | aAddons.forEach(function(aAddon) { |
michael@0 | 1098 | // If an addon's type equals plugin it is skipped since |
michael@0 | 1099 | // checking plugins compatibility information isn't supported at this |
michael@0 | 1100 | // time (also see bug 566787). Also, SCOPE_APPLICATION add-ons are |
michael@0 | 1101 | // excluded by app update so there is no reason to disable them. |
michael@0 | 1102 | if (aAddon.type != "plugin" && !aAddon.appDisabled && |
michael@0 | 1103 | !aAddon.userDisabled && |
michael@0 | 1104 | aAddon.scope != AddonManager.SCOPE_APPLICATION) { |
michael@0 | 1105 | disabledAddons.push(aAddon); |
michael@0 | 1106 | aAddon.userDisabled = true; |
michael@0 | 1107 | } |
michael@0 | 1108 | }); |
michael@0 | 1109 | // If there are no pre-existing add-ons the preference value will be an |
michael@0 | 1110 | // empty string. |
michael@0 | 1111 | Services.prefs.setCharPref(PREF_DISABLEDADDONS, disabledAddons.join(" ")); |
michael@0 | 1112 | |
michael@0 | 1113 | // Install the test add-ons. |
michael@0 | 1114 | let xpiFiles = getTestAddonXPIFiles(); |
michael@0 | 1115 | let xpiCount = xpiFiles.length; |
michael@0 | 1116 | let installs = []; |
michael@0 | 1117 | xpiFiles.forEach(function(aFile) { |
michael@0 | 1118 | AddonManager.getInstallForFile(aFile, function(aInstall) { |
michael@0 | 1119 | if (!aInstall) { |
michael@0 | 1120 | throw "No AddonInstall created for " + aFile.path; |
michael@0 | 1121 | } |
michael@0 | 1122 | |
michael@0 | 1123 | installs.push(aInstall); |
michael@0 | 1124 | |
michael@0 | 1125 | if (--xpiCount == 0) { |
michael@0 | 1126 | let installCount = installs.length; |
michael@0 | 1127 | function installCompleted(aInstall) { |
michael@0 | 1128 | aInstall.removeListener(listener); |
michael@0 | 1129 | |
michael@0 | 1130 | if (getAddonTestType(aInstall.addon.name) == "userdisabled") { |
michael@0 | 1131 | aInstall.addon.userDisabled = true; |
michael@0 | 1132 | } |
michael@0 | 1133 | if (--installCount == 0) { |
michael@0 | 1134 | setNoUpdateAddonsDisabledState(); |
michael@0 | 1135 | } |
michael@0 | 1136 | } |
michael@0 | 1137 | |
michael@0 | 1138 | let listener = { |
michael@0 | 1139 | onDownloadFailed: installCompleted, |
michael@0 | 1140 | onDownloadCancelled: installCompleted, |
michael@0 | 1141 | onInstallFailed: installCompleted, |
michael@0 | 1142 | onInstallCancelled: installCompleted, |
michael@0 | 1143 | onInstallEnded: installCompleted |
michael@0 | 1144 | }; |
michael@0 | 1145 | |
michael@0 | 1146 | installs.forEach(function(aInstall) { |
michael@0 | 1147 | aInstall.addListener(listener); |
michael@0 | 1148 | aInstall.install(); |
michael@0 | 1149 | }); |
michael@0 | 1150 | } |
michael@0 | 1151 | }); |
michael@0 | 1152 | }); |
michael@0 | 1153 | }); |
michael@0 | 1154 | } |
michael@0 | 1155 | |
michael@0 | 1156 | /** |
michael@0 | 1157 | * Uninstalls the test add-ons, enables add-ons that were disabled when the |
michael@0 | 1158 | * test started, and calls the callback specified in the aCallback parameter. |
michael@0 | 1159 | * |
michael@0 | 1160 | * @param aCallback |
michael@0 | 1161 | * A callback to call after all operations have completed. |
michael@0 | 1162 | */ |
michael@0 | 1163 | function resetAddons(aCallback) { |
michael@0 | 1164 | debugDump("entering"); |
michael@0 | 1165 | // If test_9999_cleanup.xul is ran by itself then the test add-ons will not |
michael@0 | 1166 | // have been installed and any pre-existing add-ons will not have been |
michael@0 | 1167 | // disabled so return early. |
michael@0 | 1168 | if (!Services.prefs.prefHasUserValue(PREF_DISABLEDADDONS)) { |
michael@0 | 1169 | debugDump("preference " + PREF_DISABLEDADDONS + " doesn't exist... " + |
michael@0 | 1170 | "returning early"); |
michael@0 | 1171 | aCallback(); |
michael@0 | 1172 | return; |
michael@0 | 1173 | } |
michael@0 | 1174 | |
michael@0 | 1175 | // Uninstall the test add-ons. |
michael@0 | 1176 | let count = TEST_ADDONS.length; |
michael@0 | 1177 | function uninstallCompleted(aAddon) { |
michael@0 | 1178 | if (--count == 0) { |
michael@0 | 1179 | AddonManager.removeAddonListener(listener); |
michael@0 | 1180 | |
michael@0 | 1181 | // Enable the pre-existing add-ons that were disabled so they wouldn't |
michael@0 | 1182 | // interfere with the tests. |
michael@0 | 1183 | let disabledAddons = Services.prefs.getCharPref(PREF_DISABLEDADDONS).split(" "); |
michael@0 | 1184 | Services.prefs.clearUserPref(PREF_DISABLEDADDONS); |
michael@0 | 1185 | AddonManager.getAllAddons(function(aAddons) { |
michael@0 | 1186 | aAddons.forEach(function(aAddon) { |
michael@0 | 1187 | if (disabledAddons.indexOf(aAddon.id)) { |
michael@0 | 1188 | aAddon.userDisabled = false; |
michael@0 | 1189 | } |
michael@0 | 1190 | }); |
michael@0 | 1191 | aCallback(); |
michael@0 | 1192 | }); |
michael@0 | 1193 | } |
michael@0 | 1194 | } |
michael@0 | 1195 | |
michael@0 | 1196 | let listener = { |
michael@0 | 1197 | onUninstalled: uninstallCompleted |
michael@0 | 1198 | }; |
michael@0 | 1199 | |
michael@0 | 1200 | AddonManager.addAddonListener(listener); |
michael@0 | 1201 | TEST_ADDONS.forEach(function(aName) { |
michael@0 | 1202 | AddonManager.getAddonByID(aName + ADDON_ID_SUFFIX, function(aAddon) { |
michael@0 | 1203 | aAddon.uninstall(); |
michael@0 | 1204 | }); |
michael@0 | 1205 | }); |
michael@0 | 1206 | } |
michael@0 | 1207 | |
michael@0 | 1208 | /** |
michael@0 | 1209 | * Helper function to get the string before the '_' character in an add-on's |
michael@0 | 1210 | * name or id which is used to determine the add-on test type used by the tests. |
michael@0 | 1211 | * |
michael@0 | 1212 | * @param aName |
michael@0 | 1213 | * The test add-on's name or id. |
michael@0 | 1214 | * @return The string before the '_' character in the string passed in the aName |
michael@0 | 1215 | * parameter. |
michael@0 | 1216 | */ |
michael@0 | 1217 | function getAddonTestType(aName) { |
michael@0 | 1218 | return aName.split("_")[0]; |
michael@0 | 1219 | } |
michael@0 | 1220 | |
michael@0 | 1221 | /** |
michael@0 | 1222 | * Helper function to create add-on xpi files for the default test add-ons. |
michael@0 | 1223 | * |
michael@0 | 1224 | * @return An array with each member being an nsILocalFile for an add-on XPI |
michael@0 | 1225 | * file. |
michael@0 | 1226 | */ |
michael@0 | 1227 | function getTestAddonXPIFiles() { |
michael@0 | 1228 | let addonPrepDir = Services.dirsvc.get(NS_APP_USER_PROFILE_50_DIR, |
michael@0 | 1229 | AUS_Ci.nsILocalFile); |
michael@0 | 1230 | addonPrepDir.append(ADDON_PREP_DIR); |
michael@0 | 1231 | |
michael@0 | 1232 | let bootstrap = addonPrepDir.clone(); |
michael@0 | 1233 | bootstrap.append("bootstrap.js"); |
michael@0 | 1234 | // If a previous test has already created bootstrap.js don't create it again. |
michael@0 | 1235 | if (!bootstrap.exists()) { |
michael@0 | 1236 | let bootstrapContents = "function install(data, reason){ }\n" + |
michael@0 | 1237 | "function startup(data, reason){ }\n" + |
michael@0 | 1238 | "function shutdown(data, reason){ }\n" + |
michael@0 | 1239 | "function uninstall(data, reason){ }\n"; |
michael@0 | 1240 | writeFile(bootstrap, bootstrapContents); |
michael@0 | 1241 | } |
michael@0 | 1242 | |
michael@0 | 1243 | let installRDF = addonPrepDir.clone(); |
michael@0 | 1244 | installRDF.append("install.rdf"); |
michael@0 | 1245 | |
michael@0 | 1246 | let xpiFiles = []; |
michael@0 | 1247 | TEST_ADDONS.forEach(function(aName) { |
michael@0 | 1248 | let xpiFile = addonPrepDir.clone(); |
michael@0 | 1249 | xpiFile.append(aName + ".xpi"); |
michael@0 | 1250 | |
michael@0 | 1251 | if (installRDF.exists()) |
michael@0 | 1252 | installRDF.remove(false); |
michael@0 | 1253 | writeFile(installRDF, getInstallRDFString(aName)); |
michael@0 | 1254 | gZipW.open(xpiFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); |
michael@0 | 1255 | gZipW.addEntryFile(installRDF.leafName, |
michael@0 | 1256 | AUS_Ci.nsIZipWriter.COMPRESSION_DEFAULT, installRDF, |
michael@0 | 1257 | false); |
michael@0 | 1258 | gZipW.addEntryFile(bootstrap.leafName, |
michael@0 | 1259 | AUS_Ci.nsIZipWriter.COMPRESSION_DEFAULT, bootstrap, |
michael@0 | 1260 | false); |
michael@0 | 1261 | gZipW.close(); |
michael@0 | 1262 | xpiFiles.push(xpiFile); |
michael@0 | 1263 | }); |
michael@0 | 1264 | |
michael@0 | 1265 | return xpiFiles; |
michael@0 | 1266 | } |
michael@0 | 1267 | |
michael@0 | 1268 | /** |
michael@0 | 1269 | * Helper function to gets the string representation of the contents of the |
michael@0 | 1270 | * add-on's install.rdf file. |
michael@0 | 1271 | * |
michael@0 | 1272 | * @param aName |
michael@0 | 1273 | * The string to use for the add-on's name which is also used to |
michael@0 | 1274 | * construct the local-part in RFC 5322 format of the add-on's ID. |
michael@0 | 1275 | * @return A string representation of the contents of the add-on's install.rdf |
michael@0 | 1276 | * file. |
michael@0 | 1277 | */ |
michael@0 | 1278 | function getInstallRDFString(aName) { |
michael@0 | 1279 | let maxVersion = Services.appinfo.platformVersion; |
michael@0 | 1280 | switch (getAddonTestType(aName)) { |
michael@0 | 1281 | case "compatible": |
michael@0 | 1282 | maxVersion = getNewerPlatformVersion(); |
michael@0 | 1283 | break; |
michael@0 | 1284 | case "appdisabled": |
michael@0 | 1285 | maxVersion = "0.1"; |
michael@0 | 1286 | break; |
michael@0 | 1287 | } |
michael@0 | 1288 | |
michael@0 | 1289 | return "<?xml version=\"1.0\"?>\n" + |
michael@0 | 1290 | "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" + |
michael@0 | 1291 | " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" + |
michael@0 | 1292 | " <Description about=\"urn:mozilla:install-manifest\">\n" + |
michael@0 | 1293 | " <em:id>" + aName + ADDON_ID_SUFFIX + "</em:id>\n" + |
michael@0 | 1294 | " <em:version>1.0</em:version>\n" + |
michael@0 | 1295 | " <em:bootstrap>true</em:bootstrap>\n" + |
michael@0 | 1296 | " <em:name>" + aName + "</em:name>\n" + |
michael@0 | 1297 | " <em:description>Test Description</em:description>\n" + |
michael@0 | 1298 | " <em:targetApplication>\n" + |
michael@0 | 1299 | " <Description>\n" + |
michael@0 | 1300 | " <em:id>toolkit@mozilla.org</em:id>\n" + |
michael@0 | 1301 | " <em:minVersion>undefined</em:minVersion>\n" + |
michael@0 | 1302 | " <em:maxVersion>" + maxVersion + "</em:maxVersion>\n" + |
michael@0 | 1303 | " </Description>\n" + |
michael@0 | 1304 | " </em:targetApplication>\n" + |
michael@0 | 1305 | " </Description>\n" + |
michael@0 | 1306 | "</RDF>"; |
michael@0 | 1307 | } |
michael@0 | 1308 | |
michael@0 | 1309 | /** |
michael@0 | 1310 | * Closes the update window if it is open and causes the test to fail if an |
michael@0 | 1311 | * update window is found. |
michael@0 | 1312 | * |
michael@0 | 1313 | * @return true if an update window was found, otherwise false. |
michael@0 | 1314 | */ |
michael@0 | 1315 | function closeUpdateWindow() { |
michael@0 | 1316 | let updateWindow = getUpdateWindow(); |
michael@0 | 1317 | if (!updateWindow) |
michael@0 | 1318 | return false; |
michael@0 | 1319 | |
michael@0 | 1320 | ok(false, "Found an existing Update Window from the current or a previous " + |
michael@0 | 1321 | "test... attempting to close it."); |
michael@0 | 1322 | updateWindow.close(); |
michael@0 | 1323 | return true; |
michael@0 | 1324 | } |
michael@0 | 1325 | |
michael@0 | 1326 | /** |
michael@0 | 1327 | * Gets the update window. |
michael@0 | 1328 | * |
michael@0 | 1329 | * @return The nsIDOMWindow for the Update Window if it is open and null |
michael@0 | 1330 | * if it isn't. |
michael@0 | 1331 | */ |
michael@0 | 1332 | function getUpdateWindow() { |
michael@0 | 1333 | return Services.wm.getMostRecentWindow(UPDATE_WINDOW_NAME); |
michael@0 | 1334 | } |
michael@0 | 1335 | |
michael@0 | 1336 | /** |
michael@0 | 1337 | * Helper for background check errors. |
michael@0 | 1338 | */ |
michael@0 | 1339 | var errorsPrefObserver = { |
michael@0 | 1340 | observedPref: null, |
michael@0 | 1341 | maxErrorPref: null, |
michael@0 | 1342 | |
michael@0 | 1343 | /** |
michael@0 | 1344 | * Sets up a preference observer and sets the associated maximum errors |
michael@0 | 1345 | * preference used for background notification. |
michael@0 | 1346 | * |
michael@0 | 1347 | * @param aObservePref |
michael@0 | 1348 | * The preference to observe. |
michael@0 | 1349 | * @param aMaxErrorPref |
michael@0 | 1350 | * The maximum errors preference. |
michael@0 | 1351 | * @param aMaxErrorCount |
michael@0 | 1352 | * The value to set the app.update.cert.maxErrors preference to. |
michael@0 | 1353 | */ |
michael@0 | 1354 | init: function(aObservePref, aMaxErrorPref, aMaxErrorCount) { |
michael@0 | 1355 | this.observedPref = aObservePref; |
michael@0 | 1356 | this.maxErrorPref = aMaxErrorPref; |
michael@0 | 1357 | |
michael@0 | 1358 | let maxErrors = aMaxErrorCount ? aMaxErrorCount : 2; |
michael@0 | 1359 | Services.prefs.setIntPref(aMaxErrorPref, maxErrors); |
michael@0 | 1360 | Services.prefs.addObserver(aObservePref, this, false); |
michael@0 | 1361 | }, |
michael@0 | 1362 | |
michael@0 | 1363 | /** |
michael@0 | 1364 | * Preference observer for the preference specified in |this.observedPref|. |
michael@0 | 1365 | */ |
michael@0 | 1366 | observe: function XPI_observe(aSubject, aTopic, aData) { |
michael@0 | 1367 | if (aData == this.observedPref) { |
michael@0 | 1368 | let errCount = Services.prefs.getIntPref(this.observedPref); |
michael@0 | 1369 | let errMax = Services.prefs.getIntPref(this.maxErrorPref); |
michael@0 | 1370 | if (errCount >= errMax) { |
michael@0 | 1371 | debugDump("removing pref observer"); |
michael@0 | 1372 | Services.prefs.removeObserver(this.observedPref, this); |
michael@0 | 1373 | } |
michael@0 | 1374 | else { |
michael@0 | 1375 | debugDump("notifying AUS"); |
michael@0 | 1376 | SimpleTest.executeSoon(function() { |
michael@0 | 1377 | gAUS.notify(null); |
michael@0 | 1378 | }); |
michael@0 | 1379 | } |
michael@0 | 1380 | } |
michael@0 | 1381 | } |
michael@0 | 1382 | }; |
michael@0 | 1383 | |
michael@0 | 1384 | /** |
michael@0 | 1385 | * nsIObserver for receiving window open and close notifications. |
michael@0 | 1386 | */ |
michael@0 | 1387 | var gWindowObserver = { |
michael@0 | 1388 | observe: function WO_observe(aSubject, aTopic, aData) { |
michael@0 | 1389 | let win = aSubject.QueryInterface(AUS_Ci.nsIDOMEventTarget); |
michael@0 | 1390 | |
michael@0 | 1391 | if (aTopic == "domwindowclosed") { |
michael@0 | 1392 | if (win.location != URI_UPDATE_PROMPT_DIALOG) { |
michael@0 | 1393 | debugDump("domwindowclosed event for window not being tested - " + |
michael@0 | 1394 | "location: " + win.location + "... returning early"); |
michael@0 | 1395 | return; |
michael@0 | 1396 | } |
michael@0 | 1397 | // Allow tests the ability to provide their own function (it must be |
michael@0 | 1398 | // named finishTest) for finishing the test. |
michael@0 | 1399 | try { |
michael@0 | 1400 | finishTest(); |
michael@0 | 1401 | } |
michael@0 | 1402 | catch (e) { |
michael@0 | 1403 | finishTestDefault(); |
michael@0 | 1404 | } |
michael@0 | 1405 | return; |
michael@0 | 1406 | } |
michael@0 | 1407 | |
michael@0 | 1408 | win.addEventListener("load", function WO_observe_onLoad() { |
michael@0 | 1409 | win.removeEventListener("load", WO_observe_onLoad, false); |
michael@0 | 1410 | // Ignore windows other than the update UI window. |
michael@0 | 1411 | if (win.location != URI_UPDATE_PROMPT_DIALOG) { |
michael@0 | 1412 | debugDump("load event for window not being tested - location: " + |
michael@0 | 1413 | win.location + "... returning early"); |
michael@0 | 1414 | return; |
michael@0 | 1415 | } |
michael@0 | 1416 | |
michael@0 | 1417 | // The first wizard page should always be the dummy page. |
michael@0 | 1418 | let pageid = win.document.documentElement.currentPage.pageid; |
michael@0 | 1419 | if (pageid != PAGEID_DUMMY) { |
michael@0 | 1420 | // This should never happen but if it does this will provide a clue |
michael@0 | 1421 | // for diagnosing the cause. |
michael@0 | 1422 | ok(false, "Unexpected load event - pageid got: " + pageid + |
michael@0 | 1423 | ", expected: " + PAGEID_DUMMY + "... returning early"); |
michael@0 | 1424 | return; |
michael@0 | 1425 | } |
michael@0 | 1426 | |
michael@0 | 1427 | gWin = win; |
michael@0 | 1428 | gDocElem = gWin.document.documentElement; |
michael@0 | 1429 | gDocElem.addEventListener("pageshow", onPageShowDefault, false); |
michael@0 | 1430 | }, false); |
michael@0 | 1431 | } |
michael@0 | 1432 | }; |