This commit is contained in:
Ryan VanderMeulen 2014-05-05 13:22:22 -04:00
Родитель 0f82c9229c 7ca4333a3f
Коммит 2b7d069140
14 изменённых файлов: 291 добавлений и 248 удалений

Просмотреть файл

@ -2,21 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
body, html {
height: 100%;
width: 100%;
overflow: hidden;
}
body {
margin: 0;
max-width: 320px;
position: relative;
margin: 0px auto;
padding: 0;
}
#header {
box-sizing: border-box;
width: 100%;
padding: 6px 9px;
padding: 4px 13px;
display: -moz-box;
vertical-align: top;
}
@ -38,22 +34,13 @@ body {
}
#main {
margin: 0 10px 10px 10px;
margin: 0 14px 10px 14px;
box-sizing: border-box;
width: calc(100% - 2 * 10px);
width: calc(100% - 2 * 14px);
position: absolute;
border-width: 1px;
}
@media (min-width: 320px) {
body {
position: absolute;
width: 320px;
left: -160px;
margin-left: 50%;
}
}
#content,
#borders {
border-width: 1px;
@ -194,3 +181,83 @@ body.dim > #main > p,
body.dim > #main > .tooltip {
visibility: hidden;
}
@media (max-height: 228px) {
#header {
padding-top: 0;
padding-bottom: 0;
margin-top: 10px;
margin-bottom: 8px;
}
#margins,
#padding {
border-width: 21px;
}
#borders {
padding: 21px;
}
#content {
height: 21px;
}
.padding.top {
top: 46px;
}
.padding.bottom {
bottom: 46px;
}
.border.top {
top: 25px;
}
.border.bottom {
bottom: 25px;
}
.margin.top {
top: 4px;
}
.margin.bottom {
bottom: 4px;
}
.size,
.margin.left,
.margin.right,
.border.left,
.border.right,
.padding.left,
.padding.right {
line-height: 106px;
}
.margin.right,
.margin.left,
.border.left,
.border.right,
.padding.right,
.padding.left {
width: 21px;
}
.padding.left {
left: 43px;
}
.padding.right {
right: 43px;
}
.border.left {
left: 22px;
}
.border.right {
right: 22px;
}
}

Просмотреть файл

