toolkit/mozapps/update/tests/chrome/utils.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/mozapps/update/tests/chrome/utils.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1432 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 + * http://creativecommons.org/publicdomain/zero/1.0/
     1.6 + */
     1.7 +
     1.8 +/**
     1.9 + * Test Definition
    1.10 + *
    1.11 + * Most tests can use an array named TESTS that will perform most if not all of
    1.12 + * the necessary checks. Each element in the array must be an object with the
    1.13 + * following possible properties. Additional properties besides the ones listed
    1.14 + * below can be added as needed.
    1.15 + *
    1.16 + * overrideCallback (optional)
    1.17 + *   The function to call for the next test. This is typically called when the
    1.18 + *   wizard page changes but can also be called for other events by the previous
    1.19 + *   test. If this property isn't defined then the defailtCallback function will
    1.20 + *   be called. If this property is defined then all other properties are
    1.21 + *   optional.
    1.22 + *
    1.23 + * pageid (required unless overrideCallback is specified)
    1.24 + *   The expected pageid for the wizard. This property is required unless the
    1.25 + *   overrideCallback property is defined.
    1.26 + *
    1.27 + * extraStartFunction (optional)
    1.28 + *   The function to call at the beginning of the defaultCallback function. If
    1.29 + *   the function returns true the defaultCallback function will return early
    1.30 + *   which allows waiting for a specific condition to be evaluated in the
    1.31 + *   function specified in the extraStartFunction property before continuing
    1.32 + *   with the test.
    1.33 + *
    1.34 + * extraCheckFunction (optional)
    1.35 + *   The function to call to perform extra checks in the defaultCallback
    1.36 + *   function.
    1.37 + *
    1.38 + * extraDelayedCheckFunction (optional)
    1.39 + *   The function to call to perform extra checks in the delayedDefaultCallback
    1.40 + *   function.
    1.41 + *
    1.42 + * buttonStates (optional)
    1.43 + *   A javascript object representing the expected hidden and disabled attribute
    1.44 + *   values for the buttons of the current wizard page. The values are checked
    1.45 + *   in the delayedDefaultCallback function. For information about the structure
    1.46 + *   of this object refer to the getExpectedButtonStates and checkButtonStates
    1.47 + *   functions.
    1.48 + *
    1.49 + * buttonClick (optional)
    1.50 + *   The current wizard page button to click at the end of the
    1.51 + *   delayedDefaultCallback function. If the buttonClick property is defined
    1.52 + *   then the extraDelayedFinishFunction property can't be specified due to race
    1.53 + *   conditions in some of the tests and if both of them are specified the test
    1.54 + *   will intentionally throw.
    1.55 + *
    1.56 + * extraDelayedFinishFunction (optional)
    1.57 + *   The function to call at the end of the delayedDefaultCallback function.
    1.58 + *   If the extraDelayedFinishFunction property is defined then the buttonClick
    1.59 + *   property can't be specified due to race conditions in some of the tests and
    1.60 + *   if both of them are specified the test will intentionally throw.
    1.61 + *
    1.62 + * ranTest (should not be specified)
    1.63 + *   When delayedDefaultCallback is called a property named ranTest is added to
    1.64 + *   the current test so it is possible to verify that each test in the TESTS
    1.65 + *   array has ran.
    1.66 + *
    1.67 + * prefHasUserValue (optional)
    1.68 + *   For comparing the expected value defined by this property with the return
    1.69 + *   value of prefHasUserValue using gPrefToCheck for the preference name in the
    1.70 + *   checkPrefHasUserValue function.
    1.71 + *
    1.72 + * expectedRadioGroupSelectedIndex (optional)
    1.73 + *   For comparing the expected selectedIndex attribute value of the wizard's
    1.74 + *   license page radiogroup selectedIndex attribute in the
    1.75 + *   checkRadioGroupSelectedIndex function.
    1.76 + *
    1.77 + * expectedRemoteContentState (optional)
    1.78 + *   For comparing the expected remotecontent state attribute value of the
    1.79 + *   wizard's billboard and license pages in the checkRemoteContentState and
    1.80 + *   waitForRemoteContentLoaded functions.
    1.81 + *
    1.82 + *
    1.83 + * Test Add-ons
    1.84 + *
    1.85 + * All tests include the test add-ons specified in the TEST_ADDONS array and
    1.86 + * the only thing that can be configured is whether the noupdate test add-on is
    1.87 + * disabled (see below). The add-on names are in the format of typename_X where
    1.88 + * X is a number to make the add-on ID unique and typename is one of the values
    1.89 + * specified below:
    1.90 + *
    1.91 + * appdisabled
    1.92 + *   disabled by the application due to being incompatible with the current
    1.93 + *   toolkit version.
    1.94 + *
    1.95 + * compatible
    1.96 + *   compatible with the current toolkit version and the update's toolkit
    1.97 + *   version.
    1.98 + *
    1.99 + * noupdate
   1.100 + *   the add-on is compatible with the current toolkit version and does not have
   1.101 + *   an update to make it compatible with the update's toolkit version. Tests
   1.102 + *   that need to have all add-ons compatible for the application update can
   1.103 + *   disable this add-on by setting the gDisableNoUpdateAddon variable to true.
   1.104 + *
   1.105 + * updatecompatibility
   1.106 + *   the add-on is compatible with the current toolkit version and has a
   1.107 + *   compatibility update to make it compatible with the update's toolkit
   1.108 + *   version.
   1.109 + *
   1.110 + * updateversion
   1.111 + *   the add-on is compatible with the current toolkit version and has a version
   1.112 + *   update to make it compatible with the update's toolkit version.
   1.113 + *
   1.114 + * userdisabled
   1.115 + *   disabled by the user and compatible with the current toolkit version but
   1.116 + *   not the update's toolkit version. This add-on will be disabled after its
   1.117 + *   install completes.
   1.118 + */
   1.119 +
   1.120 +Components.utils.import("resource://gre/modules/AddonManager.jsm");
   1.121 +
   1.122 +// The tests have to use the pageid instead of the pageIndex due to the
   1.123 +// app update wizard's access method being random.
   1.124 +const PAGEID_DUMMY            = "dummy";                 // Done
   1.125 +const PAGEID_CHECKING         = "checking";              // Done
   1.126 +const PAGEID_PLUGIN_UPDATES   = "pluginupdatesfound";
   1.127 +const PAGEID_NO_UPDATES_FOUND = "noupdatesfound";        // Done
   1.128 +const PAGEID_MANUAL_UPDATE    = "manualUpdate"; // Tested on license load failure
   1.129 +const PAGEID_UNSUPPORTED      = "unsupported";           // Done
   1.130 +const PAGEID_INCOMPAT_CHECK   = "incompatibleCheck";     // Done
   1.131 +const PAGEID_FOUND_BASIC      = "updatesfoundbasic";     // Done
   1.132 +const PAGEID_FOUND_BILLBOARD  = "updatesfoundbillboard"; // Done
   1.133 +const PAGEID_LICENSE          = "license";               // Done
   1.134 +const PAGEID_INCOMPAT_LIST    = "incompatibleList";      // Done
   1.135 +const PAGEID_DOWNLOADING      = "downloading";           // Done
   1.136 +const PAGEID_ERRORS           = "errors";                // Done
   1.137 +const PAGEID_ERROR_EXTRA      = "errorextra";            // Done
   1.138 +const PAGEID_ERROR_PATCHING   = "errorpatching";         // Done
   1.139 +const PAGEID_FINISHED         = "finished";              // Done
   1.140 +const PAGEID_FINISHED_BKGRD   = "finishedBackground";    // Done
   1.141 +const PAGEID_INSTALLED        = "installed";             // Done
   1.142 +
   1.143 +const UPDATE_WINDOW_NAME = "Update:Wizard";
   1.144 +
   1.145 +const URL_HOST = "http://example.com";
   1.146 +const URL_PATH_UPDATE_XML = "/chrome/toolkit/mozapps/update/tests/chrome/update.sjs";
   1.147 +const REL_PATH_DATA = "chrome/toolkit/mozapps/update/tests/data";
   1.148 +
   1.149 +const URL_HTTP_UPDATE_XML = URL_HOST + URL_PATH_UPDATE_XML;
   1.150 +const URL_HTTPS_UPDATE_XML = "https://example.com" + URL_PATH_UPDATE_XML;
   1.151 +
   1.152 +const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
   1.153 +
   1.154 +const ADDON_ID_SUFFIX = "@appupdatetest.mozilla.org";
   1.155 +const ADDON_PREP_DIR = "appupdateprep";
   1.156 +// Preference for storing add-ons that are disabled by the tests to prevent them
   1.157 +// from interefering with the tests.
   1.158 +const PREF_DISABLEDADDONS = "app.update.test.disabledAddons";
   1.159 +const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
   1.160 +const TEST_ADDONS = [ "appdisabled_1", "appdisabled_2",
   1.161 +                      "compatible_1", "compatible_2",
   1.162 +                      "noupdate_1", "noupdate_2",
   1.163 +                      "updatecompatibility_1", "updatecompatibility_2",
   1.164 +                      "updateversion_1", "updateversion_2",
   1.165 +                      "userdisabled_1", "userdisabled_2", "hotfix" ];
   1.166 +
   1.167 +var gURLData = URL_HOST + "/" + REL_PATH_DATA + "/";
   1.168 +
   1.169 +var gTestTimeout = 240000; // 4 minutes
   1.170 +var gTimeoutTimer;
   1.171 +
   1.172 +// The number of SimpleTest.executeSoon calls to perform when waiting on an
   1.173 +// update window to close before giving up.
   1.174 +const CLOSE_WINDOW_TIMEOUT_MAXCOUNT = 10;
   1.175 +// Counter for the SimpleTest.executeSoon when waiting on an update window to
   1.176 +// close before giving up.
   1.177 +var gCloseWindowTimeoutCounter = 0;
   1.178 +
   1.179 +// The following vars are for restoring previous preference values (if present)
   1.180 +// when the test finishes.
   1.181 +var gAppUpdateEnabled;            // app.update.enabled
   1.182 +var gAppUpdateMetroEnabled;       // app.update.metro.enabled
   1.183 +var gAppUpdateServiceEnabled;     // app.update.service.enabled
   1.184 +var gAppUpdateStagingEnabled;     // app.update.staging.enabled
   1.185 +var gAppUpdateURLDefault;         // app.update.url (default prefbranch)
   1.186 +var gAppUpdateURL;                // app.update.url.override
   1.187 +var gExtUpdateURL;                // extensions.update.url
   1.188 +
   1.189 +var gTestCounter = -1;
   1.190 +var gWin;
   1.191 +var gDocElem;
   1.192 +var gPrefToCheck;
   1.193 +var gDisableNoUpdateAddon = false;
   1.194 +
   1.195 +// Set to true to log additional information for debugging. To log additional
   1.196 +// information for an individual test set DEBUG_AUS_TEST to true in the test's
   1.197 +// onload function.
   1.198 +var DEBUG_AUS_TEST = true;
   1.199 +
   1.200 +#include ../shared.js
   1.201 +
   1.202 +/**
   1.203 + * The current test in TESTS array.
   1.204 + */
   1.205 +this.__defineGetter__("gTest", function() {
   1.206 +  return TESTS[gTestCounter];
   1.207 +});
   1.208 +
   1.209 +/**
   1.210 + * The current test's callback. This will either return the callback defined in
   1.211 + * the test's overrideCallback property or defaultCallback if the
   1.212 + * overrideCallback property is undefined.
   1.213 + */
   1.214 +this.__defineGetter__("gCallback", function() {
   1.215 +  return gTest.overrideCallback ? gTest.overrideCallback
   1.216 +                                : defaultCallback;
   1.217 +});
   1.218 +
   1.219 +/**
   1.220 + * The remotecontent element for the current page if one exists or null if a
   1.221 + * remotecontent element doesn't exist.
   1.222 + */
   1.223 +this.__defineGetter__("gRemoteContent", function() {
   1.224 +  switch (gTest.pageid) {
   1.225 +    case PAGEID_FOUND_BILLBOARD:
   1.226 +      return gWin.document.getElementById("updateMoreInfoContent");
   1.227 +    case PAGEID_LICENSE:
   1.228 +      return gWin.document.getElementById("licenseContent");
   1.229 +  }
   1.230 +  return null;
   1.231 +});
   1.232 +
   1.233 +/**
   1.234 + * The state for the remotecontent element if one exists or null if a
   1.235 + * remotecontent element doesn't exist.
   1.236 + */
   1.237 +this.__defineGetter__("gRemoteContentState", function() {
   1.238 +  if (gRemoteContent) {
   1.239 +    return gRemoteContent.getAttribute("state");
   1.240 +  }
   1.241 +  return null;
   1.242 +});
   1.243 +
   1.244 +/**
   1.245 + * The radiogroup for the license page.
   1.246 + */
   1.247 +this.__defineGetter__("gAcceptDeclineLicense", function() {
   1.248 +  return gWin.document.getElementById("acceptDeclineLicense");
   1.249 +});
   1.250 +
   1.251 +/**
   1.252 + * The listbox for the incompatibleList page.
   1.253 + */
   1.254 +this.__defineGetter__("gIncompatibleListbox", function() {
   1.255 +  return gWin.document.getElementById("incompatibleListbox");
   1.256 +});
   1.257 +
   1.258 +/**
   1.259 + * Default test run function that can be used by most tests. This function uses
   1.260 + * protective measures to prevent the test from failing provided by
   1.261 + * |runTestDefaultWaitForWindowClosed| helper functions to prevent failure due
   1.262 + * to a previous test failure.
   1.263 + */
   1.264 +function runTestDefault() {
   1.265 +  debugDump("entering");
   1.266 +
   1.267 +  if (!("@mozilla.org/zipwriter;1" in AUS_Cc)) {
   1.268 +    ok(false, "nsIZipWriter is required to run these tests");
   1.269 +    return;
   1.270 +  }
   1.271 +
   1.272 +  SimpleTest.waitForExplicitFinish();
   1.273 +
   1.274 +  runTestDefaultWaitForWindowClosed();
   1.275 +}
   1.276 +
   1.277 +/**
   1.278 + * If an update window is found SimpleTest.executeSoon can callback before the
   1.279 + * update window is fully closed especially with debug builds. If an update
   1.280 + * window is found this function will call itself using SimpleTest.executeSoon
   1.281 + * up to the amount declared in CLOSE_WINDOW_TIMEOUT_MAXCOUNT until the update
   1.282 + * window has closed before continuing the test.
   1.283 + */
   1.284 +function runTestDefaultWaitForWindowClosed() {
   1.285 +  gCloseWindowTimeoutCounter++;
   1.286 +  if (gCloseWindowTimeoutCounter > CLOSE_WINDOW_TIMEOUT_MAXCOUNT) {
   1.287 +    try {
   1.288 +      finishTest();
   1.289 +    }
   1.290 +    catch (e) {
   1.291 +      finishTestDefault();
   1.292 +    }
   1.293 +    return;
   1.294 +  }
   1.295 +
   1.296 +  // The update window should not be open at this time. If it is the call to
   1.297 +  // |closeUpdateWindow| will close it and cause the test to fail.
   1.298 +  if (closeUpdateWindow()) {
   1.299 +    SimpleTest.executeSoon(runTestDefaultWaitForWindowClosed);
   1.300 +  }
   1.301 +  else {
   1.302 +    Services.ww.registerNotification(gWindowObserver);
   1.303 +
   1.304 +    gCloseWindowTimeoutCounter = 0;
   1.305 +
   1.306 +    setupFiles();
   1.307 +    setupPrefs();
   1.308 +    removeUpdateDirsAndFiles();
   1.309 +    reloadUpdateManagerData();
   1.310 +    setupAddons(runTest);
   1.311 +  }
   1.312 +}
   1.313 +
   1.314 +/**
   1.315 + * Default test finish function that can be used by most tests. This function
   1.316 + * uses protective measures to prevent the next test from failing provided by
   1.317 + * |finishTestDefaultWaitForWindowClosed| helper functions to prevent failure
   1.318 + * due to an update window being left open.
   1.319 + */
   1.320 +function finishTestDefault() {
   1.321 +  debugDump("entering");
   1.322 +  if (gTimeoutTimer) {
   1.323 +    gTimeoutTimer.cancel();
   1.324 +    gTimeoutTimer = null;
   1.325 +  }
   1.326 +
   1.327 +  if (gChannel) {
   1.328 +    debugDump("channel = " + gChannel);
   1.329 +    gChannel = null;
   1.330 +    gPrefRoot.removeObserver(PREF_APP_UPDATE_CHANNEL, observer);
   1.331 +  }
   1.332 +
   1.333 +  verifyTestsRan();
   1.334 +
   1.335 +  resetPrefs();
   1.336 +  resetFiles();
   1.337 +  removeUpdateDirsAndFiles();
   1.338 +  reloadUpdateManagerData();
   1.339 +
   1.340 +  Services.ww.unregisterNotification(gWindowObserver);
   1.341 +  if (gDocElem) {
   1.342 +    gDocElem.removeEventListener("pageshow", onPageShowDefault, false);
   1.343 +  }
   1.344 +
   1.345 +  finishTestDefaultWaitForWindowClosed();
   1.346 +}
   1.347 +
   1.348 +/**
   1.349 + * nsITimerCallback for the timeout timer to cleanly finish a test if the Update
   1.350 + * Window doesn't close for a test. This allows the next test to run properly if
   1.351 + * a previous test fails.
   1.352 + *
   1.353 + * @param  aTimer
   1.354 + *         The nsITimer that fired.
   1.355 + */
   1.356 +function finishTestTimeout(aTimer) {
   1.357 +  ok(false, "Test timed out. Maximum time allowed is " + (gTestTimeout / 1000) +
   1.358 +     " seconds");
   1.359 +
   1.360 +  try {
   1.361 +    finishTest();
   1.362 +  }
   1.363 +  catch (e) {
   1.364 +    finishTestDefault();
   1.365 +  }
   1.366 +}
   1.367 +
   1.368 +/**
   1.369 + * If an update window is found SimpleTest.executeSoon can callback before the
   1.370 + * update window is fully closed especially with debug builds. If an update
   1.371 + * window is found this function will call itself using SimpleTest.executeSoon
   1.372 + * up to the amount declared in CLOSE_WINDOW_TIMEOUT_MAXCOUNT until the update
   1.373 + * window has closed before finishing the test.
   1.374 + */
   1.375 +function finishTestDefaultWaitForWindowClosed() {
   1.376 +  gCloseWindowTimeoutCounter++;
   1.377 +  if (gCloseWindowTimeoutCounter > CLOSE_WINDOW_TIMEOUT_MAXCOUNT) {
   1.378 +    SimpleTest.finish();
   1.379 +    return;
   1.380 +  }
   1.381 +
   1.382 +  // The update window should not be open at this time. If it is the call to
   1.383 +  // |closeUpdateWindow| will close it and cause the test to fail.
   1.384 +  if (closeUpdateWindow()) {
   1.385 +    SimpleTest.executeSoon(finishTestDefaultWaitForWindowClosed);
   1.386 +  }
   1.387 +  else {
   1.388 +    SimpleTest.finish();
   1.389 +  }
   1.390 +}
   1.391 +
   1.392 +/**
   1.393 + * Default callback for the wizard's documentElement pageshow listener. This
   1.394 + * will return early for event's where the originalTarget's nodeName is not
   1.395 + * wizardpage.
   1.396 + */
   1.397 +function onPageShowDefault(aEvent) {
   1.398 +  if (!gTimeoutTimer) {
   1.399 +    debugDump("gTimeoutTimer is null... returning early");
   1.400 +    return;
   1.401 +  }
   1.402 +
   1.403 +  // Return early if the event's original target isn't for a wizardpage element.
   1.404 +  // This check is necessary due to the remotecontent element firing pageshow.
   1.405 +  if (aEvent.originalTarget.nodeName != "wizardpage") {
   1.406 +    debugDump("only handles events with an originalTarget nodeName of " +
   1.407 +              "|wizardpage|. aEvent.originalTarget.nodeName = " +
   1.408 +              aEvent.originalTarget.nodeName + "... returning early");
   1.409 +    return;
   1.410 +  }
   1.411 +
   1.412 +  gTestCounter++;
   1.413 +  gCallback(aEvent);
   1.414 +}
   1.415 +
   1.416 +/**
   1.417 + * Default callback that can be used by most tests.
   1.418 + */
   1.419 +function defaultCallback(aEvent) {
   1.420 +  if (!gTimeoutTimer) {
   1.421 +    debugDump("gTimeoutTimer is null... returning early");
   1.422 +    return;
   1.423 +  }
   1.424 +
   1.425 +  debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid +
   1.426 +            ", aEvent.originalTarget.nodeName: " +
   1.427 +            aEvent.originalTarget.nodeName);
   1.428 +
   1.429 +  if (gTest && gTest.extraStartFunction) {
   1.430 +    debugDump("calling extraStartFunction " + gTest.extraStartFunction.name);
   1.431 +    if (gTest.extraStartFunction(aEvent)) {
   1.432 +      debugDump("extraStartFunction early return");
   1.433 +      return;
   1.434 +    }
   1.435 +  }
   1.436 +
   1.437 +  is(gDocElem.currentPage.pageid, gTest.pageid,
   1.438 +     "Checking currentPage.pageid equals " + gTest.pageid + " in pageshow");
   1.439 +
   1.440 +  // Perform extra checks if specified by the test
   1.441 +  if (gTest.extraCheckFunction) {
   1.442 +    debugDump("calling extraCheckFunction " + gTest.extraCheckFunction.name);
   1.443 +    gTest.extraCheckFunction();
   1.444 +  }
   1.445 +
   1.446 +  // The wizard page buttons' disabled and hidden attributes are set after the
   1.447 +  // pageshow event so use executeSoon to allow them to be set so their disabled
   1.448 +  // and hidden attribute values can be checked.
   1.449 +  SimpleTest.executeSoon(delayedDefaultCallback);
   1.450 +}
   1.451 +
   1.452 +/**
   1.453 + * Delayed default callback called using executeSoon in defaultCallback which
   1.454 + * allows the wizard page buttons' disabled and hidden attributes to be set
   1.455 + * before checking their values.
   1.456 + */
   1.457 +function delayedDefaultCallback() {
   1.458 +  if (!gTimeoutTimer) {
   1.459 +    debugDump("gTimeoutTimer is null... returning early");
   1.460 +    return;
   1.461 +  }
   1.462 +
   1.463 +  if (!gTest) {
   1.464 +    debugDump("gTest is null... returning early");
   1.465 +    return;
   1.466 +  }
   1.467 +
   1.468 +  debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid);
   1.469 +
   1.470 +  // Verify the pageid hasn't changed after executeSoon was called.
   1.471 +  is(gDocElem.currentPage.pageid, gTest.pageid,
   1.472 +     "Checking currentPage.pageid equals " + gTest.pageid + " after " +
   1.473 +     "executeSoon");
   1.474 +
   1.475 +  checkButtonStates();
   1.476 +
   1.477 +  // Perform delayed extra checks if specified by the test
   1.478 +  if (gTest.extraDelayedCheckFunction) {
   1.479 +    debugDump("calling extraDelayedCheckFunction " +
   1.480 +              gTest.extraDelayedCheckFunction.name);
   1.481 +    gTest.extraDelayedCheckFunction();
   1.482 +  }
   1.483 +
   1.484 +  // Used to verify that this test has been performed
   1.485 +  gTest.ranTest = true;
   1.486 +
   1.487 +  if (gTest.buttonClick) {
   1.488 +    debugDump("clicking " + gTest.buttonClick + " button");
   1.489 +    if(gTest.extraDelayedFinishFunction) {
   1.490 +      throw("Tests cannot have a buttonClick and an extraDelayedFinishFunction property");
   1.491 +    }
   1.492 +    gDocElem.getButton(gTest.buttonClick).click();
   1.493 +  }
   1.494 +  else if (gTest.extraDelayedFinishFunction) {
   1.495 +    debugDump("calling extraDelayedFinishFunction " +
   1.496 +              gTest.extraDelayedFinishFunction.name);
   1.497 +    gTest.extraDelayedFinishFunction();
   1.498 +  }
   1.499 +}
   1.500 +
   1.501 +/**
   1.502 + * Checks the wizard page buttons' disabled and hidden attributes values are
   1.503 + * correct. If an expected button id is not specified then the expected disabled
   1.504 + * and hidden attribute value is true.
   1.505 + */
   1.506 +function checkButtonStates() {
   1.507 +  debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid);
   1.508 +
   1.509 +  const buttonNames = ["extra1", "extra2", "back", "next", "finish", "cancel"];
   1.510 +  let buttonStates = getExpectedButtonStates();
   1.511 +  buttonNames.forEach(function(aButtonName) {
   1.512 +    let button = gDocElem.getButton(aButtonName);
   1.513 +    let hasHidden = aButtonName in buttonStates &&
   1.514 +                    "hidden" in buttonStates[aButtonName];
   1.515 +    let hidden = hasHidden ? buttonStates[aButtonName].hidden : true;
   1.516 +    let hasDisabled = aButtonName in buttonStates &&
   1.517 +                      "disabled" in buttonStates[aButtonName];
   1.518 +    let disabled = hasDisabled ? buttonStates[aButtonName].disabled : true;
   1.519 +    is(button.hidden, hidden, "Checking " + aButtonName + " button " +
   1.520 +       "hidden attribute value equals " + (hidden ? "true" : "false"));
   1.521 +    is(button.disabled, disabled, "Checking " + aButtonName + " button " +
   1.522 +       "disabled attribute value equals " + (disabled ? "true" : "false"));
   1.523 +  });
   1.524 +}
   1.525 +
   1.526 +/**
   1.527 + * Returns the expected disabled and hidden attribute values for the buttons of
   1.528 + * the current wizard page.
   1.529 + */
   1.530 +function getExpectedButtonStates() {
   1.531 +  // Allow individual tests to override the expected button states.
   1.532 +  if (gTest.buttonStates) {
   1.533 +    return gTest.buttonStates;
   1.534 +  }
   1.535 +
   1.536 +  switch (gTest.pageid) {
   1.537 +    case PAGEID_CHECKING:
   1.538 +    case PAGEID_INCOMPAT_CHECK:
   1.539 +      return { cancel: { disabled: false, hidden: false } };
   1.540 +    case PAGEID_FOUND_BASIC:
   1.541 +    case PAGEID_FOUND_BILLBOARD:
   1.542 +      if (gTest.neverButton) {
   1.543 +        return { extra1: { disabled: false, hidden: false },
   1.544 +                 extra2: { disabled: false, hidden: false },
   1.545 +                 next  : { disabled: false, hidden: false } }
   1.546 +      }
   1.547 +      return { extra1: { disabled: false, hidden: false },
   1.548 +               next  : { disabled: false, hidden: false } };
   1.549 +    case PAGEID_LICENSE:
   1.550 +      if (gRemoteContentState != "loaded" ||
   1.551 +          gAcceptDeclineLicense.selectedIndex != 0) {
   1.552 +        return { extra1: { disabled: false, hidden: false },
   1.553 +                 next  : { disabled: true, hidden: false } };
   1.554 +      }
   1.555 +      return { extra1: { disabled: false, hidden: false },
   1.556 +               next  : { disabled: false, hidden: false } };
   1.557 +    case PAGEID_INCOMPAT_LIST:
   1.558 +      return { extra1: { disabled: false, hidden: false },
   1.559 +               next  : { disabled: false, hidden: false } };
   1.560 +    case PAGEID_DOWNLOADING:
   1.561 +      return { extra1: { disabled: false, hidden: false } };
   1.562 +    case PAGEID_NO_UPDATES_FOUND:
   1.563 +    case PAGEID_MANUAL_UPDATE:
   1.564 +    case PAGEID_UNSUPPORTED:
   1.565 +    case PAGEID_ERRORS:
   1.566 +    case PAGEID_ERROR_EXTRA:
   1.567 +    case PAGEID_INSTALLED:
   1.568 +      return { finish: { disabled: false, hidden: false } };
   1.569 +    case PAGEID_ERROR_PATCHING:
   1.570 +      return { next  : { disabled: false, hidden: false } };
   1.571 +    case PAGEID_FINISHED:
   1.572 +    case PAGEID_FINISHED_BKGRD:
   1.573 +      return { extra1: { disabled: false, hidden: false },
   1.574 +               finish: { disabled: false, hidden: false } };
   1.575 +  }
   1.576 +  return null;
   1.577 +}
   1.578 +
   1.579 +/**
   1.580 + * Adds a load event listener to the current remotecontent element.
   1.581 + */
   1.582 +function addRemoteContentLoadListener() {
   1.583 +  debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid);
   1.584 +
   1.585 +  gRemoteContent.addEventListener("load", remoteContentLoadListener, false);
   1.586 +}
   1.587 +
   1.588 +/**
   1.589 + * The nsIDOMEventListener for a remotecontent load event.
   1.590 + */
   1.591 +function remoteContentLoadListener(aEvent) {
   1.592 +  // Return early if the event's original target's nodeName isn't remotecontent.
   1.593 +  if (aEvent.originalTarget.nodeName != "remotecontent") {
   1.594 +    debugDump("only handles events with an originalTarget nodeName of " +
   1.595 +              "|remotecontent|. aEvent.originalTarget.nodeName = " +
   1.596 +              aEvent.originalTarget.nodeName);
   1.597 +    return;
   1.598 +  }
   1.599 +
   1.600 +  gTestCounter++;
   1.601 +  gCallback(aEvent);
   1.602 +}
   1.603 +
   1.604 +/**
   1.605 + * Waits until a remotecontent element to finish loading which is determined
   1.606 + * by the current test's expectedRemoteContentState property and then removes
   1.607 + * the event listener.
   1.608 + *
   1.609 + * Note: tests that use this function should not test the state of the
   1.610 + *      remotecontent since this will check the expected state.
   1.611 + *
   1.612 + * @return false if the remotecontent has loaded and its state is the state
   1.613 + *         specified in the current test's expectedRemoteContentState
   1.614 + *         property... otherwise true.
   1.615 + */
   1.616 +function waitForRemoteContentLoaded(aEvent) {
   1.617 +  // Return early until the remotecontent has loaded with the state that is
   1.618 +  // expected or isn't the event's originalTarget.
   1.619 +  if (gRemoteContentState != gTest.expectedRemoteContentState ||
   1.620 +      aEvent.originalTarget != gRemoteContent) {
   1.621 +    debugDump("returning early\n" +
   1.622 +              "gRemoteContentState: " + gRemoteContentState + "\n" +
   1.623 +              "expectedRemoteContentState: " +
   1.624 +              gTest.expectedRemoteContentState + "\n" +
   1.625 +              "aEvent.originalTarget.nodeName: " +
   1.626 +              aEvent.originalTarget.nodeName);
   1.627 +    return true;
   1.628 +  }
   1.629 +
   1.630 +  gRemoteContent.removeEventListener("load", remoteContentLoadListener, false);
   1.631 +  return false;
   1.632 +}
   1.633 +
   1.634 +/**
   1.635 + * Compares the value of the remotecontent state attribute with the value
   1.636 + * specified in the test's expectedRemoteContentState property.
   1.637 + */
   1.638 +function checkRemoteContentState() {
   1.639 +  is(gRemoteContentState, gTest.expectedRemoteContentState, "Checking remote " +
   1.640 +     "content state equals " + gTest.expectedRemoteContentState + " - pageid " +
   1.641 +     gTest.pageid);
   1.642 +}
   1.643 +
   1.644 +/**
   1.645 + * Adds a select event listener to the license radiogroup element and clicks
   1.646 + * the radio element specified in the current test's radioClick property.
   1.647 + */
   1.648 +function addRadioGroupSelectListenerAndClick() {
   1.649 +  debugDump("entering - TESTS[" + gTestCounter + "], pageid: " + gTest.pageid);
   1.650 +
   1.651 +  gAcceptDeclineLicense.addEventListener("select", radioGroupSelectListener,
   1.652 +                                         false);
   1.653 +  gWin.document.getElementById(gTest.radioClick).click();
   1.654 +}
   1.655 +
   1.656 +/**
   1.657 + * The nsIDOMEventListener for the license radiogroup select event.
   1.658 + */
   1.659 +function radioGroupSelectListener(aEvent) {
   1.660 +  // Return early if the event's original target's nodeName isn't radiogroup.
   1.661 +  if (aEvent.originalTarget.nodeName != "radiogroup") {
   1.662 +    debugDump("only handles events with an originalTarget nodeName of " +
   1.663 +              "|radiogroup|. aEvent.originalTarget.nodeName = " +
   1.664 +              aEvent.originalTarget.nodeName);
   1.665 +    return;
   1.666 +  }
   1.667 +
   1.668 +  gAcceptDeclineLicense.removeEventListener("select", radioGroupSelectListener,
   1.669 +                                            false);
   1.670 +  gTestCounter++;
   1.671 +  gCallback(aEvent);
   1.672 +}
   1.673 +
   1.674 +/**
   1.675 + * Compares the value of the License radiogroup's selectedIndex attribute with
   1.676 + * the value specified in the test's expectedRadioGroupSelectedIndex property.
   1.677 + */
   1.678 +function checkRadioGroupSelectedIndex() {
   1.679 +  is(gAcceptDeclineLicense.selectedIndex, gTest.expectedRadioGroupSelectedIndex,
   1.680 +     "Checking license radiogroup selectedIndex equals " +
   1.681 +     gTest.expectedRadioGroupSelectedIndex);
   1.682 +}
   1.683 +
   1.684 +/**
   1.685 + * Checks that only incompatible add-ons (e.g. noupdate_X add-ons) that don't
   1.686 + * have an update are listed in the add-ons incompatible list.
   1.687 + */
   1.688 +function checkIncompatbleList() {
   1.689 +  for (let i = 0; i < gIncompatibleListbox.itemCount; i++) {
   1.690 +    let label = gIncompatibleListbox.getItemAtIndex(i).label;
   1.691 +    // Use indexOf since locales can change the text displayed
   1.692 +    ok(label.indexOf("noupdate") != -1, "Checking that only incompatible " + 
   1.693 +       "add-ons that don't have an update are listed in the incompatible list");
   1.694 +  }
   1.695 +}
   1.696 +
   1.697 +/**
   1.698 + * Compares the return value of prefHasUserValue for the preference specified in
   1.699 + * gPrefToCheck with the value passed in the aPrefHasValue parameter or the
   1.700 + * value specified in the current test's prefHasUserValue property if
   1.701 + * aPrefHasValue is undefined.
   1.702 + *
   1.703 + * @param  aPrefHasValue (optional)
   1.704 + *         The expected value returned from prefHasUserValue for the preference
   1.705 + *         specified in gPrefToCheck. If aPrefHasValue is undefined the value
   1.706 + *         of the current test's prefHasUserValue property will be used.
   1.707 + */
   1.708 +function checkPrefHasUserValue(aPrefHasValue) {
   1.709 +  let prefHasUserValue = aPrefHasValue === undefined ? gTest.prefHasUserValue
   1.710 +                                                     : aPrefHasValue;
   1.711 +  is(Services.prefs.prefHasUserValue(gPrefToCheck), prefHasUserValue,
   1.712 +     "Checking prefHasUserValue for preference " + gPrefToCheck + " equals " +
   1.713 +     (prefHasUserValue ? "true" : "false"));
   1.714 +}
   1.715 +
   1.716 +/**
   1.717 + * Checks whether the link is hidden (general background update check error or
   1.718 + * a certificate attribute check error with an update) or not (certificate
   1.719 + * attribute check error without an update) on the errorextra page and that the
   1.720 + * app.update.cert.errors and app.update.backgroundErrors preferences do not
   1.721 + & have a user value.
   1.722 + *
   1.723 + * @param  aShouldBeHidden (optional)
   1.724 + *         The expected value for the label's hidden attribute for the link. If
   1.725 + *         aShouldBeHidden is undefined the value of the current test's
   1.726 + *         shouldBeHidden property will be used.
   1.727 + */
   1.728 +function checkErrorExtraPage(aShouldBeHidden) {
   1.729 +  let shouldBeHidden = aShouldBeHidden === undefined ? gTest.shouldBeHidden
   1.730 +                                                     : aShouldBeHidden;
   1.731 +  is(gWin.document.getElementById("errorExtraLinkLabel").hidden, shouldBeHidden,
   1.732 +     "Checking errorExtraLinkLabel hidden attribute equals " +
   1.733 +     (shouldBeHidden ? "true" : "false"));
   1.734 +
   1.735 +  is(gWin.document.getElementById(gTest.displayedTextElem).hidden, false,
   1.736 +     "Checking " + gTest.displayedTextElem + " should not be hidden");
   1.737 +
   1.738 +  ok(!Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS),
   1.739 +     "Preference " + PREF_APP_UPDATE_CERT_ERRORS + " should not have a " +
   1.740 +     "user value");
   1.741 +
   1.742 +  ok(!Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS),
   1.743 +     "Preference " + PREF_APP_UPDATE_BACKGROUNDERRORS + " should not have a " +
   1.744 +     "user value");
   1.745 +}
   1.746 +
   1.747 +/**
   1.748 + * Gets the update version info for the update url parameters to send to
   1.749 + * update.sjs.
   1.750 + *
   1.751 + * @param  aAppVersion (optional)
   1.752 + *         The application version for the update snippet. If not specified the
   1.753 + *         current application version will be used.
   1.754 + * @param  aPlatformVersion (optional)
   1.755 + *         The platform version for the update snippet. If not specified the
   1.756 + *         current platform version will be used.
   1.757 + * @return The url parameters for the application and platform version to send
   1.758 + *         to update.sjs.
   1.759 + */
   1.760 +function getVersionParams(aAppVersion, aPlatformVersion) {
   1.761 +  let appInfo = Services.appinfo;
   1.762 +  return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version) +
   1.763 +         "&platformVersion=" + (aPlatformVersion ? aPlatformVersion
   1.764 +                                                 : appInfo.platformVersion);
   1.765 +}
   1.766 +
   1.767 +/**
   1.768 + * Gets an application version that is greater than the current application
   1.769 + * version. The version is created by taking the first sequence from the current
   1.770 + * application version and adding 1 to it.
   1.771 + *
   1.772 + * @return A version string greater than the current application version string.
   1.773 + */
   1.774 +function getNewerAppVersion() {
   1.775 +  let appVersion = Services.appinfo.version.split(".")[0];
   1.776 +  appVersion++;
   1.777 +  return appVersion;
   1.778 +}
   1.779 +
   1.780 +/**
   1.781 + * Gets a platform version that is greater than the current platform version.
   1.782 + * The version is created by taking the first sequence from the current platform
   1.783 + * version and adding 1 to it.
   1.784 + *
   1.785 + * @return A version string greater than the current platform version string.
   1.786 + */
   1.787 +function getNewerPlatformVersion() {
   1.788 +  let platformVersion = Services.appinfo.platformVersion.split(".")[0];
   1.789 +  platformVersion++;
   1.790 +  return platformVersion;
   1.791 +}
   1.792 +
   1.793 +/**
   1.794 + * Verifies that all tests ran.
   1.795 + */
   1.796 +function verifyTestsRan() {
   1.797 +  debugDump("entering");
   1.798 +
   1.799 +  // Return early if there are no tests defined.
   1.800 +  if (!TESTS) {
   1.801 +    return;
   1.802 +  }
   1.803 +
   1.804 +  gTestCounter = -1;
   1.805 +  for (let i = 0; i < TESTS.length; ++i) {
   1.806 +    gTestCounter++;
   1.807 +    let test = TESTS[i];
   1.808 +    let msg = "Checking if TESTS[" + i + "] test was performed... " +
   1.809 +              "callback function name = " + gCallback.name + ", " +
   1.810 +              "pageid = " + test.pageid;
   1.811 +    ok(test.ranTest, msg);
   1.812 +  }
   1.813 +}
   1.814 +
   1.815 +/**
   1.816 + * Creates a backup of files the tests need to modify so they can be restored to
   1.817 + * the original file when the test has finished and then modifies the files.
   1.818 + */
   1.819 +function setupFiles() {
   1.820 +  // Backup the updater-settings.ini file if it exists by moving it.
   1.821 +  let baseAppDir = getAppBaseDir();
   1.822 +  let updateSettingsIni = baseAppDir.clone();
   1.823 +  updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
   1.824 +  if (updateSettingsIni.exists()) {
   1.825 +    updateSettingsIni.moveTo(baseAppDir, FILE_UPDATE_SETTINGS_INI_BAK);
   1.826 +  }
   1.827 +  updateSettingsIni = baseAppDir.clone();
   1.828 +  updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI);
   1.829 +  writeFile(updateSettingsIni, UPDATE_SETTINGS_CONTENTS);
   1.830 +}
   1.831 +
   1.832 +/**
   1.833 + * Sets the most common preferences used by tests to values used by the majority
   1.834 + * of the tests and when necessary saves the preference's original values if
   1.835 + * present so they can be set back to the original values when the test has
   1.836 + * finished.
   1.837 + */
   1.838 +function setupPrefs() {
   1.839 +  if (DEBUG_AUS_TEST) {
   1.840 +    Services.prefs.setBoolPref(PREF_APP_UPDATE_LOG, true);
   1.841 +  }
   1.842 +
   1.843 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) {
   1.844 +    gAppUpdateURL = Services.prefs.getCharPref(PREF_APP_UPDATE_URL_OVERRIDE);
   1.845 +  }
   1.846 +
   1.847 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ENABLED)) {
   1.848 +    gAppUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED);
   1.849 +  }
   1.850 +  Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true);
   1.851 +
   1.852 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_METRO_ENABLED)) {
   1.853 +    gAppUpdateMetroEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_METRO_ENABLED);
   1.854 +  }
   1.855 +  Services.prefs.setBoolPref(PREF_APP_UPDATE_METRO_ENABLED, true);
   1.856 +
   1.857 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ENABLED)) {
   1.858 +    gAppUpdateServiceEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED);
   1.859 +  }
   1.860 +  Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, false);
   1.861 +
   1.862 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_STAGING_ENABLED)) {
   1.863 +    gAppUpdateStagingEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_STAGING_ENABLED);
   1.864 +  }
   1.865 +  Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false);
   1.866 +
   1.867 +  if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_UPDATE_URL)) {
   1.868 +    gExtUpdateURL = Services.prefs.getCharPref(PREF_EXTENSIONS_UPDATE_URL);
   1.869 +  }
   1.870 +  let extUpdateUrl = URL_HTTP_UPDATE_XML + "?addonID=%ITEM_ID%" +
   1.871 +                     "&platformVersion=" + getNewerPlatformVersion();
   1.872 +  Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, extUpdateUrl);
   1.873 +
   1.874 +  Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0);
   1.875 +  Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0);
   1.876 +  Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true);
   1.877 +  Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix" + ADDON_ID_SUFFIX);
   1.878 +}
   1.879 +
   1.880 +/**
   1.881 + * Restores files that were backed up for the tests and general file cleanup.
   1.882 + */
   1.883 +function resetFiles() {
   1.884 +  // Restore the backed up updater-settings.ini if it exists.
   1.885 +  let baseAppDir = getAppBaseDir();
   1.886 +  let updateSettingsIni = baseAppDir.clone();
   1.887 +  updateSettingsIni.append(FILE_UPDATE_SETTINGS_INI_BAK);
   1.888 +  if (updateSettingsIni.exists()) {
   1.889 +    updateSettingsIni.moveTo(baseAppDir, FILE_UPDATE_SETTINGS_INI);
   1.890 +  }
   1.891 +
   1.892 +  // Not being able to remove the "updated" directory will not adversely affect
   1.893 +  // subsequent tests so wrap it in a try block and don't test whether its
   1.894 +  // removal was successful.
   1.895 +  let updatedDir = getUpdatedDir();
   1.896 +  if (updatedDir.exists()) {
   1.897 +    try {
   1.898 +      removeDirRecursive(updatedDir);
   1.899 +    }
   1.900 +    catch (e) {
   1.901 +      dump("Unable to remove directory\n" +
   1.902 +           "path: " + updatedDir.path + "\n" +
   1.903 +           "Exception: " + e + "\n");
   1.904 +    }
   1.905 +  }
   1.906 +}
   1.907 +
   1.908 +/**
   1.909 + * Resets the most common preferences used by tests to their original values.
   1.910 + */
   1.911 +function resetPrefs() {
   1.912 +  if (gAppUpdateURL !== undefined) {
   1.913 +    Services.prefs.setCharPref(PREF_APP_UPDATE_URL_OVERRIDE, gAppUpdateURL);
   1.914 +  }
   1.915 +  else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) {
   1.916 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_URL_OVERRIDE);
   1.917 +  }
   1.918 +
   1.919 +  if (gAppUpdateURLDefault) {
   1.920 +    gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_URL, gAppUpdateURLDefault);
   1.921 +  }
   1.922 +
   1.923 +  if (gAppUpdateEnabled !== undefined) {
   1.924 +    Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, gAppUpdateEnabled);
   1.925 +  }
   1.926 +  else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ENABLED)) {
   1.927 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED);
   1.928 +  }
   1.929 +
   1.930 +  if (gAppUpdateMetroEnabled !== undefined) {
   1.931 +    Services.prefs.setBoolPref(PREF_APP_UPDATE_METRO_ENABLED, gAppUpdateMetroEnabled);
   1.932 +  }
   1.933 +  else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_METRO_ENABLED)) {
   1.934 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_METRO_ENABLED);
   1.935 +  }
   1.936 +
   1.937 +  if (gAppUpdateServiceEnabled !== undefined) {
   1.938 +    Services.prefs.setBoolPref(PREF_APP_UPDATE_SERVICE_ENABLED, gAppUpdateServiceEnabled);
   1.939 +  }
   1.940 +  else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ENABLED)) {
   1.941 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ENABLED);
   1.942 +  }
   1.943 +
   1.944 +  if (gAppUpdateStagingEnabled !== undefined) {
   1.945 +    Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, gAppUpdateStagingEnabled);
   1.946 +  }
   1.947 +  else if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_STAGING_ENABLED)) {
   1.948 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_STAGING_ENABLED);
   1.949 +  }
   1.950 +
   1.951 +  if (gExtUpdateURL !== undefined) {
   1.952 +    Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, gExtUpdateURL);
   1.953 +  }
   1.954 +  else if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_UPDATE_URL)) {
   1.955 +    Services.prefs.clearUserPref(PREF_EXTENSIONS_UPDATE_URL);
   1.956 +  }
   1.957 +
   1.958 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_IDLETIME)) {
   1.959 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_IDLETIME);
   1.960 +  }
   1.961 +
   1.962 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_PROMPTWAITTIME)) {
   1.963 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_PROMPTWAITTIME);
   1.964 +  }
   1.965 +
   1.966 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_DETAILS)) {
   1.967 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_URL_DETAILS);
   1.968 +  }
   1.969 +
   1.970 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SHOW_INSTALLED_UI)) {
   1.971 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_SHOW_INSTALLED_UI);
   1.972 +  }
   1.973 +
   1.974 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED)) {
   1.975 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED);
   1.976 +  }
   1.977 +
   1.978 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LOG)) {
   1.979 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_LOG);
   1.980 +  }
   1.981 +
   1.982 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS)) {
   1.983 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_ERRORS);
   1.984 +  }
   1.985 +
   1.986 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_MAXERRORS)) {
   1.987 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_MAXERRORS);
   1.988 +  }
   1.989 +
   1.990 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS)) {
   1.991 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS);
   1.992 +  }
   1.993 +
   1.994 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDMAXERRORS)) {
   1.995 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDMAXERRORS);
   1.996 +  }
   1.997 +
   1.998 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME)) {
   1.999 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME);
  1.1000 +  }
  1.1001 +
  1.1002 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_REQUIREBUILTIN)) {
  1.1003 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_REQUIREBUILTIN);
  1.1004 +  }
  1.1005 +
  1.1006 +  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_CHECKATTRS)) {
  1.1007 +    Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_CHECKATTRS);
  1.1008 +  }
  1.1009 +
  1.1010 +  try {
  1.1011 +    CERT_ATTRS.forEach(function(aCertAttrName) {
  1.1012 +      Services.prefs.clearUserPref(PREF_APP_UPDATE_CERTS_BRANCH + "1." +
  1.1013 +                                   aCertAttrName);
  1.1014 +    });
  1.1015 +  }
  1.1016 +  catch (e) {
  1.1017 +  }
  1.1018 +
  1.1019 +  try {
  1.1020 +    Services.prefs.deleteBranch(PREF_APP_UPDATE_NEVER_BRANCH);
  1.1021 +  }
  1.1022 +  catch(e) {
  1.1023 +  }
  1.1024 +
  1.1025 +  if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) {
  1.1026 +		Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT);
  1.1027 +  }
  1.1028 +
  1.1029 +  if (Services.prefs.prefHasUserValue(PREF_EM_HOTFIX_ID)) {
  1.1030 +    Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID);
  1.1031 +  }
  1.1032 +}
  1.1033 +
  1.1034 +function setupTimer(aTestTimeout) {
  1.1035 +  gTestTimeout = aTestTimeout;
  1.1036 +  if (gTimeoutTimer) {
  1.1037 +    gTimeoutTimer.cancel();
  1.1038 +    gTimeoutTimer = null;
  1.1039 +  }
  1.1040 +  gTimeoutTimer = AUS_Cc["@mozilla.org/timer;1"].
  1.1041 +                  createInstance(AUS_Ci.nsITimer);
  1.1042 +  gTimeoutTimer.initWithCallback(finishTestTimeout, gTestTimeout,
  1.1043 +                                 AUS_Ci.nsITimer.TYPE_ONE_SHOT);
  1.1044 +}
  1.1045 +
  1.1046 +/**
  1.1047 + * Disables pre-existing add-ons so they don't interfere with the tests,
  1.1048 + * installs the test add-ons, sets the noupdate test add-ons' userDisabled value
  1.1049 + * for the test, and calls the callback specified in the aCallback parameter. If
  1.1050 + * the app.update.test.disabledAddons has a user value then setting the noupdate
  1.1051 + * test add-ons' userDisabled value for the test is the only thing that is done.
  1.1052 + *
  1.1053 + * @param  aCallback
  1.1054 + *         A callback to call after all operations have completed.
  1.1055 + */
  1.1056 +function setupAddons(aCallback) {
  1.1057 +  debugDump("entering");
  1.1058 +
  1.1059 +  // Sets the appropriate userDisabled value for the noupdate test add-ons based
  1.1060 +  // on the value of gDisableNoUpdateAddon and calls the callback specified in
  1.1061 +  // setupAddons aCallback parameter.
  1.1062 +  function setNoUpdateAddonsDisabledState() {
  1.1063 +    AddonManager.getAllAddons(function(aAddons) {
  1.1064 +      aAddons.forEach(function(aAddon) {
  1.1065 +        if (aAddon.name.indexOf("noupdate") != 0)
  1.1066 +          return;
  1.1067 +
  1.1068 +        if (gDisableNoUpdateAddon) {
  1.1069 +          if (!aAddon.userDisabled) {
  1.1070 +            aAddon.userDisabled = true;
  1.1071 +          }
  1.1072 +        }
  1.1073 +        else {
  1.1074 +          if (aAddon.userDisabled) {
  1.1075 +            aAddon.userDisabled = false;
  1.1076 +          }
  1.1077 +        }
  1.1078 +      });
  1.1079 +      // Start the timout timer before the update window is displayed so it can
  1.1080 +      // clean up tests that don't successfully display the update window.
  1.1081 +      setupTimer(gTestTimeout);
  1.1082 +      aCallback();
  1.1083 +    });
  1.1084 +  }
  1.1085 +
  1.1086 +  // If the app.update.test.disabledAddons preference exists the pre-existing
  1.1087 +  // add-ons have already been disabled so they don't interfere with the tests,
  1.1088 +  // the test add-ons have already been installed, and the only thing that needs
  1.1089 +  // to be done is setting the appropriate userDisabled value for the noupdate
  1.1090 +  // test add-ons.
  1.1091 +  if (Services.prefs.prefHasUserValue(PREF_DISABLEDADDONS)) {
  1.1092 +    setNoUpdateAddonsDisabledState();
  1.1093 +    return;
  1.1094 +  }
  1.1095 +
  1.1096 +  // Disable all pre-existing enabled addons so they don't interfere with the
  1.1097 +  // tests.
  1.1098 +  AddonManager.getAllAddons(function(aAddons) {
  1.1099 +    let disabledAddons = [];
  1.1100 +    aAddons.forEach(function(aAddon) {
  1.1101 +      // If an addon's type equals plugin it is skipped since
  1.1102 +      // checking plugins compatibility information isn't supported at this
  1.1103 +      // time (also see bug 566787). Also, SCOPE_APPLICATION add-ons are
  1.1104 +      // excluded by app update so there is no reason to disable them.
  1.1105 +      if (aAddon.type != "plugin" && !aAddon.appDisabled &&
  1.1106 +          !aAddon.userDisabled &&
  1.1107 +          aAddon.scope != AddonManager.SCOPE_APPLICATION) {
  1.1108 +        disabledAddons.push(aAddon);
  1.1109 +        aAddon.userDisabled = true;
  1.1110 +      }
  1.1111 +    });
  1.1112 +    // If there are no pre-existing add-ons the preference value will be an
  1.1113 +    // empty string.
  1.1114 +    Services.prefs.setCharPref(PREF_DISABLEDADDONS, disabledAddons.join(" "));
  1.1115 +
  1.1116 +    // Install the test add-ons.
  1.1117 +    let xpiFiles = getTestAddonXPIFiles();
  1.1118 +    let xpiCount = xpiFiles.length;
  1.1119 +    let installs = [];
  1.1120 +    xpiFiles.forEach(function(aFile) {
  1.1121 +      AddonManager.getInstallForFile(aFile, function(aInstall) {
  1.1122 +        if (!aInstall) {
  1.1123 +          throw "No AddonInstall created for " + aFile.path;
  1.1124 +        }
  1.1125 +
  1.1126 +        installs.push(aInstall);
  1.1127 +
  1.1128 +        if (--xpiCount == 0) {
  1.1129 +          let installCount = installs.length;
  1.1130 +          function installCompleted(aInstall) {
  1.1131 +            aInstall.removeListener(listener);
  1.1132 +
  1.1133 +            if (getAddonTestType(aInstall.addon.name) == "userdisabled") {
  1.1134 +              aInstall.addon.userDisabled = true;
  1.1135 +            }
  1.1136 +            if (--installCount == 0) {
  1.1137 +              setNoUpdateAddonsDisabledState();
  1.1138 +            }
  1.1139 +          }
  1.1140 +
  1.1141 +          let listener = {
  1.1142 +            onDownloadFailed: installCompleted,
  1.1143 +            onDownloadCancelled: installCompleted,
  1.1144 +            onInstallFailed: installCompleted,
  1.1145 +            onInstallCancelled: installCompleted,
  1.1146 +            onInstallEnded: installCompleted
  1.1147 +          };
  1.1148 +
  1.1149 +          installs.forEach(function(aInstall) {
  1.1150 +            aInstall.addListener(listener);
  1.1151 +            aInstall.install();
  1.1152 +          });
  1.1153 +        }
  1.1154 +      });
  1.1155 +    });
  1.1156 +  });
  1.1157 +}
  1.1158 +
  1.1159 +/**
  1.1160 + * Uninstalls the test add-ons, enables add-ons that were disabled when the
  1.1161 + * test started, and calls the callback specified in the aCallback parameter.
  1.1162 + *
  1.1163 + * @param  aCallback
  1.1164 + *         A callback to call after all operations have completed.
  1.1165 + */
  1.1166 +function resetAddons(aCallback) {
  1.1167 +  debugDump("entering");
  1.1168 +  // If test_9999_cleanup.xul is ran by itself then the test add-ons will not
  1.1169 +  // have been installed and any pre-existing add-ons will not have been
  1.1170 +  // disabled so return early.
  1.1171 +  if (!Services.prefs.prefHasUserValue(PREF_DISABLEDADDONS)) {
  1.1172 +    debugDump("preference " + PREF_DISABLEDADDONS + " doesn't exist... " +
  1.1173 +              "returning early");
  1.1174 +    aCallback();
  1.1175 +    return;
  1.1176 +  }
  1.1177 +
  1.1178 +  // Uninstall the test add-ons.
  1.1179 +  let count = TEST_ADDONS.length;
  1.1180 +  function uninstallCompleted(aAddon) {
  1.1181 +    if (--count == 0) {
  1.1182 +      AddonManager.removeAddonListener(listener);
  1.1183 +
  1.1184 +      // Enable the pre-existing add-ons that were disabled so they wouldn't
  1.1185 +      // interfere with the tests.
  1.1186 +      let disabledAddons = Services.prefs.getCharPref(PREF_DISABLEDADDONS).split(" ");
  1.1187 +      Services.prefs.clearUserPref(PREF_DISABLEDADDONS);
  1.1188 +      AddonManager.getAllAddons(function(aAddons) {
  1.1189 +        aAddons.forEach(function(aAddon) {
  1.1190 +          if (disabledAddons.indexOf(aAddon.id)) {
  1.1191 +            aAddon.userDisabled = false;
  1.1192 +          }
  1.1193 +        });
  1.1194 +        aCallback();
  1.1195 +      });
  1.1196 +    }
  1.1197 +  }
  1.1198 +
  1.1199 +  let listener = {
  1.1200 +    onUninstalled: uninstallCompleted
  1.1201 +  };
  1.1202 +
  1.1203 +  AddonManager.addAddonListener(listener);
  1.1204 +  TEST_ADDONS.forEach(function(aName) {
  1.1205 +    AddonManager.getAddonByID(aName + ADDON_ID_SUFFIX, function(aAddon) {
  1.1206 +      aAddon.uninstall();
  1.1207 +    });
  1.1208 +  });
  1.1209 +}
  1.1210 +
  1.1211 +/**
  1.1212 + * Helper function to get the string before the '_' character in an add-on's
  1.1213 + * name or id which is used to determine the add-on test type used by the tests.
  1.1214 + *
  1.1215 + * @param  aName
  1.1216 + *         The test add-on's name or id.
  1.1217 + * @return The string before the '_' character in the string passed in the aName
  1.1218 + *         parameter.
  1.1219 + */
  1.1220 +function getAddonTestType(aName) {
  1.1221 +  return aName.split("_")[0];
  1.1222 +}
  1.1223 +
  1.1224 +/**
  1.1225 + * Helper function to create add-on xpi files for the default test add-ons.
  1.1226 + *
  1.1227 + * @return An array with each member being an nsILocalFile for an add-on XPI
  1.1228 + *         file.
  1.1229 + */
  1.1230 +function getTestAddonXPIFiles() {
  1.1231 +  let addonPrepDir = Services.dirsvc.get(NS_APP_USER_PROFILE_50_DIR,
  1.1232 +                                         AUS_Ci.nsILocalFile);
  1.1233 +  addonPrepDir.append(ADDON_PREP_DIR);
  1.1234 +
  1.1235 +  let bootstrap = addonPrepDir.clone();
  1.1236 +  bootstrap.append("bootstrap.js");
  1.1237 +  // If a previous test has already created bootstrap.js don't create it again.
  1.1238 +  if (!bootstrap.exists()) {
  1.1239 +    let bootstrapContents = "function install(data, reason){ }\n" +
  1.1240 +                            "function startup(data, reason){ }\n" +
  1.1241 +                            "function shutdown(data, reason){ }\n" +
  1.1242 +                            "function uninstall(data, reason){ }\n";
  1.1243 +    writeFile(bootstrap, bootstrapContents);
  1.1244 +  }
  1.1245 +
  1.1246 +  let installRDF = addonPrepDir.clone();
  1.1247 +  installRDF.append("install.rdf");
  1.1248 +
  1.1249 +  let xpiFiles = [];
  1.1250 +  TEST_ADDONS.forEach(function(aName) {
  1.1251 +    let xpiFile = addonPrepDir.clone();
  1.1252 +    xpiFile.append(aName + ".xpi");
  1.1253 +
  1.1254 +    if (installRDF.exists())
  1.1255 +      installRDF.remove(false);
  1.1256 +    writeFile(installRDF, getInstallRDFString(aName));
  1.1257 +    gZipW.open(xpiFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
  1.1258 +    gZipW.addEntryFile(installRDF.leafName,
  1.1259 +                       AUS_Ci.nsIZipWriter.COMPRESSION_DEFAULT, installRDF,
  1.1260 +                       false);
  1.1261 +    gZipW.addEntryFile(bootstrap.leafName,
  1.1262 +                       AUS_Ci.nsIZipWriter.COMPRESSION_DEFAULT, bootstrap,
  1.1263 +                       false);
  1.1264 +    gZipW.close();
  1.1265 +    xpiFiles.push(xpiFile);
  1.1266 +  });
  1.1267 +
  1.1268 +  return xpiFiles;
  1.1269 +}
  1.1270 +
  1.1271 +/**
  1.1272 + * Helper function to gets the string representation of the contents of the
  1.1273 + * add-on's install.rdf file.
  1.1274 + *
  1.1275 + * @param  aName
  1.1276 + *         The string to use for the add-on's name which is also used to
  1.1277 + *         construct the local-part in RFC 5322 format of the add-on's ID.
  1.1278 + * @return A string representation of the contents of the add-on's install.rdf
  1.1279 + *         file.
  1.1280 + */
  1.1281 +function getInstallRDFString(aName) {
  1.1282 +  let maxVersion = Services.appinfo.platformVersion;
  1.1283 +  switch (getAddonTestType(aName)) {
  1.1284 +    case "compatible":
  1.1285 +      maxVersion = getNewerPlatformVersion();
  1.1286 +      break;
  1.1287 +    case "appdisabled":
  1.1288 +      maxVersion = "0.1";
  1.1289 +      break;
  1.1290 +  }
  1.1291 +
  1.1292 +  return "<?xml version=\"1.0\"?>\n" +
  1.1293 +         "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" +
  1.1294 +         "  xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" +
  1.1295 +         "  <Description about=\"urn:mozilla:install-manifest\">\n" +
  1.1296 +         "    <em:id>" + aName + ADDON_ID_SUFFIX + "</em:id>\n" +
  1.1297 +         "    <em:version>1.0</em:version>\n" +
  1.1298 +         "    <em:bootstrap>true</em:bootstrap>\n" +
  1.1299 +         "    <em:name>" + aName + "</em:name>\n" +
  1.1300 +         "    <em:description>Test Description</em:description>\n" +
  1.1301 +         "    <em:targetApplication>\n" +
  1.1302 +         "      <Description>\n" +
  1.1303 +         "        <em:id>toolkit@mozilla.org</em:id>\n" +
  1.1304 +         "        <em:minVersion>undefined</em:minVersion>\n" +
  1.1305 +         "        <em:maxVersion>" + maxVersion + "</em:maxVersion>\n" +
  1.1306 +         "      </Description>\n" +
  1.1307 +         "    </em:targetApplication>\n" +
  1.1308 +         "  </Description>\n" +
  1.1309 +         "</RDF>";
  1.1310 +}
  1.1311 +
  1.1312 +/**
  1.1313 + * Closes the update window if it is open and causes the test to fail if an
  1.1314 + * update window is found.
  1.1315 + *
  1.1316 + * @return true if an update window was found, otherwise false.
  1.1317 + */
  1.1318 +function closeUpdateWindow() {
  1.1319 +  let updateWindow = getUpdateWindow();
  1.1320 +  if (!updateWindow)
  1.1321 +    return false;
  1.1322 +
  1.1323 +  ok(false, "Found an existing Update Window from the current or a previous " +
  1.1324 +            "test... attempting to close it.");
  1.1325 +  updateWindow.close();
  1.1326 +  return true;
  1.1327 +}
  1.1328 +
  1.1329 +/**
  1.1330 + * Gets the update window.
  1.1331 + *
  1.1332 + * @return The nsIDOMWindow for the Update Window if it is open and null
  1.1333 + *         if it isn't.
  1.1334 + */
  1.1335 +function getUpdateWindow() {
  1.1336 +  return Services.wm.getMostRecentWindow(UPDATE_WINDOW_NAME);
  1.1337 +}
  1.1338 +
  1.1339 +/**
  1.1340 + * Helper for background check errors.
  1.1341 + */
  1.1342 +var errorsPrefObserver = {
  1.1343 +  observedPref: null,
  1.1344 +  maxErrorPref: null,
  1.1345 +
  1.1346 +  /**
  1.1347 +   * Sets up a preference observer and sets the associated maximum errors
  1.1348 +   * preference used for background notification.
  1.1349 +   *
  1.1350 +   * @param  aObservePref
  1.1351 +   *         The preference to observe.
  1.1352 +   * @param  aMaxErrorPref
  1.1353 +   *         The maximum errors preference.
  1.1354 +   * @param  aMaxErrorCount
  1.1355 +   *         The value to set the app.update.cert.maxErrors preference to.
  1.1356 +   */
  1.1357 +  init: function(aObservePref, aMaxErrorPref, aMaxErrorCount) {
  1.1358 +    this.observedPref = aObservePref;
  1.1359 +    this.maxErrorPref = aMaxErrorPref;
  1.1360 +
  1.1361 +    let maxErrors = aMaxErrorCount ? aMaxErrorCount : 2;
  1.1362 +    Services.prefs.setIntPref(aMaxErrorPref, maxErrors);
  1.1363 +    Services.prefs.addObserver(aObservePref, this, false);
  1.1364 +  },
  1.1365 +
  1.1366 +  /**
  1.1367 +   * Preference observer for the preference specified in |this.observedPref|.
  1.1368 +   */
  1.1369 +  observe: function XPI_observe(aSubject, aTopic, aData) {
  1.1370 +    if (aData == this.observedPref) {
  1.1371 +      let errCount = Services.prefs.getIntPref(this.observedPref);
  1.1372 +      let errMax = Services.prefs.getIntPref(this.maxErrorPref);
  1.1373 +      if (errCount >= errMax) {
  1.1374 +        debugDump("removing pref observer");
  1.1375 +        Services.prefs.removeObserver(this.observedPref, this);
  1.1376 +      }
  1.1377 +      else {
  1.1378 +        debugDump("notifying AUS");
  1.1379 +        SimpleTest.executeSoon(function() {
  1.1380 +          gAUS.notify(null);
  1.1381 +        });
  1.1382 +      }
  1.1383 +    }
  1.1384 +  }
  1.1385 +};
  1.1386 +
  1.1387 +/**
  1.1388 + * nsIObserver for receiving window open and close notifications.
  1.1389 + */
  1.1390 +var gWindowObserver = {
  1.1391 +  observe: function WO_observe(aSubject, aTopic, aData) {
  1.1392 +    let win = aSubject.QueryInterface(AUS_Ci.nsIDOMEventTarget);
  1.1393 +
  1.1394 +    if (aTopic == "domwindowclosed") {
  1.1395 +      if (win.location != URI_UPDATE_PROMPT_DIALOG) {
  1.1396 +        debugDump("domwindowclosed event for window not being tested - " +
  1.1397 +                  "location: " + win.location + "... returning early");
  1.1398 +        return;
  1.1399 +      }
  1.1400 +      // Allow tests the ability to provide their own function (it must be
  1.1401 +      // named finishTest) for finishing the test.
  1.1402 +      try {
  1.1403 +        finishTest();
  1.1404 +      }
  1.1405 +      catch (e) {
  1.1406 +        finishTestDefault();
  1.1407 +      }
  1.1408 +      return;
  1.1409 +    }
  1.1410 +
  1.1411 +    win.addEventListener("load", function WO_observe_onLoad() {
  1.1412 +      win.removeEventListener("load", WO_observe_onLoad, false);
  1.1413 +      // Ignore windows other than the update UI window.
  1.1414 +      if (win.location != URI_UPDATE_PROMPT_DIALOG) {
  1.1415 +        debugDump("load event for window not being tested - location: " +
  1.1416 +                  win.location + "... returning early");
  1.1417 +        return;
  1.1418 +      }
  1.1419 +
  1.1420 +      // The first wizard page should always be the dummy page.
  1.1421 +      let pageid = win.document.documentElement.currentPage.pageid;
  1.1422 +      if (pageid != PAGEID_DUMMY) {
  1.1423 +        // This should never happen but if it does this will provide a clue
  1.1424 +        // for diagnosing the cause.
  1.1425 +        ok(false, "Unexpected load event - pageid got: " + pageid +
  1.1426 +           ", expected: " + PAGEID_DUMMY + "... returning early");
  1.1427 +        return;
  1.1428 +      }
  1.1429 +
  1.1430 +      gWin = win;
  1.1431 +      gDocElem = gWin.document.documentElement;
  1.1432 +      gDocElem.addEventListener("pageshow", onPageShowDefault, false);
  1.1433 +    }, false);
  1.1434 +  }
  1.1435 +};

mercurial