@ -94,15 +94,6 @@ function test() {
is(fragment.textContent, "#F06");
}
},
{
name: "border-top-left-color",
value: "rgba(14, 255, 20, .5)",
test: fragment => {
is(countAll(fragment), 1);
is(countColors(fragment), 1);
is(fragment.textContent, "rgba(14, 255, 20, .5)");
}
},
{
name: "border",
value: "80em dotted pink",

Просмотреть файл

@ -294,16 +294,12 @@ OutputParser.prototype = {
let win = Services.appShell.hiddenDOMWindow;
let doc = win.document;
name = name.replace(/-\w{1}/g, function(match) {
return match.charAt(1).toUpperCase();
});
value = value.replace("!important", "");
let div = doc.createElement("div");
div.style[name] = value;
div.style.setProperty(name, value);
return !!div.style[name];
return !!div.style.getPropertyValue(name);
},
/**

Просмотреть файл

@ -67,6 +67,8 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
@ -462,6 +464,7 @@ var gUpdateEnabled = true;
var gAutoUpdateDefault = true;
var gHotfixID = null;
var gUpdateCheckInProgress = false;
/**
* This is the real manager, kept here rather than in AddonManager to keep its
* contents hidden from API users.
@ -477,7 +480,6 @@ var AddonManagerInternal = {
// Store telemetry details per addon provider
telemetryDetails: {},
// A read-only wrapper around the types dictionary
typesProxy: Proxy.create({
getOwnPropertyDescriptor: function typesProxy_getOwnPropertyDescriptor(aName) {
@ -1132,120 +1134,121 @@ var AddonManagerInternal = {
/**
* Performs a background update check by starting an update for all add-ons
* that can be updated.
* @return Promise{null} resolves when the background update check is complete
* (including all addon installs)
*/
backgroundUpdateCheck: function AMI_backgroundUpdateCheck() {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
let hotfixID = this.hotfixID;
let checkHotfix = hotfixID &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
if (!this.updateEnabled && !checkHotfix)
return;
Services.obs.notifyObservers(null, "addons-background-update-start", null);
// Start this from one to ensure the whole of this function completes before
// we can send the complete notification. Some parts can in some cases
// complete synchronously before later parts have a chance to increment
// pendingUpdates.
let pendingUpdates = 1;
function notifyComplete() {
if (--pendingUpdates == 0) {
Services.obs.notifyObservers(null,
"addons-background-update-complete",
null);
}
if (gUpdateCheckInProgress) {
throw Components.Exception("Background update check already in progress",
Cr.NS_ERROR_UNEXPECTED);
}
gUpdateCheckInProgress = true;
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
scope.LightweightThemeManager.updateCurrentTheme();
return Task.spawn(function* backgroundUpdateTask() {
let hotfixID = this.hotfixID;
let checkHotfix = hotfixID &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
if (!this.updateEnabled && !checkHotfix)
return;
Services.obs.notifyObservers(null, "addons-background-update-start", null);
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
scope.LightweightThemeManager.updateCurrentTheme();
let aAddons = yield new Promise((resolve, reject) => this.getAllAddons(resolve));
pendingUpdates++;
this.getAllAddons(function getAddonsCallback(aAddons) {
// If there is a known hotfix then exclude it from the list of add-ons to update.
var ids = [a.id for each (a in aAddons) if (a.id != hotfixID)];
// Repopulate repository cache first, to ensure compatibility overrides
// are up to date before checking for addon updates.
AddonRepository.backgroundUpdateCheck(
ids, function BUC_backgroundUpdateCheckCallback() {
pendingUpdates += aAddons.length;
aAddons.forEach(function BUC_forEachCallback(aAddon) {
if (aAddon.id == hotfixID) {
notifyComplete();
return;
}
yield new Promise((resolve, reject) => AddonRepository.backgroundUpdateCheck(ids, resolve));
// Check all add-ons for updates so that any compatibility updates will
// be applied
// Keep track of all the async add-on updates happening in parallel
let updates = [];
for (let aAddon of aAddons) {
if (aAddon.id == hotfixID) {
continue;
}
// Check all add-ons for updates so that any compatibility updates will
// be applied
updates.push(new Promise((resolve, reject) => {
aAddon.findUpdates({
onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
// Start installing updates when the add-on can be updated and
// background updates should be applied.
if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
AddonManager.shouldAutoUpdate(aAddon)) {
// XXX we really should resolve when this install is done,
// not when update-available check completes, no?
aInstall.install();
}
},
onUpdateFinished: notifyComplete
onUpdateFinished: resolve
}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
});
notifyComplete();
});
});
}
if (checkHotfix) {
var hotfixVersion = "";
try {
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
}));
}
yield Promise.all(updates);
}
catch (e) { }
let url = null;
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
else
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
if (checkHotfix) {
var hotfixVersion = "";
try {
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
}
catch (e) { }
// Build the URI from a fake add-on data.
url = AddonManager.escapeAddonURI({
id: hotfixID,
version: hotfixVersion,
userDisabled: false,
appDisabled: false
}, url);
let url = null;
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
else
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
pendingUpdates++;
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
onUpdateCheckComplete: function BUC_onUpdateCheckComplete(aUpdates) {
let update = AddonUpdateChecker.getNewestCompatibleUpdate(aUpdates);
if (!update) {
notifyComplete();
return;
}
// Build the URI from a fake add-on data.
url = AddonManager.escapeAddonURI({
id: hotfixID,
version: hotfixVersion,
userDisabled: false,
appDisabled: false
}, url);
// If the available version isn't newer than the last installed
// version then ignore it.
if (Services.vc.compare(hotfixVersion, update.version) >= 0) {
notifyComplete();
return;
}
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
let update = null;
try {
let foundUpdates = yield new Promise((resolve, reject) => {
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
onUpdateCheckComplete: resolve,
onUpdateCheckError: reject
});
});
update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates);
} catch (e) {
// AUC.checkForUpdates already logged the error
}
// Check that we have a hotfix update, and it's newer than the one we already
// have installed (if any)
if (update) {
if (Services.vc.compare(hotfixVersion, update.version) < 0) {
logger.debug("Downloading hotfix version " + update.version);
let aInstall = yield new Promise((resolve, reject) =>
AddonManager.getInstallForURL(update.updateURL, resolve,
"application/x-xpinstall", update.updateHash, null,
null, update.version));
logger.debug("Downloading hotfix version " + update.version);
AddonManager.getInstallForURL(update.updateURL,
function BUC_getInstallForURL(aInstall) {
aInstall.addListener({
onDownloadEnded: function BUC_onDownloadEnded(aInstall) {
try {
@ -1283,17 +1286,15 @@ var AddonManagerInternal = {
});
aInstall.install();
}
}
}
notifyComplete();
}, "application/x-xpinstall", update.updateHash, null,
null, update.version);
},
onUpdateCheckError: notifyComplete
});
}
notifyComplete();
gUpdateCheckInProgress = false;
Services.obs.notifyObservers(null,
"addons-background-update-complete",
null);
}.bind(this));
},
/**

Просмотреть файл

@ -3610,7 +3610,13 @@ this.XPIProvider = {
* The AddonInstall to remove
*/
removeActiveInstall: function XPI_removeActiveInstall(aInstall) {
this.installs = this.installs.filter(function installFilter(i) i != aInstall);
let where = this.installs.indexOf(aInstall);
if (where == -1) {
logger.warn("removeActiveInstall: could not find active install for "
+ aInstall.sourceURI.spec);
return;
}
this.installs.splice(where, 1);
},
/**

Просмотреть файл

@ -75,7 +75,7 @@ function install_test_addons(aCallback) {
// Switch to the test update URL
Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "browser_bug557956.rdf");
aCallback();
executeSoon(aCallback);
}
}
};

Просмотреть файл

@ -41,7 +41,7 @@ add_test(function () {
gInstall = new MockInstall(undefined, undefined, addon);
gInstall.addTestListener({
onNewInstall: function () {
run_next_test();
executeSoon(run_next_test);
}
});
gProvider.addInstall(gInstall);
@ -65,7 +65,7 @@ add_test(function () {
}
}
ok(false, "Item with correct name was not found");
run_next_test();
executeSoon(run_next_test);
}
});
gInstall.install();

Просмотреть файл

@ -21,17 +21,18 @@ var gTestInstallListener = {
onInstallEnded: function(aInstall) {
check_hidden(false);
run_next_test();
executeSoon(run_next_test);
},
onInstallCancelled: function(aInstall) {
ok(gExpectedCancel, "Should expect install cancel");
check_hidden(false);
run_next_test();
executeSoon(run_next_test);
},
onInstallFailed: function(aInstall) {
ok(false, "Did not expect onInstallFailed");
executeSoon(run_next_test);
}
};

Просмотреть файл

@ -40,7 +40,7 @@ function install_locale(aCallback) {
gInstall.addTestListener({
onInstallEnded: function(aInstall) {
gInstall.removeTestListener(this);
aCallback();
executeSoon(aCallback);
}
});
gInstall.install();

Просмотреть файл

@ -97,7 +97,7 @@ add_test(function() {
},
onInstallEnded: function() {
check_list(gItem);
run_next_test();
executeSoon(run_next_test);
}
});
@ -136,7 +136,7 @@ add_test(function() {
onInstallEnded: function() {
check_list(null);
extension.cancel();
run_next_test();
executeSoon(run_next_test);
}
});

Просмотреть файл

@ -15,51 +15,56 @@ const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
const HOTFIX_ID = "hotfix@tests.mozilla.org";
var gNextTest;
var SuccessfulInstallListener = {
onDownloadCancelled: function(aInstall) {
ok(false, "Should not have seen the download cancelled");
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
AddonManager.removeInstallListener(this);
gNextTest();
},
onInstallEnded: function(aInstall) {
ok(true, "Should have seen the install complete");
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
AddonManager.removeInstallListener(this);
aInstall.addon.uninstall();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
gNextTest();
}
/*
* Register an addon install listener and return a promise that:
* resolves with the AddonInstall object if the install succeeds
* rejects with the AddonInstall if the install fails
*/
function promiseInstallListener() {
return new Promise((resolve, reject) => {
let listener = {
onInstallEnded: ai => {
AddonManager.removeInstallListener(listener);
resolve(ai);
},
onDownloadCancelled: ai => {
AddonManager.removeInstallListener(listener);
reject(ai);
}
};
AddonManager.addInstallListener(listener);
});
}
var FailedInstallListener = {
onDownloadCancelled: function(aInstall) {
ok(true, "Should have seen the download cancelled");
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
AddonManager.removeInstallListener(this);
gNextTest();
},
onInstallEnded: function(aInstall) {
ok(false, "Should not have seen the install complete");
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
AddonManager.removeInstallListener(this);
aInstall.addon.uninstall();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
gNextTest();
}
function promiseSuccessfulInstall() {
return promiseInstallListener().then(
aInstall => {
ok(true, "Should have seen the install complete");
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
aInstall.addon.uninstall();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
},
aInstall => {
ok(false, "Should not have seen the download cancelled");
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
});
}
function test() {
waitForExplicitFinish();
function promiseFailedInstall() {
return promiseInstallListener().then(
aInstall => {
ok(false, "Should not have seen the install complete");
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
aInstall.addon.uninstall();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
},
aInstall => {
ok(true, "Should have seen the download cancelled");
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
});
}
add_task(function setup() {
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true);
Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
Services.prefs.setBoolPref(PREF_UPDATE_REQUIREBUILTINCERTS, false);
@ -78,109 +83,85 @@ function test() {
var prefs = Services.prefs.getChildList(PREF_EM_HOTFIX_CERTS);
prefs.forEach(Services.prefs.clearUserPref);
});
run_next_test();
}
function end_test() {
finish();
}
add_test(function check_no_cert_checks() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false);
AddonManager.addInstallListener(SuccessfulInstallListener);
gNextTest = run_next_test;
AddonManagerPrivate.backgroundUpdateCheck();
});
add_test(function check_wrong_cert_fingerprint() {
add_task(function* check_no_cert_checks() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false);
yield Promise.all([
promiseSuccessfulInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
});
add_task(function* check_wrong_cert_fingerprint() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo");
AddonManager.addInstallListener(FailedInstallListener);
gNextTest = function() {
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
run_next_test();
};
AddonManagerPrivate.backgroundUpdateCheck();
yield Promise.all([
promiseFailedInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
});
add_test(function check_right_cert_fingerprint() {
add_task(function* check_right_cert_fingerprint() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
AddonManager.addInstallListener(SuccessfulInstallListener);
yield Promise.all([
promiseSuccessfulInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
gNextTest = function() {
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
run_next_test();
};
AddonManagerPrivate.backgroundUpdateCheck();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
});
add_test(function check_multi_cert_fingerprint_1() {
add_task(function* check_multi_cert_fingerprint_1() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "foo");
AddonManager.addInstallListener(SuccessfulInstallListener);
yield Promise.all([
promiseSuccessfulInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
gNextTest = function() {
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
run_next_test();
};
AddonManagerPrivate.backgroundUpdateCheck();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
});
add_test(function check_multi_cert_fingerprint_2() {
add_task(function* check_multi_cert_fingerprint_2() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo");
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
AddonManager.addInstallListener(SuccessfulInstallListener);
yield Promise.all([
promiseSuccessfulInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
gNextTest = function() {
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
run_next_test();
};
AddonManagerPrivate.backgroundUpdateCheck();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
});
add_test(function check_no_cert_no_checks() {
add_task(function* check_no_cert_no_checks() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false);
Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, TESTROOT + "unsigned_hotfix.rdf");
AddonManager.addInstallListener(SuccessfulInstallListener);
gNextTest = run_next_test;
AddonManagerPrivate.backgroundUpdateCheck();
yield Promise.all([
promiseSuccessfulInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
});
add_test(function check_no_cert_cert_fingerprint_check() {
add_task(function* check_no_cert_cert_fingerprint_check() {
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
AddonManager.addInstallListener(FailedInstallListener);
yield Promise.all([
promiseFailedInstall(),
AddonManagerPrivate.backgroundUpdateCheck()
]);
gNextTest = function() {
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
run_next_test();
};
AddonManagerPrivate.backgroundUpdateCheck();
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
});

Просмотреть файл

@ -184,7 +184,7 @@ add_test(function() {
is_element_hidden(item._installStatus, "Install progress widget should be hidden");
if (badgeUpdated)
run_next_test();
executeSoon(run_next_test);
else
installCompleted = true;
}

Просмотреть файл

@ -566,7 +566,7 @@ add_test(function() {
is(installBtn.hidden, true, "Install button should be hidden after install ended");
check_filtered_results(QUERY, "relevancescore", false);
run_next_test();
executeSoon(run_next_test);
}
}

Просмотреть файл

@ -30,7 +30,7 @@ function install_test_addon(aCallback) {
onInstallEnded: function() {
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
gTestAddon = addon;
aCallback();
executeSoon(aCallback);
});
}
};