Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-03-24 15:38:14 +01:00
Родитель 60e4e48de3 9a22ffe8aa
Коммит 543901014d
76 изменённых файлов: 1514 добавлений и 346 удалений

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

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

@ -4,6 +4,6 @@
"branch": "",
"revision": ""
},
"revision": "340ca395d9cbeedd3d25abf2c12549b99dbf0a11",
"revision": "c4bd8e11f0a758c307494392f6cc0d725674c224",
"repo_path": "/integration/gaia-central"
}

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

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

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

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

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

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>

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

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3286e2a0cbcac52e38c0494ab614bac23cdc229f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3977de3c913fedb331ad2445ad245501e3a62239"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

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

@ -1,3 +1,5 @@
// Force SafeBrowsing to be initialized for the tests
Services.prefs.setCharPref("urlclassifier.malware_table", "test-malware-simple");
Services.prefs.setCharPref("urlclassifier.phish_table", "test-phish-simple");
SafeBrowsing.init();

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

@ -28,6 +28,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryPing",
"resource://gre/modules/TelemetryPing.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryLog",
"resource://gre/modules/TelemetryLog.jsm");
// CertUtils.jsm doesn't expose a single "CertUtils" object like a normal .jsm
// would.
XPCOMUtils.defineLazyGetter(this, "CertUtils",
@ -62,6 +64,27 @@ const PREF_BRANCH_TELEMETRY = "toolkit.telemetry.";
const PREF_TELEMETRY_ENABLED = "enabled";
const PREF_TELEMETRY_PRERELEASE = "enabledPreRelease";
const TELEMETRY_LOG = {
// log(key, [kind, experimentId, details])
ACTIVATION_KEY: "EXPERIMENT_ACTIVATION",
ACTIVATION: {
ACTIVATED: "ACTIVATED", // successfully activated
INSTALL_FAILURE: "INSTALL_FAILURE", // failed to install the extension
REJECTED: "REJECTED", // experiment was rejected because of it's conditions,
// provides details on which
},
// log(key, [kind, experimentId, optionalDetails...])
TERMINATION_KEY: "EXPERIMENT_TERMINATION",
TERMINATION: {
USERDISABLED: "USERDISABLED", // the user disabled this experiment
FROM_API: "FROM_API", // the experiment disabled itself
EXPIRED: "EXPIRED", // experiment expired e.g. by exceeding the end-date
RECHECK: "RECHECK", // disabled after re-evaluating conditions,
// provides details on which
},
};
const gPrefs = new Preferences(PREF_BRANCH);
const gPrefsTelemetry = new Preferences(PREF_BRANCH_TELEMETRY);
let gExperimentsEnabled = false;
@ -505,23 +528,34 @@ Experiments.Experiments.prototype = {
},
onDisabled: function (addon) {
this._checkForShutdown();
let experiment = this._experiments.get(addon.id);
if (!experiment) {
return;
}
gLogger.trace("Experiments::onDisabled() - addon id: " + addon.id)
this.disableExperiment(addon.id);
},
onUninstalled: function (addon) {
gLogger.trace("Experiments::onUninstalled() - addon id: " + addon.id);
this.disableExperiment(addon.id);
},
_getExperimentByAddonId: function (addonId) {
for (let [, entry] of this._experiments) {
if (entry._addonId === addonId) {
return entry;
}
}
return null;
},
_disableExperimentByAddonId: function (addonId) {
this._checkForShutdown();
let experiment = this._experiments.get(addon.id);
gLogger.trace("Experiments::disableExperimentByAddonId() - addon id: " + addonId);
let experiment = this._getExperimentByAddonId(addonId);
if (!experiment) {
return;
}
this.disableExperiment(addon.id);
this.disableExperiment(experiment.id);
},
/*
@ -726,11 +760,12 @@ Experiments.Experiments.prototype = {
// Make sure we keep experiments that are or were running.
// We remove them after KEEP_HISTORY_N_DAYS.
for (let [id, entry] of this._experiments) {
if (experiments.has(id) || !entry.startDate || !entry.shouldDiscard()) {
if (experiments.has(id) || !entry.startDate || entry.shouldDiscard()) {
gLogger.trace("Experiments::updateExperiments() - discarding entry for " + id);
continue;
}
experiments.set(id, experiment);
experiments.set(id, entry);
}
this._experiments = experiments;
@ -794,16 +829,25 @@ Experiments.Experiments.prototype = {
}
if (!experiment.enabled) {
return Promise.reject();
let message = "experiment is not enabled";
gLogger.debug("Experiments::disableExperiment() - " + message);
return Promise.reject(new Error(message));
}
return Task.spawn(function* Experiments_disableExperimentTaskOuter() {
gLogger.trace("Experiments_disableExperimentTaskOuter");
// We need to wait on possible previous disable tasks.
yield this._pendingTasks.disableExperiment;
let disableTask = Task.spawn(function* Experiments_disableExperimentTaskInner() {
yield this._pendingTasksDone([this._pendingTasks.disableExperiment]);
yield experiment.stop(userDisabled);
let terminationKind = TELEMETRY_LOG.TERMINATION.USERDISABLED;
if (!userDisabled) {
terminationKind = TELEMETRY_LOG.TERMINATION.FROM_API;
}
yield experiment.stop(terminationKind);
Services.obs.notifyObservers(null, OBSERVER_TOPIC, null);
this._pendingTasks.disableExperiment = null;
}.bind(this));
@ -828,6 +872,7 @@ Experiments.Experiments.prototype = {
this._checkForShutdown();
let activeExperiment = this._getActiveExperiment();
let activeChanged = false;
let now = this._policy.now();
if (activeExperiment) {
let wasStopped = yield activeExperiment.maybeStop();
@ -854,14 +899,23 @@ Experiments.Experiments.prototype = {
if (!activeExperiment) {
for (let [id, experiment] of this._experiments) {
let applicable;
let reason = null;
yield experiment.isApplicable().then(
result => applicable = result,
reason => {
result => {
applicable = false;
// TODO telemetry: experiment rejection reason
reason = result;
}
);
if (!applicable && reason && reason[0] != "was-active") {
// Report this from here to avoid over-reporting.
let desc = TELEMETRY_LOG.ACTIVATION;
let data = [TELEMETRY_LOG.ACTIVATION.REJECTED, id];
data = data.concat(reason);
TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY, data);
}
if (applicable) {
gLogger.debug("Experiments::evaluateExperiments() - activating experiment " + id);
try {
@ -888,22 +942,32 @@ Experiments.Experiments.prototype = {
*/
_scheduleExperimentEvaluation: function () {
this._checkForShutdown();
if (this._timer) {
this._timer.clear();
}
if (!gExperimentsEnabled || this._experiments.length == 0) {
return;
}
let time = new Date(90000, 0, 1, 12).getTime();
let time = null;
let now = this._policy.now().getTime();
for (let [id, experiment] of this._experiments) {
let scheduleTime = experiment.getScheduleTime();
if (scheduleTime > now) {
if (time !== null) {
time = Math.min(time, scheduleTime);
} else {
time = scheduleTime;
}
}
}
if (this._timer) {
this._timer.clear();
if (time === null) {
// No schedule time found.
return;
}
gLogger.trace("Experiments::scheduleExperimentEvaluation() - scheduling for "+time+", now: "+now);
@ -940,6 +1004,7 @@ Experiments.ExperimentEntry = function (policy) {
this._name = null;
this._description = null;
this._homepageURL = null;
this._addonId = null;
};
Experiments.ExperimentEntry.prototype = {
@ -1151,7 +1216,7 @@ Experiments.ExperimentEntry.prototype = {
// Not applicable if it already ran.
if (!this.enabled && this._endDate) {
return Promise.reject("was already active");
return Promise.reject(["was-active"]);
}
// Define and run the condition checks.
@ -1200,7 +1265,7 @@ Experiments.ExperimentEntry.prototype = {
if (!result) {
gLogger.debug("ExperimentEntry::isApplicable() - id="
+ data.id + " - test '" + check.name + "' failed");
return Promise.reject(check.name);
return Promise.reject([check.name]);
}
}
@ -1234,7 +1299,7 @@ Experiments.ExperimentEntry.prototype = {
Cu.evalInSandbox(jsfilter, sandbox);
} catch (e) {
gLogger.error("ExperimentEntry::runFilterFunction() - failed to eval jsfilter: " + e.message);
throw "jsfilter:evalFailure";
throw ["jsfilter-evalfailed"];
}
// You can't insert arbitrarily complex objects into a sandbox, so
@ -1250,13 +1315,17 @@ Experiments.ExperimentEntry.prototype = {
catch (e) {
gLogger.debug("ExperimentEntry::runFilterFunction() - filter function failed: "
+ e.message + ", " + e.stack);
throw "jsfilter:rejected " + e.message;
throw ["jsfilter-threw", e.message];
}
finally {
Cu.nukeSandbox(sandbox);
}
throw new Task.Result(result);
if (!result) {
throw ["jsfilter-false"];
}
throw new Task.Result(true);
}.bind(this));
},
@ -1275,7 +1344,8 @@ Experiments.ExperimentEntry.prototype = {
gLogger.error("ExperimentEntry::start() - " + message);
this._failedStart = true;
// TODO telemetry: install failure
TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
[TELEMETRY_LOG.ACTIVATION.INSTALL_FAILURE, this.id]);
deferred.reject(new Error(message));
};
@ -1283,13 +1353,6 @@ Experiments.ExperimentEntry.prototype = {
let listener = {
onDownloadEnded: install => {
gLogger.trace("ExperimentEntry::start() - onDownloadEnded for " + this.id);
let addon = install.addon;
if (addon.id !== this.id) {
let message = "id mismatch: '" + this.id + "' vs. '" + addon.id + "'";
gLogger.error("ExperimentEntry::start() - " + message);
install.cancel();
}
},
onInstallStarted: install => {
@ -1302,6 +1365,7 @@ Experiments.ExperimentEntry.prototype = {
let addon = install.addon;
this._name = addon.name;
this._addonId = addon.id;
this._description = addon.description || "";
this._homepageURL = addon.homepageURL || "";
},
@ -1312,14 +1376,17 @@ Experiments.ExperimentEntry.prototype = {
this._startDate = this._policy.now();
this._enabled = true;
// TODO telemetry: install success
TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
[TELEMETRY_LOG.ACTIVATION.ACTIVATED, this.id]);
deferred.resolve();
},
};
["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"]
.forEach(what => listener[what] = install => failureHandler(install, what));
.forEach(what => {
listener[what] = install => failureHandler(install, what)
});
install.addListener(listener);
install.install();
@ -1334,11 +1401,13 @@ Experiments.ExperimentEntry.prototype = {
/*
* Stop running the experiment if it is active.
* @param userDisabled (optional) Whether this is disabled by user action, defaults to false.
* @param terminationKind (optional) The termination kind, e.g. USERDISABLED or EXPIRED.
* @param terminationReason (optional) The termination reason details for
* termination kind RECHECK.
* @return Promise<> Resolved when the operation is complete.
*/
stop: function (userDisabled=false) {
gLogger.trace("ExperimentEntry::stop() - id=" + this.id + ", userDisabled=" + userDisabled);
stop: function (terminationKind, terminationReason) {
gLogger.trace("ExperimentEntry::stop() - id=" + this.id + ", terminationKind=" + terminationKind);
if (!this._enabled) {
gLogger.warning("ExperimentEntry::stop() - experiment not enabled: " + id);
return Promise.reject();
@ -1352,7 +1421,7 @@ Experiments.ExperimentEntry.prototype = {
this._endDate = now;
};
AddonManager.getAddonByID(this.id, addon => {
AddonManager.getAddonByID(this._addonId, addon => {
if (!addon) {
let message = "could not get Addon for " + this.id;
gLogger.warn("ExperimentEntry::stop() - " + message);
@ -1363,11 +1432,12 @@ Experiments.ExperimentEntry.prototype = {
let listener = {};
let handler = addon => {
if (addon.id !== this.id) {
if (addon.id !== this._addonId) {
return;
}
updateDates();
this._logTermination(terminationKind, terminationReason);
AddonManager.removeAddonListener(listener);
deferred.resolve();
@ -1379,13 +1449,29 @@ Experiments.ExperimentEntry.prototype = {
AddonManager.addAddonListener(listener);
addon.uninstall();
// TODO telemetry: experiment disabling, differentiate by userDisabled
});
return deferred.promise;
},
_logTermination: function (terminationKind, terminationReason) {
if (terminationKind === undefined) {
return;
}
if (!(terminationKind in TELEMETRY_LOG.TERMINATION)) {
gLogger.warn("ExperimentEntry::stop() - unknown terminationKind " + terminationKind);
return;
}
let data = [terminationKind, this.id];
if (terminationReason) {
data = data.concat(terminationReason);
}
TelemetryLog.log(TELEMETRY_LOG.TERMINATION_KEY, data);
},
/*
* Stop if experiment stop criteria are met.
* @return Promise<boolean> Resolved when done stopping or checking,
@ -1395,11 +1481,17 @@ Experiments.ExperimentEntry.prototype = {
gLogger.trace("ExperimentEntry::maybeStop()");
return Task.spawn(function ExperimentEntry_maybeStop_task() {
let shouldStop = yield this._shouldStop();
if (shouldStop) {
yield this.stop();
let result = yield this._shouldStop();
if (result.shouldStop) {
let expireReasons = ["endTime", "maxActiveSeconds"];
if (expireReasons.indexOf(result.reason[0]) != -1) {
yield this.stop(TELEMETRY_LOG.TERMINATION.EXPIRED);
} else {
yield this.stop(TELEMETRY_LOG.TERMINATION.RECHECK, result.reason);
}
throw new Task.Result(shouldStop);
}
throw new Task.Result(result.shouldStop);
}.bind(this));
},
@ -1409,13 +1501,13 @@ Experiments.ExperimentEntry.prototype = {
let maxActiveSec = data.maxActiveSeconds || 0;
if (!this._enabled) {
return Promise.resolve(false);
return Promise.resolve({shouldStop: false});
}
let deferred = Promise.defer();
this.isApplicable().then(
() => deferred.resolve(false),
() => deferred.resolve(true)
() => deferred.resolve({shouldStop: false}),
reason => deferred.resolve({shouldStop: true, reason: reason})
);
return deferred.promise;

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

@ -25,6 +25,9 @@ const EXPERIMENT2_ID = "test-experiment-2@tests.mozilla.org"
const EXPERIMENT2_XPI_SHA1 = "sha1:81877991ec70360fb48db84c34a9b2da7aa41d6a";
const EXPERIMENT2_XPI_NAME = "experiment-2.xpi";
const EXPERIMENT3_ID = "test-experiment-3@tests.mozilla.org";
const EXPERIMENT4_ID = "test-experiment-4@tests.mozilla.org";
const FAKE_EXPERIMENTS_1 = [
{
id: "id1",
@ -100,6 +103,61 @@ function dateToSeconds(date) {
return date.getTime() / 1000;
}
// Install addon and return a Promise<boolean> that is
// resolve with true on success, false otherwise.
function installAddon(url, hash) {
let deferred = Promise.defer();
let success = () => deferred.resolve(true);
let fail = () => deferred.resolve(false);
let listener = {
onDownloadCancelled: fail,
onDownloadFailed: fail,
onInstallCancelled: fail,
onInstallFailed: fail,
onInstallEnded: success,
};
let installCallback = install => {
install.addListener(listener);
install.install();
};
AddonManager.getInstallForURL(url, installCallback,
"application/x-xpinstall", hash);
return deferred.promise;
}
// Uninstall addon and return a Promise<boolean> that is
// resolve with true on success, false otherwise.
function uninstallAddon(id) {
let deferred = Promise.defer();
AddonManager.getAddonByID(id, addon => {
if (!addon) {
deferred.resolve(false);
}
let listener = {};
let handler = addon => {
if (addon.id !== id) {
return;
}
AddonManager.removeAddonListener(listener);
deferred.resolve(true);
};
listener.onUninstalled = handler;
listener.onDisabled = handler;
AddonManager.addAddonListener(listener);
addon.uninstall();
});
return deferred.promise;
}
function createAppInfo(options) {
const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");

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

@ -118,15 +118,15 @@ add_task(function* test_startStop() {
yield experiment.start();
Assert.equal(experiment.enabled, true, "Experiment should now be enabled.");
let shouldStop = yield experiment._shouldStop();
Assert.equal(shouldStop, false, "shouldStop should be false.");
let result = yield experiment._shouldStop();
Assert.equal(result.shouldStop, false, "shouldStop should be false.");
let maybeStop = yield experiment.maybeStop();
Assert.equal(maybeStop, false, "Experiment should not have been stopped.");
Assert.equal(experiment.enabled, true, "Experiment should be enabled.");
defineNow(gPolicy, futureDate(endDate, MS_IN_ONE_DAY));
shouldStop = yield experiment._shouldStop();
Assert.equal(shouldStop, true, "shouldStop should now be true.");
result = yield experiment._shouldStop();
Assert.equal(result.shouldStop, true, "shouldStop should now be true.");
maybeStop = yield experiment.maybeStop();
Assert.equal(maybeStop, true, "Experiment should have been stopped.");
Assert.equal(experiment.enabled, false, "Experiment should be disabled.");

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

@ -797,6 +797,487 @@ add_task(function* test_updateActiveExperiment() {
yield removeCacheFile();
});
// Tests that setting the disable flag for an active experiment
// stops it.
add_task(function* test_disableActiveExperiment() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate),
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called yet.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Trigger update, clock set for the experiment to start.
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
// Trigger an update with the experiment being disabled.
now = futureDate(now, 1 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].disabled = true;
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, false, "Experiment 1 should be disabled.");
// Check that the experiment stays disabled.
now = futureDate(now, 1 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
delete gManifestObject.experiments[0].disabled;
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, false, "Experiment 1 should still be disabled.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
// Test that:
// * setting the frozen flag for a not-yet-started experiment keeps
// it from starting
// * after a removing the frozen flag, the experiment can still start
add_task(function* test_freezePendingExperiment() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate),
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called yet.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Trigger update, clock set for the experiment to start but frozen.
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].frozen = true;
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should have no entries yet.");
// Trigger an update with the experiment not being frozen anymore.
now = futureDate(now, 1 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
delete gManifestObject.experiments[0].frozen;
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should be active now.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
// Test that setting the frozen flag for an active experiment doesn't
// stop it.
add_task(function* test_freezeActiveExperiment() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate),
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called yet.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Trigger update, clock set for the experiment to start.
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match.");
// Trigger an update with the experiment being disabled.
now = futureDate(now, 1 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].frozen = true;
yield experiments.updateManifest();
Assert.equal(observerFireCount, expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should still be active.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
// Test that removing an active experiment from the manifest doesn't
// stop it.
add_task(function* test_removeActiveExperiment() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
let startDate2 = futureDate(baseDate, 20000 * MS_IN_ONE_DAY);
let endDate2 = futureDate(baseDate, 30000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate),
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
{
id: EXPERIMENT2_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT2_XPI_SHA1,
startTime: dateToSeconds(startDate2),
endTime: dateToSeconds(endDate2),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called yet.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Trigger update, clock set for the experiment to start.
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match.");
// Trigger an update with experiment 1 missing from the manifest
now = futureDate(now, 1 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].frozen = true;
yield experiments.updateManifest();
Assert.equal(observerFireCount, expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should still be active.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
// Test that we correctly handle experiment start & install failures.
add_task(function* test_invalidUrl() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME + ".invalid",
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: 0,
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set for the experiment to start.
let now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gTimerScheduleOffset = null;
yield experiments.updateManifest();
Assert.equal(observerFireCount, expectedObserverFireCount,
"Experiments observer should not have been called.");
Assert.equal(gTimerScheduleOffset, null, "No new timer should have been scheduled.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
// Test that we handle it properly when active experiment addons are being
// uninstalled.
add_task(function* test_unexpectedUninstall() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedObserverFireCount = 0;
let observer = () => ++observerFireCount;
Services.obs.addObserver(observer, OBSERVER_TOPIC, false);
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate),
endTime: dateToSeconds(endDate),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, 0,
"Experiments observer should not have been called yet.");
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
// Trigger update, clock set for the experiment to start.
now = futureDate(startDate, 10 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.updateManifest();
Assert.equal(observerFireCount, ++expectedObserverFireCount,
"Experiments observer should have been called.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, true, "Experiment 1 should be active.");
// Uninstall the addon through the addon manager instead of stopping it through
// the experiments API.
let success = yield uninstallAddon(EXPERIMENT1_ID);
Assert.ok(success, "Addon should have been uninstalled.");
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry.");
Assert.equal(list[0].active, false, "Experiment 1 should not be active anymore.");
// Cleanup.
Services.obs.removeObserver(observer, OBSERVER_TOPIC);
yield experiments.uninit();
yield removeCacheFile();
});
add_task(function* shutdown() {
yield gReporter._shutdown();
yield removeCacheFile();

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

@ -74,6 +74,20 @@ add_task(function* test_setup() {
let experiments = new Experiments.Experiments();
});
function arraysEqual(a, b) {
if (a.length !== b.length) {
return false;
}
for (let i=0; i<a.length; ++i) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
// This function exists solely to be .toSource()d
const sanityFilter = function filter(c) {
if (c.telemetryPayload === undefined) {
@ -94,18 +108,18 @@ const sanityFilter = function filter(c) {
add_task(function* test_simpleFields() {
let testData = [
// "expected applicable?", failure reason or null, manifest data
[false, "os", {os: ["42", "abcdef"]}],
[false, ["os"], {os: ["42", "abcdef"]}],
[true, null, {os: [gAppInfo.OS, "plan9"]}],
[false, "buildIDs", {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID + "-invalid"]}],
[false, ["buildIDs"], {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID + "-invalid"]}],
[true, null, {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID]}],
[true, null, {jsfilter: "function filter(c) { return true; }"}],
[false, null, {jsfilter: "function filter(c) { return false; }"}],
[false, ["jsfilter-false"], {jsfilter: "function filter(c) { return false; }"}],
[true, null, {jsfilter: "function filter(c) { return 123; }"}], // truthy
[false, null, {jsfilter: "function filter(c) { return ''; }"}], // falsy
[false, null, {jsfilter: "function filter(c) { var a = []; }"}], // undefined
[false, "jsfilter:rejected some error", {jsfilter: "function filter(c) { throw new Error('some error'); }"}],
[false, "jsfilter:evalFailure", {jsfilter: "123, this won't work"}],
[true, {jsfilter: "var filter = " + sanityFilter.toSource()}],
[false, ["jsfilter-false"], {jsfilter: "function filter(c) { return ''; }"}], // falsy
[false, ["jsfilter-false"], {jsfilter: "function filter(c) { var a = []; }"}], // undefined
[false, ["jsfilter-threw", "some error"], {jsfilter: "function filter(c) { throw new Error('some error'); }"}],
[false, ["jsfilter-evalfailed"], {jsfilter: "123, this won't work"}],
[true, null, {jsfilter: "var filter = " + sanityFilter.toSource()}],
];
for (let i=0; i<testData.length; ++i) {
@ -124,8 +138,13 @@ add_task(function* test_simpleFields() {
Assert.equal(applicable, entry[0],
"Experiment entry applicability should match for test "
+ i + ": " + JSON.stringify(entry[2]));
if (!applicable) {
Assert.equal(reason, entry[1], "Experiment rejection reason should match for test " + i);
let expectedReason = entry[1];
if (!applicable && expectedReason) {
Assert.ok(arraysEqual(reason, expectedReason),
"Experiment rejection reasons should match for test " + i + ". "
+ "Got " + JSON.stringify(reason) + ", expected "
+ JSON.stringify(expectedReason));
}
}
});

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

@ -0,0 +1,360 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/TelemetryLog.jsm");
Cu.import("resource://gre/modules/TelemetryPing.jsm");
Cu.import("resource:///modules/experiments/Experiments.jsm");
const FILE_MANIFEST = "experiments.manifest";
const PREF_EXPERIMENTS_ENABLED = "experiments.enabled";
const PREF_LOGGING_LEVEL = "experiments.logging.level";
const PREF_LOGGING_DUMP = "experiments.logging.dump";
const PREF_MANIFEST_URI = "experiments.manifest.uri";
const PREF_FETCHINTERVAL = "experiments.manifest.fetchIntervalSeconds";
const MANIFEST_HANDLER = "manifests/handler";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
let gProfileDir = null;
let gHttpServer = null;
let gHttpRoot = null;
let gDataRoot = null;
let gReporter = null;
let gPolicy = null;
let gManifestObject = null;
let gManifestHandlerURI = null;
const TLOG = {
// log(key, [kind, experimentId, details])
ACTIVATION_KEY: "EXPERIMENT_ACTIVATION",
ACTIVATION: {
ACTIVATED: "ACTIVATED",
INSTALL_FAILURE: "INSTALL_FAILURE",
REJECTED: "REJECTED",
},
// log(key, [kind, experimentId, optionalDetails...])
TERMINATION_KEY: "EXPERIMENT_TERMINATION",
TERMINATION: {
USERDISABLED: "USERDISABLED",
FROM_API: "FROM_API",
EXPIRED: "EXPIRED",
RECHECK: "RECHECK",
},
};
let gGlobalScope = this;
function loadAddonManager() {
let ns = {};
Cu.import("resource://gre/modules/Services.jsm", ns);
let head = "../../../../toolkit/mozapps/extensions/test/xpcshell/head_addons.js";
let file = do_get_file(head);
let uri = ns.Services.io.newFileURI(file);
ns.Services.scriptloader.loadSubScript(uri.spec, gGlobalScope);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
startupManager();
}
function checkEvent(event, id, data)
{
do_print("Checking message " + id);
Assert.equal(event[0], id, "id should match");
Assert.ok(event[1] > 0, "timestamp should be greater than 0");
if (data === undefined) {
Assert.equal(event.length, 2, "event array should have 2 entries");
} else {
Assert.equal(event.length, data.length + 2, "event entry count should match expected count");
for (var i = 0; i < data.length; ++i) {
Assert.equal(typeof(event[i + 2]), "string", "event entry should be a string");
Assert.equal(event[i + 2], data[i], "event entry should match expected entry");
}
}
}
function run_test() {
run_next_test();
}
add_task(function* test_setup() {
loadAddonManager();
gProfileDir = do_get_profile();
gHttpServer = new HttpServer();
gHttpServer.start(-1);
let port = gHttpServer.identity.primaryPort;
gHttpRoot = "http://localhost:" + port + "/";
gDataRoot = gHttpRoot + "data/";
gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
gHttpServer.registerDirectory("/data/", do_get_cwd());
gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => {
response.setStatusLine(null, 200, "OK");
response.write(JSON.stringify(gManifestObject));
response.processAsync();
response.finish();
});
do_register_cleanup(() => gHttpServer.stop(() => {}));
disableCertificateChecks();
Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true);
Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI);
Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0);
gReporter = yield getReporter("json_payload_simple");
yield gReporter.collectMeasurements();
let payload = yield gReporter.getJSONPayload(true);
gPolicy = new Experiments.Policy();
let dummyTimer = { cancel: () => {}, clear: () => {} };
patchPolicy(gPolicy, {
updatechannel: () => "nightly",
healthReportPayload: () => Promise.resolve(payload),
oneshotTimer: (callback, timeout, thisObj, name) => dummyTimer,
});
yield removeCacheFile();
});
// Test basic starting and stopping of experiments.
add_task(function* test_telemetryBasics() {
const OBSERVER_TOPIC = "experiments-changed";
let observerFireCount = 0;
let expectedLogLength = 0;
// Dates the following tests are based on.
let baseDate = new Date(2014, 5, 1, 12);
let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY);
let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY);
let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY);
// The manifest data we test with.
gManifestObject = {
"version": 1,
experiments: [
{
id: EXPERIMENT1_ID,
xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
xpiHash: EXPERIMENT1_XPI_SHA1,
startTime: dateToSeconds(startDate1),
endTime: dateToSeconds(endDate1),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
{
id: EXPERIMENT2_ID,
xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME,
xpiHash: EXPERIMENT2_XPI_SHA1,
startTime: dateToSeconds(startDate2),
endTime: dateToSeconds(endDate2),
maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
appName: ["XPCShell"],
channel: ["nightly"],
},
],
};
// Data to compare the result of Experiments.getExperiments() against.
let experimentListData = [
{
id: EXPERIMENT2_ID,
name: "Test experiment 2",
description: "And yet another experiment that experiments experimentally.",
},
{
id: EXPERIMENT1_ID,
name: EXPERIMENT1_NAME,
description: "Yet another experiment that experiments experimentally.",
},
];
let experiments = new Experiments.Experiments(gPolicy);
// Trigger update, clock set to before any activation.
// Use updateManifest() to provide for coverage of that path.
let now = baseDate;
defineNow(gPolicy, now);
yield experiments.updateManifest();
let list = yield experiments.getExperiments();
Assert.equal(list.length, 0, "Experiment list should be empty.");
expectedLogLength += 2;
let log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-2], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.REJECTED, EXPERIMENT1_ID, "startTime"]);
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]);
// Trigger update, clock set for experiment 1 to start.
now = futureDate(startDate1, 5 * MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT1_ID]);
// Trigger update, clock set for experiment 1 to stop.
now = futureDate(endDate1, 1000);
defineNow(gPolicy, now);
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entry.");
expectedLogLength += 2;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-2], TLOG.TERMINATION_KEY,
[TLOG.TERMINATION.EXPIRED, EXPERIMENT1_ID]);
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]);
// Trigger update, clock set for experiment 2 to start with invalid hash.
now = startDate2;
defineNow(gPolicy, now);
gManifestObject.experiments[1].xpiHash = "sha1:0000000000000000000000000000000000000000";
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 1, "Experiment list should have 1 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.INSTALL_FAILURE, EXPERIMENT2_ID]);
// Trigger update, clock set for experiment 2 to properly start now.
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[1].xpiHash = EXPERIMENT2_XPI_SHA1;
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 2, "Experiment list should have 2 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT2_ID]);
// Fake user-disable of an experiment.
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.disableExperiment(EXPERIMENT2_ID);
list = yield experiments.getExperiments();
Assert.equal(list.length, 2, "Experiment list should have 2 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
[TLOG.TERMINATION.USERDISABLED, EXPERIMENT2_ID]);
// Trigger update with experiment 1a ready to start.
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].id = EXPERIMENT3_ID;
gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY));
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 3, "Experiment list should have 3 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT3_ID]);
// Trigger non-user-disable of an experiment via the API
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
yield experiments.disableExperiment(EXPERIMENT3_ID, false);
list = yield experiments.getExperiments();
Assert.equal(list.length, 3, "Experiment list should have 3 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
[TLOG.TERMINATION.FROM_API, EXPERIMENT3_ID]);
// Trigger update with experiment 1a ready to start.
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].id = EXPERIMENT4_ID;
gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY));
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 4, "Experiment list should have 4 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
[TLOG.ACTIVATION.ACTIVATED, EXPERIMENT4_ID]);
// Trigger experiment termination by something other than expiry via the manifest.
now = futureDate(now, MS_IN_ONE_DAY);
defineNow(gPolicy, now);
gManifestObject.experiments[0].os = "Plan9";
yield experiments.updateManifest();
list = yield experiments.getExperiments();
Assert.equal(list.length, 4, "Experiment list should have 4 entries.");
expectedLogLength += 1;
log = TelemetryPing.getPayload().log;
Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
[TLOG.TERMINATION.RECHECK, EXPERIMENT4_ID, "os"]);
// Cleanup.
yield experiments.uninit();
yield removeCacheFile();
});
add_task(function* shutdown() {
yield gReporter._shutdown();
yield removeCacheFile();
});

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

@ -12,4 +12,5 @@ support-files =
[test_api.js]
[test_conditions.js]
[test_fetch.js]
[test_telemetry.js]
[test_healthreport.js]

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

@ -1,13 +1,13 @@
default-preferences pref(dom.forms.number,true)
needs-focus == input-load.html input-ref.html
needs-focus == input-create.html input-ref.html
needs-focus == input-number.html input-number-ref.html
needs-focus == button-load.html button-ref.html
needs-focus == button-create.html button-ref.html
needs-focus == textarea-load.html textarea-ref.html
needs-focus == textarea-create.html textarea-ref.html
needs-focus == select-load.html select-ref.html
needs-focus == select-create.html select-ref.html
skip-if(B2G) needs-focus == input-load.html input-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == input-create.html input-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == input-number.html input-number-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == button-load.html button-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == button-create.html button-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == textarea-load.html textarea-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == textarea-create.html textarea-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == select-load.html select-ref.html # B2G timed out waiting for reftest-wait to be removed
skip-if(B2G) needs-focus == select-create.html select-ref.html # B2G timed out waiting for reftest-wait to be removed
needs-focus == autofocus-after-load.html autofocus-after-load-ref.html
needs-focus == autofocus-leaves-iframe.html autofocus-leaves-iframe-ref.html
fails-if(B2G) needs-focus == autofocus-leaves-iframe.html autofocus-leaves-iframe-ref.html # B2G focus difference between test and reference
skip-if(B2G) needs-focus == autofocus-after-body-focus.html autofocus-after-body-focus-ref.html # bug 773482

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

@ -31,6 +31,7 @@
#include "mozilla/ipc/UnixSocket.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
using namespace mozilla;
using namespace mozilla::ipc;
@ -801,7 +802,7 @@ BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
nsAutoString replyError;
DispatchBluetoothReply(runnable.get(), v, replyError);
runnable.forget();
unused << runnable.forget(); // picked up in DispatchBluetoothReply
return NS_OK;
}

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

@ -46,6 +46,7 @@
#include "mozilla/Mutex.h"
#include "mozilla/NullPtr.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/unused.h"
#if defined(MOZ_WIDGET_GONK)
#include "cutils/properties.h"
@ -1116,7 +1117,7 @@ AppendDeviceName(BluetoothSignal& aSignal)
NS_ENSURE_TRUE_VOID(success);
handler.forget();
unused << handler.forget(); // picked up by callback handler
}
static DBusHandlerResult
@ -1461,7 +1462,7 @@ private:
NS_ENSURE_TRUE(success, false);
handler.forget();
unused << handler.forget(); // picked up by callback handler
return true;
}
@ -1505,7 +1506,7 @@ public:
NS_ENSURE_TRUE_VOID(success);
handler.forget();
unused << handler.forget(); /* picked up by callback handler */
}
private:
@ -2191,7 +2192,7 @@ protected:
return false;
}
handler.forget();
unused << handler.forget(); // picked up by callback handler
return true;
}
@ -2251,7 +2252,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
handler.forget();
unused << handler.forget(); // picked up by callback handler
}
private:
@ -2321,7 +2322,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
}
private:
@ -2596,7 +2597,7 @@ protected:
NS_ENSURE_TRUE(success, false);
handler.forget();
unused << handler.forget(); // picked up by callback handler
return true;
}
@ -2757,7 +2758,7 @@ public:
1000, msg);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
}
private:
@ -2912,7 +2913,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
/**
* FIXME: Bug 820274
@ -2984,7 +2985,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
}
protected:
@ -3511,7 +3512,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
handler.forget();
unused << handler.forget(); // picked up by callback handler
}
private:
@ -3813,7 +3814,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
}
private:
@ -3941,7 +3942,7 @@ public:
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE_VOID(success);
mRunnable.forget();
unused << mRunnable.forget(); // picked up by callback handler
}
private:

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

@ -46,10 +46,10 @@
== dir_auto-pre-N-EN.html dir_auto-pre-N-EN-ref.html
== dir_auto-R.html dir_auto-R-ref.html
== dir_auto-textarea-mixed.html dir_auto-textarea-mixed-ref.html
== dir_auto-textarea-N-between-Rs.html dir_auto-textarea-N-between-Rs-ref.html
fails-if(B2G) == dir_auto-textarea-N-between-Rs.html dir_auto-textarea-N-between-Rs-ref.html # B2G scrollbar on opposite side
== dir_auto-textarea-N-EN.html dir_auto-textarea-N-EN-ref.html
== dir_auto-textarea-script-mixed.html dir_auto-textarea-script-mixed-ref.html
== dir_auto-textarea-script-N-between-Rs.html dir_auto-textarea-script-N-between-Rs-ref.html
fails-if(B2G) == dir_auto-textarea-script-N-between-Rs.html dir_auto-textarea-script-N-between-Rs-ref.html # B2G scrollbar on reference only
== dir_auto-textarea-script-N-EN.html dir_auto-textarea-script-N-EN-ref.html
== lang-xyzzy.html lang-xyzzy-ref.html
== lang-xmllang-01.html lang-xmllang-01-ref.html

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

@ -61,7 +61,7 @@ needs-focus == caret_on_focus.html caret_on_focus-ref.html
needs-focus != caret_on_textarea_lastline.html caret_on_textarea_lastline-ref.html
needs-focus == input-text-onfocus-reframe.html input-text-onfocus-reframe-ref.html
needs-focus == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe-ref.html
needs-focus == caret_after_reframe.html caret_after_reframe-ref.html
skip-if(B2G) needs-focus == caret_after_reframe.html caret_after_reframe-ref.html # B2G timed out waiting for reftest-wait to be removed
== nobogusnode-1.html nobogusnode-ref.html
== nobogusnode-2.html nobogusnode-ref.html
== spellcheck-hyphen-valid.html spellcheck-hyphen-valid-ref.html
@ -110,7 +110,7 @@ needs-focus == 824080-7.html 824080-7-ref.html
needs-focus != 824080-6.html 824080-7.html
# Bug 674927: copy spellcheck-textarea tests to contenteditable
== spellcheck-contenteditable-attr.html spellcheck-contenteditable-nofocus-ref.html
fails-if(Android) needs-focus != spellcheck-contenteditable-attr.html spellcheck-contenteditable-ref.html
fails-if(Android||B2G) needs-focus != spellcheck-contenteditable-attr.html spellcheck-contenteditable-ref.html # B2G no spellcheck underline
needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-ref.html
needs-focus == spellcheck-contenteditable-focused-reframe.html spellcheck-contenteditable-ref.html
== spellcheck-contenteditable-nofocus.html spellcheck-contenteditable-disabled-ref.html

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

@ -1945,7 +1945,7 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd)
nscoord parentDescent = fm->MaxDescent();
if (frameSpan) {
pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent -
pfd->mBounds.BStart(lineWM) +
pfd->mBounds.BSize(lineWM) +
pfd->mBorderPadding.BEnd(frameWM) -
frameSpan->mBEndLeading;
}

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

@ -140,5 +140,5 @@ skip-if(B2G) == 726420-1.html 726420-1-ref.html
== 779003-1-dynamic.html 779003-1-ref.html
== 847242-1.html 847242-1-ref.html
== 869833-1.xul 869833-1-ref.xul
== 922530-1.html 922530-1-ref.html
fails-if(B2G) == 922530-1.html 922530-1-ref.html # B2G kerning
== 922550-1.html 922550-1-ref.html

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

@ -15,8 +15,8 @@
!= different-h-v-2.html different-h-v-ref.html
!= different-h-v-1.html different-h-v-2.html
== center-scaling-1.html center-scaling-1-ref.html
== center-scaling-2.html center-scaling-2-ref.html
== center-scaling-3.html center-scaling-3-ref.html
fails-if(Android||B2G) == center-scaling-2.html center-scaling-2-ref.html # Android/B2G: very different scaling (blurriness) on some sides
fails-if(Android||B2G) == center-scaling-3.html center-scaling-3-ref.html # Android/B2G: very different scaling (blurriness) on some sides
== center-scaling-4t.html center-scaling-4t-ref.html
== center-scaling-4r.html center-scaling-4r-ref.html
== center-scaling-4b.html center-scaling-4b-ref.html

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

@ -2,15 +2,15 @@
!= boxshadow-blur.html boxshadow-blur-notref.html
!= boxshadow-blur.html boxshadow-blur-notref2.html
random == boxshadow-blur-2.html boxshadow-blur-2-ref.html # fixedpoint division in blur code makes this fail
random fails-if(Android) != boxshadow-blur-2.html boxshadow-blur-2-notref.html # fixedpoint division in blur code makes this fail
random != boxshadow-blur-2.html boxshadow-blur-2-notref.html # fixedpoint division in blur code makes this fail
== boxshadow-multiple.html boxshadow-multiple-ref.html
== boxshadow-spread.html boxshadow-spread-ref.html
== tableboxshadow-basic.html tableboxshadow-basic-ref.html
== tableboxshadow-trshadow.html tableboxshadow-trshadow-ref.html
== tableboxshadow-tdshadow.html tableboxshadow-tdshadow-ref.html
== boxshadow-rounding.html boxshadow-rounding-ref.html
fails-if(Android) == boxshadow-button.html boxshadow-button-ref.html
fails-if(Android) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
fails-if(Android||B2G) == boxshadow-button.html boxshadow-button-ref.html
fails-if(Android||B2G) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
== boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html
random-if(d2d) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html
@ -25,6 +25,6 @@ random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html
== overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html
== overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html
== overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
fails-if(Android) == 611574-1.html 611574-1-ref.html
fails-if(Android) == 611574-2.html 611574-2-ref.html
fails-if(Android||B2G) == 611574-1.html 611574-1-ref.html
fails-if(Android||B2G) == 611574-2.html 611574-2-ref.html
fuzzy-if(winWidget,5,30) == fieldset.html fieldset-ref.html # minor anti-aliasing problem on Windows

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

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
@font-face {
src: url(../fonts/Ahem.ttf);
font-family: AhemReftest;
}
span { line-height: 1.0; font-family: AhemReftest; font-size: 30px }
</style>
</head>
<body>
<div>
<span>XXX
<span style="vertical-align:text-bottom">XXX</span>
<span style="vertical-align:text-top">XXX</span>
</span>
</div>
</body>
</html>

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

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
@font-face {
src: url(../fonts/Ahem.ttf);
font-family: AhemReftest;
}
span { line-height: 1.0; font-family: AhemReftest; font-size: 30px }
</style>
</head>
<body>
<div>
<span>XXX XXX XXX</span>
</div>
</body>
</html>

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

@ -1803,3 +1803,4 @@ skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
== 983084-1.html 983084-1-ref.html
== 983084-2.html 983084-2-ref.html
== 983084-3.html 983084-1-ref.html
== 983691-1.html 983691-ref.html

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

@ -68,7 +68,7 @@
== counter-ua-limits-list-00.html counter-ua-limits-list-00-ref.html
== counter-ua-limits-list-01.html counter-ua-limits-list-01-ref.html
== multiple-thai-counters.html multiple-thai-counters-ref.html
== counter-suffix.html counter-suffix-ref.html
fails-if(B2G) == counter-suffix.html counter-suffix-ref.html # B2G kerning
== counter-cjk-decimal.html counter-cjk-decimal-ref.html
== counter-japanese-informal.html counter-japanese-informal-ref.html
== counter-japanese-formal.html counter-japanese-formal-ref.html

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

@ -1,9 +1,9 @@
== button-fieldset-1.html button-fieldset-ref.html
fails-if(Android) == button-fieldset-2.html button-fieldset-ref.html
fails-if(Android) == button-fieldset-3.html button-fieldset-ref.html
fails-if(Android||B2G) == button-fieldset-2.html button-fieldset-ref.html
fails-if(Android||B2G) == button-fieldset-3.html button-fieldset-ref.html
== button-fieldset-4.html button-fieldset-ref.html
== button-fieldset-legend-1.html button-fieldset-legend-ref-1.html
fails-if(Android) == button-fieldset-legend-2.html button-fieldset-legend-ref-2.html
fails-if(Android) == button-fieldset-legend-3.html button-fieldset-legend-ref-3.html
fails-if(Android||B2G) == button-fieldset-legend-2.html button-fieldset-legend-ref-2.html
fails-if(Android||B2G) == button-fieldset-legend-3.html button-fieldset-legend-ref-3.html
== button-fieldset-legend-4.html button-fieldset-legend-ref-4.html
== button-fieldset-legend-5.html button-fieldset-legend-ref-5.html

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

@ -1,9 +1,9 @@
== select-fieldset-1.html select-fieldset-ref.html
fails-if(Android) == select-fieldset-2.html select-fieldset-ref-disabled.html
fails-if(Android) == select-fieldset-3.html select-fieldset-ref-disabled.html
fails-if(Android) == select-fieldset-4.html select-fieldset-ref.html
fails-if(Android||B2G) == select-fieldset-2.html select-fieldset-ref-disabled.html
fails-if(Android||B2G) == select-fieldset-3.html select-fieldset-ref-disabled.html
== select-fieldset-4.html select-fieldset-ref.html
== select-fieldset-legend-1.html select-fieldset-legend-ref-1.html
fails-if(Android) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html
fails-if(Android) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html
fails-if(Android||B2G) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html
fails-if(Android||B2G) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html
== select-fieldset-legend-4.html select-fieldset-legend-ref-4.html
== select-fieldset-legend-5.html select-fieldset-legend-ref-5.html

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

@ -1,9 +1,9 @@
== button-fieldset-1.html button-fieldset-ref.html
fails-if(Android) == button-fieldset-2.html button-fieldset-ref.html
fails-if(Android) == button-fieldset-3.html button-fieldset-ref.html
fails-if(Android||B2G) == button-fieldset-2.html button-fieldset-ref.html
fails-if(Android||B2G) == button-fieldset-3.html button-fieldset-ref.html
== button-fieldset-4.html button-fieldset-ref.html
== button-fieldset-legend-1.html button-fieldset-legend-ref-1.html
fails-if(Android) == button-fieldset-legend-2.html button-fieldset-legend-ref-2.html
fails-if(Android) == button-fieldset-legend-3.html button-fieldset-legend-ref-3.html
fails-if(Android||B2G) == button-fieldset-legend-2.html button-fieldset-legend-ref-2.html
fails-if(Android||B2G) == button-fieldset-legend-3.html button-fieldset-legend-ref-3.html
== button-fieldset-legend-4.html button-fieldset-legend-ref-4.html
== button-fieldset-legend-5.html button-fieldset-legend-ref-5.html

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

@ -1,9 +1,9 @@
== select-fieldset-1.html select-fieldset-ref.html
fails-if(Android) == select-fieldset-2.html select-fieldset-ref-disabled.html
fails-if(Android) == select-fieldset-3.html select-fieldset-ref-disabled.html
fails-if(Android||B2G) == select-fieldset-2.html select-fieldset-ref-disabled.html
fails-if(Android||B2G) == select-fieldset-3.html select-fieldset-ref-disabled.html
== select-fieldset-4.html select-fieldset-ref.html
== select-fieldset-legend-1.html select-fieldset-legend-ref-1.html
fails-if(Android) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html
fails-if(Android) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html
fails-if(Android||B2G) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html
fails-if(Android||B2G) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html
== select-fieldset-legend-4.html select-fieldset-legend-ref-4.html
== select-fieldset-legend-5.html select-fieldset-legend-ref-5.html

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

@ -1,7 +1,7 @@
== input-valid.html input-ref.html
fuzzy(11,4) == input-customerror.html input-ref.html
fails-if(Android) == input-disabled.html input-ref.html
fails-if(Android) == input-dyn-disabled.html input-ref.html
fails-if(Android||B2G) == input-disabled.html input-ref.html
fails-if(Android||B2G) == input-dyn-disabled.html input-ref.html
== input-dyn-not-disabled.html input-ref.html
== input-dyn-not-disabled-changed.html input-ref.html
== input-readonly.html input-ref.html

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

@ -12,7 +12,7 @@ needs-focus == select-required-valid-changed-2.html select-required-ref.html
needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html
needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html
fuzzy(64,4) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html
fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html
fails-if(Android) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
fails-if(Android||B2G) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html
fails-if(Android||B2G) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html
needs-focus == select-novalidate.html select-required-ref.html

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

@ -1,7 +1,7 @@
== input-valid.html input-ref.html
fuzzy(64,4) == input-customerror.html input-ref.html
fails-if(Android) == input-disabled.html input-ref.html
fails-if(Android) == input-dyn-disabled.html input-ref.html
fails-if(Android||B2G) == input-disabled.html input-ref.html
fails-if(Android||B2G) == input-dyn-disabled.html input-ref.html
== input-dyn-not-disabled.html input-ref.html
== input-readonly.html input-ref.html
== input-dyn-readonly.html input-ref.html

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

@ -7,6 +7,6 @@ needs-focus == select-required-invalid.html select-required-ref.html
needs-focus == select-required-valid.html select-required-ref.html
needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html
needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html
fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html
fails-if(Android) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
fails-if(Android||B2G) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html
fails-if(Android||B2G) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html

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

@ -1,6 +1,6 @@
== textarea-valid.html textarea-ref.html
fuzzy(11,4) == textarea-customerror.html textarea-ref.html
fails-if(Android) == textarea-disabled.html textarea-ref.html
fails-if(Android||B2G) == textarea-disabled.html textarea-ref.html
fuzzy(11,4) fails-if(Android||B2G) == textarea-dyn-disabled.html textarea-ref.html
fuzzy(11,4) == textarea-dyn-not-disabled.html textarea-ref.html
== textarea-readonly.html textarea-ref.html

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

@ -23,7 +23,7 @@ fails == quote-1e.html quote-1-ref.html # bug 509685
== quote-1e.html quote-1b.html
== quote-1f.html quote-1-ref.html
fails == dynamic-1.html dynamic-1-ref.html # bug 8253
fails-if(Android) random-if(d2d) == dynamic-2.html dynamic-2-ref.html
random-if(d2d) == dynamic-2.html dynamic-2-ref.html
== dynamic-3a.html dynamic-3-ref.html
== dynamic-3b.html dynamic-3-ref.html
== 23605-1.html 23605-1-ref.html
@ -59,7 +59,7 @@ fails-if(!cocoaWidget) == 329069-5.html 329069-5-ref.html # bug 603710
== 469227-1.html 469227-1-ref.html
== 484400-1.html 484400-1-ref.html
== 594303-1.html 594303-1-ref.html
fails-if(!gtk2Widget&&!Android) == 617869-1.html 617869-1-ref.html
fails-if(winWidget||cocoaWidget) == 617869-1.html 617869-1-ref.html
== 723509-1.html 723509-1-ref.html
== 922550-1.html 922550-1-ref.html
== 958249.html 958249-ref.html

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

@ -6,10 +6,10 @@ asserts(1) != first-letter-1.html first-letter-1-noref.html
# The buttons in these tests have some fancy shading applied to their corners
# on B2G, despite their "-moz-appearance: none; background: gray", so they
# don't quite match the reference case's normal <div>. That's why they're fuzzy.
fuzzy-if(B2G,125,20) == percent-height-child-1.html percent-height-child-1-ref.html
fuzzy-if(B2G,125,80) == percent-height-child-2.html percent-height-child-2-ref.html
fuzzy-if(B2G,125,20) == percent-width-child-1.html percent-width-child-1-ref.html
fuzzy-if(B2G,125,80) == percent-width-child-2.html percent-width-child-2-ref.html
fuzzy-if(B2G||Android,125,20) == percent-height-child-1.html percent-height-child-1-ref.html
fuzzy-if(B2G||Android,125,80) == percent-height-child-2.html percent-height-child-2-ref.html
fuzzy-if(B2G||Android,125,20) == percent-width-child-1.html percent-width-child-1-ref.html
fuzzy-if(B2G||Android,125,80) == percent-width-child-2.html percent-width-child-2-ref.html
== vertical-centering.html vertical-centering-ref.html

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

@ -1,8 +1,8 @@
# B2G failures: bug 855352.
fails-if(B2G) fuzzy-if(OSX==10.6,8,128) skip-if(B2G&&browserIsRemote) == simple.html simple-ref.xul # bug 974780
fails-if(B2G) fuzzy-if(OSX==10.6,8,64) skip-if(B2G&&browserIsRemote) == rtl.html rtl-ref.xul # bug 974780
fails-if(B2G) fuzzy-if(OSX==10.6,8,128) skip-if(B2G&&browserIsRemote) == size.html simple-ref.xul # bug 974780
fails-if(B2G) fuzzy-if(OSX==10.6,8,64) skip-if(B2G&&browserIsRemote) == background.html background-ref.xul # bug 974780
fails-if(B2G) skip-if(B2G&&browserIsRemote) == style.html style-ref.xul # bug 974780
fails-if(B2G||Android) fuzzy-if(OSX==10.6,8,128) skip-if(B2G&&browserIsRemote) == simple.html simple-ref.xul # bug 974780
fails-if(B2G||Android) fuzzy-if(OSX==10.6,8,64) skip-if(B2G&&browserIsRemote) == rtl.html rtl-ref.xul # bug 974780
fails-if(B2G||Android) fuzzy-if(OSX==10.6,8,128) skip-if(B2G&&browserIsRemote) == size.html simple-ref.xul # bug 974780
fails-if(B2G||Android) fuzzy-if(OSX==10.6,8,64) skip-if(B2G&&browserIsRemote) == background.html background-ref.xul # bug 974780
fails-if(B2G||Android) skip-if(B2G&&browserIsRemote) == style.html style-ref.xul # bug 974780
!= width-clip.html width-clip-ref.html
fails-if(B2G) == color-inherit.html color-inherit-ref.html
fails-if(B2G||Android) == color-inherit.html color-inherit-ref.html

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

@ -24,10 +24,10 @@ fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),64,4) fuzzy-if(cocoaWidget,63
== number-auto-width-1.html number-auto-width-1-ref.html
# min-height/max-height tests:
skip-if(B2G) == number-min-height-1.html number-min-height-1-ref.html
skip-if(B2G) == number-min-height-2.html number-min-height-2-ref.html
skip-if(B2G) == number-max-height-1.html number-max-height-1-ref.html
skip-if(B2G) == number-max-height-2.html number-max-height-2-ref.html
skip-if(B2G||Android) == number-min-height-1.html number-min-height-1-ref.html
skip-if(B2G||Android) == number-min-height-2.html number-min-height-2-ref.html
skip-if(B2G||Android) == number-max-height-1.html number-max-height-1-ref.html
skip-if(B2G||Android) == number-max-height-2.html number-max-height-2-ref.html
# focus
# autofocus is disabled on B2G

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

@ -27,7 +27,7 @@ fuzzy-if(B2G,1,1) == max-prop.html 100pct-common-ref.html
== direction-unthemed-1.html direction-unthemed-1-ref.html
# ::-moz-range-progress pseudo-element:
fails-if(B2G) == moz-range-progress-1.html moz-range-progress-1-ref.html
fails-if(B2G||Android) == moz-range-progress-1.html moz-range-progress-1-ref.html
== moz-range-progress-2.html moz-range-progress-2-ref.html
== moz-range-progress-3.html moz-range-progress-3-ref.html

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

@ -1,4 +1,4 @@
== values.html values-ref.html
fuzzy-if(Android,128,16) == values.html values-ref.html
== values-rtl.html values-rtl-ref.html
== margin-padding.html margin-padding-ref.html
== margin-padding-rtl.html margin-padding-rtl-ref.html

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

@ -98,9 +98,9 @@ skip-if(B2G) == quotes-1.xhtml quotes-1-ref.xhtml
== mpadded-5.html mpadded-5-ref.html
== mpadded-1-2.html mpadded-1-2-ref.html
== mpadded-6.html mpadded-6-ref.html
== mpadded-7.html mpadded-7-ref.html
== mpadded-8.html mpadded-8-ref.html
== mpadded-9.html mpadded-9-ref.html
fails-if(B2G) == mpadded-7.html mpadded-7-ref.html # B2G: slight character width variation
fails-if(B2G) == mpadded-8.html mpadded-8-ref.html # B2G: slight character width variation
fails-if(B2G) == mpadded-9.html mpadded-9-ref.html # B2G: slight character width variation
== math-display.html math-display-ref.html
== scriptlevel-1.html scriptlevel-1-ref.html
== scriptlevel-movablelimits-1.html scriptlevel-movablelimits-1-ref.html
@ -152,7 +152,7 @@ fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 787215
== operator-1.xhtml operator-1-ref.xhtml
== scriptshift-1.xhtml scriptshift-1-ref.xhtml
== number-size-1.xhtml number-size-1-ref.xhtml
== multiscripts-1.html multiscripts-1-ref.html
fails-if(B2G) == multiscripts-1.html multiscripts-1-ref.html # B2G - slight height variation from font metrics
== mathml-mmultiscript-base.html mathml-mmultiscript-base-ref.html
== mathml-mmultiscript-mprescript.html mathml-mmultiscript-mprescript-ref.html
!= menclose-1a.html menclose-1-ref.html
@ -171,21 +171,21 @@ fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 787215
!= menclose-1n.html menclose-1-ref.html
!= menclose-1o.html menclose-1-ref.html
!= menclose-1p.html menclose-1-ref.html
== menclose-2-actuarial.html menclose-2-actuarial-ref.html
fails-if(B2G) == menclose-2-actuarial.html menclose-2-actuarial-ref.html # B2G slight thickness variation
== menclose-2-bottom.html menclose-2-bottom-ref.html
== menclose-2-box.html menclose-2-box-ref.html
fails-if(B2G) == menclose-2-box.html menclose-2-box-ref.html # B2G slight thickness variation
== menclose-2-circle.html menclose-2-circle-ref.html
== menclose-2-downdiagonalstrike.html menclose-2-downdiagonalstrike-ref.html
== menclose-2-horizontalstrike.html menclose-2-horizontalstrike-ref.html
== menclose-2-left.html menclose-2-left-ref.html
fails-if(B2G) == menclose-2-left.html menclose-2-left-ref.html # B2G slight thickness variation
== menclose-2-longdiv.html menclose-2-longdiv-ref.html
== menclose-2-right.html menclose-2-right-ref.html
== menclose-2-roundedbox.html menclose-2-roundedbox-ref.html
== menclose-2-top.html menclose-2-top-ref.html
== menclose-2-updiagonalarrow.html menclose-2-updiagonalarrow-ref.html
fails-if(B2G) == menclose-2-roundedbox.html menclose-2-roundedbox-ref.html # B2G slight thickness variation
fails-if(B2G) == menclose-2-top.html menclose-2-top-ref.html # B2G slight thickness variation
fails-if(B2G) == menclose-2-updiagonalarrow.html menclose-2-updiagonalarrow-ref.html # B2G slight thickness variation
== menclose-2-updiagonalstrike.html menclose-2-updiagonalstrike-ref.html
== menclose-2-verticalstrike.html menclose-2-verticalstrike-ref.html
== menclose-2-roundedbox.html menclose-2-roundedbox-ref.html
fails-if(B2G) == menclose-2-roundedbox.html menclose-2-roundedbox-ref.html # B2G slight thickness variation
== menclose-3-box.html menclose-3-box-ref.html
== menclose-3-madruwb.html menclose-3-madruwb-ref.html
fails random-if(winWidget) == menclose-3-radical.html menclose-3-radical-ref.html # Bug 973917

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

@ -76,7 +76,9 @@ skip-if(!winWidget) == scroll-thumb-minimum-size-notheme.html scroll-thumb-minim
# These tests have been written to test the overflow of the window widget
# (bug 568825) but we can't test it on Windows and Cocoa because they have
# animated progress bars.
# Nothing shows up on Android, presumably because that appearance type is
# not implemented.
skip-if(cocoaWidget) skip-if(winWidget) == progress-overflow.html progress-overflow-ref.html
skip-if(cocoaWidget) skip-if(winWidget) != progress-overflow-small.html progress-nobar.html
fails-if(Android) skip-if(cocoaWidget) skip-if(winWidget) != progress-overflow-small.html progress-nobar.html
== 676387-1.xul 676387-1-ref.xul

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

@ -60,4 +60,4 @@ skip-if(B2G) == table-caption-splitaftercaption-7.html table-caption-splitafterc
# == table-caption-splitaftercaption-10.html blank.html # bug 672654
# == table-caption-splitaftercaption-11.html blank.html # bug 672654
== column-balancing-break-inside-avoid-2.html column-balancing-break-inside-avoid-2-ref.html
== combobox-page-break-inside.html combobox-page-break-inside-ref.html
fails-if(B2G) == combobox-page-break-inside.html combobox-page-break-inside-ref.html # reftest-print doesn't work on B2G

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

@ -11,7 +11,7 @@ skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollAbsHeightQuirks.html g
skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482
skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-1D.html greenboxhbar.html # bug 650591, 732565 # bug 773482
skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-2D.html greenboxhbar.html # bug 650591, 732565 # bug 773482
fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-3D.html greenboxhbar.html # bug 650591, 732565
fails-if(B2G) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-3D.html greenboxhbar.html # bug 650591, 732565
skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollAbsHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482
skip-if(B2G) fails-if(Android&&browserIsRemote) == hScrollAbsHeightQuirksD.html greenboxhbar.html # bug 650591, 732565 # bug 773482
== simpleMinHeight100D.html greenbox.html

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

@ -5,13 +5,13 @@
== 272830-1.html 272830-1-ref.html
== 318022-1.html 318022-1-ref.html
== 403669-1.html 403669-1-ref.html
== 381497-n.html 381497-f.html
fails-if(B2G) == 381497-n.html 381497-f.html # reftest-print doesn't work on B2G (scrollbar difference only)
== test-async-print.html 272830-1-ref.html
== 129941-1a.html 129941-1-ref.html
fails-if(B2G) == 129941-1a.html 129941-1-ref.html # reftest-print doesn't work on B2G
== 129941-1b.html 129941-1-ref.html
== 609227-1.html 609227-1-ref.html
== 609227-2a.html 609227-2-ref.html
== 609227-2b.html 609227-2-ref.html
fails-if(B2G) == 609227-2a.html 609227-2-ref.html # reftest-print doesn't work on B2G
fails-if(B2G) == 609227-2b.html 609227-2-ref.html # reftest-print doesn't work on B2G
== 577450-1.html 577450-1-ref.html
== 626395-1a.html 626395-1-ref.html
== 626395-1b.html 626395-1-ref.html
@ -20,15 +20,15 @@
== 626395-2c.html 626395-2-ref.html
== 626395-2d.html 626395-2-ref.html
== 652178-1.html 652178-1-ref.html
== 115199-1.html 115199-1-ref.html
fails-if(B2G) == 115199-1.html 115199-1-ref.html # reftest-print doesn't work on B2G
== 115199-2a.html 115199-2-ref.html
== 115199-2b.html 115199-2-ref.html
== 652178-1.html 652178-1-ref2.html
fuzzy-if(cocoaWidget,1,5000) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),255,100) == 745025-1.html 745025-1-ref.html
== 820496-1.html 820496-1-ref.html
fails-if(B2G) fuzzy-if(cocoaWidget,1,5000) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),255,100) == 745025-1.html 745025-1-ref.html # reftest-print doesn't work on B2G
fails-if(B2G) == 820496-1.html 820496-1-ref.html # reftest-print doesn't work on B2G (scrollbar difference only)
# NOTE: These tests don't yet rigorously test what they're
# trying to test (shrink-to-fit behavior), due to bug 967311.
== 960822.html 960822-ref.html
fails-if(B2G) == 960822.html 960822-ref.html # reftest-print doesn't work on B2G (scrollbar difference only)
== 966419-1.html 966419-1-ref.html
== 966419-2.html 966419-2-ref.html

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

@ -12,35 +12,35 @@ include reftest-sanity/reftest.list
include ../../image/test/reftest/reftest.list
# CSSWG tests
skip-if(B2G) include w3c-css/submitted/reftest.list
skip-if(B2G) include w3c-css/received/reftest.list
include w3c-css/submitted/reftest.list
include w3c-css/received/reftest.list
# relative and absolute positioning
skip-if(B2G) include abs-pos/reftest.list
include abs-pos/reftest.list
# backgrounds/
skip-if(B2G) include backgrounds/reftest.list
include backgrounds/reftest.list
# bidi/
skip-if(B2G) include bidi/reftest.list
include bidi/reftest.list
# border-image
skip-if(Android||B2G) include border-image/reftest.list
include border-image/reftest.list
# border-radius/
skip-if(B2G) include border-radius/reftest.list
include border-radius/reftest.list
# -moz-box tests
skip-if(B2G) include box/reftest.list
include box/reftest.list
# box-ordinal/
skip-if(B2G) include box-ordinal/reftest.list
include box-ordinal/reftest.list
# box-properties/
skip-if(B2G) include box-properties/reftest.list
include box-properties/reftest.list
# box-shadow/
skip-if(Android||B2G) include box-shadow/reftest.list
include box-shadow/reftest.list
# bugs/
include bugs/reftest.list
@ -52,70 +52,70 @@ include canvas/reftest.list
include css-animations/reftest.list
# blending/
skip-if(B2G||Android) include css-blending/reftest.list
include css-blending/reftest.list
# css calc() tests
include css-calc/reftest.list
# css character encoding tests
skip-if(B2G) include css-charset/reftest.list
include css-charset/reftest.list
# css default pseudo class tests
skip-if(B2G) include css-default/reftest.list
include css-default/reftest.list
# css :disable tests
skip-if(Android||B2G) include css-disabled/reftest.list
include css-disabled/reftest.list
# css :enable tests
skip-if(Android||B2G) include css-enabled/reftest.list
include css-enabled/reftest.list
# css @import tests
skip-if(B2G) include css-import/reftest.list
include css-import/reftest.list
# css gradients
include css-gradients/reftest.list
# css media queries (tests for print mode)
skip-if(B2G) include css-mediaqueries/reftest.list
include css-mediaqueries/reftest.list
# css parsing
skip-if(B2G) include css-parsing/reftest.list
include css-parsing/reftest.list
# css placeholder
skip-if(B2G) include css-placeholder/reftest.list
include css-placeholder/reftest.list
# css required
skip-if(B2G) include css-required/reftest.list
include css-required/reftest.list
# css optional
skip-if(B2G) include css-optional/reftest.list
include css-optional/reftest.list
# css valid
skip-if(Android||B2G) include css-valid/reftest.list
include css-valid/reftest.list
# css invalid
skip-if(Android||B2G) include css-invalid/reftest.list
include css-invalid/reftest.list
# css-submit-invalid
skip-if(B2G) include css-submit-invalid/reftest.list
include css-submit-invalid/reftest.list
# css text-overflow
skip-if(B2G) include text-overflow/reftest.list
include text-overflow/reftest.list
# css selectors
include css-selectors/reftest.list
# css transitions
skip-if(B2G) include css-transitions/reftest.list
include css-transitions/reftest.list
# css :-moz-ui-invalid
skip-if(Android||B2G) include css-ui-invalid/reftest.list
include css-ui-invalid/reftest.list
# css :-moz-ui-valid
skip-if(Android||B2G) include css-ui-valid/reftest.list
include css-ui-valid/reftest.list
# css values and units
skip-if(B2G) include css-valuesandunits/reftest.list
include css-valuesandunits/reftest.list
# css variables
include css-variables/reftest.list
@ -124,108 +124,109 @@ include css-variables/reftest.list
# layout/style/test/test_visited_reftests instead of using the reftest
# harness.
skip-if(B2G) include cssom/reftest.list
include cssom/reftest.list
# columns/
skip-if(B2G) include columns/reftest.list
include columns/reftest.list
# content/
include ../../content/test/reftest/reftest.list
# counters/
skip-if(B2G) include counters/reftest.list
include counters/reftest.list
# datalist
skip-if(B2G) include datalist/reftest.list
include datalist/reftest.list
# dom/
skip-if(B2G) include dom/reftest.list
include dom/reftest.list
# generated-content/
skip-if(B2G) include generated-content/reftest.list
include generated-content/reftest.list
# first-letter/
skip-if(Android||B2G) include first-letter/reftest.list
include first-letter/reftest.list
# first-line/
skip-if(B2G) include first-line/reftest.list
include first-line/reftest.list
# flexbox (display: flex, display: inline-flex)
include flexbox/reftest.list
# floats/
skip-if(B2G) include floats/reftest.list
include floats/reftest.list
# font-face
include font-face/reftest.list
# font features (opentype)
skip-if(B2G) include font-features/reftest.list
include font-features/reftest.list
# mobile font size inflation
skip-if(B2G&&browserIsRemote) include font-inflation/reftest.list
include font-inflation/reftest.list
# font matching
skip-if(B2G) include font-matching/reftest.list
include font-matching/reftest.list
# forms
skip-if(Android) include forms/reftest.list
include forms/reftest.list
# gfx
include ../../gfx/tests/reftest/reftest.list
# block-inside-inline splits
skip-if(B2G) include ib-split/reftest.list
include ib-split/reftest.list
# image/
include image/reftest.list
# image-element/
skip-if(B2G) include image-element/reftest.list
include image-element/reftest.list
# image-rect/
skip-if(B2G) include image-rect/reftest.list
include image-rect/reftest.list
# image-region/
skip-if(B2G) include image-region/reftest.list
include image-region/reftest.list
# indic shaping with harfbuzz
skip-if(B2G) include indic-shaping/reftest.list
include indic-shaping/reftest.list
# inline layout
include inline/reftest.list
# inline borders and padding
skip-if(B2G) include inline-borderpadding/reftest.list
include inline-borderpadding/reftest.list
# layers/
include layers/reftest.list
# line-breaking/
skip-if(B2G) include line-breaking/reftest.list
include line-breaking/reftest.list
# list-item/
skip-if(B2G) include list-item/reftest.list
include list-item/reftest.list
# mathml/
skip-if(B2G) include mathml/reftest.list
include mathml/reftest.list
# margin-collapsing
skip-if(B2G) include margin-collapsing/reftest.list
include margin-collapsing/reftest.list
# marquee/
skip-if(B2G) include marquee/reftest.list
include marquee/reftest.list
# native-theme/
skip-if(Android||B2G) include native-theme/reftest.list
# skipping for B2G since something around radio-nonnative.html makes the whole suite hang
skip-if(B2G) include native-theme/reftest.list
# netwerk/
skip-if(B2G) include ../../netwerk/test/reftest/reftest.list
include ../../netwerk/test/reftest/reftest.list
include outline/reftest.list
# object/
skip-if(B2G) include object/reftest.list
include object/reftest.list
# ogg-video/
include ogg-video/reftest.list
@ -234,29 +235,29 @@ include ogg-video/reftest.list
include webm-video/reftest.list
# parser/
skip-if(B2G) include ../../parser/htmlparser/tests/reftest/reftest.list
include ../../parser/htmlparser/tests/reftest/reftest.list
# percent-overflow-sizing/
skip-if(B2G) include percent-overflow-sizing/reftest.list
include percent-overflow-sizing/reftest.list
# pixel-rounding/
skip-if(B2G) include pixel-rounding/reftest.list
include pixel-rounding/reftest.list
# plugin/
skip-if(B2G) include ../../dom/plugins/test/reftest/reftest.list
include ../../dom/plugins/test/reftest/reftest.list
# position-dynamic-changes/
include position-dynamic-changes/reftest.list
# printing
skip-if(B2G) include printing/reftest.list
skip-if(B2G) include pagination/reftest.list
include printing/reftest.list
include pagination/reftest.list
# <style scoped>
skip-if(B2G) include scoped-style/reftest.list
include scoped-style/reftest.list
# scrolling
skip-if(Android&&AndroidVersion>=15) include scrolling/reftest.list
include scrolling/reftest.list
# selection
include selection/reftest.list
@ -268,45 +269,45 @@ include position-sticky/reftest.list
include svg/reftest.list
# tab-size/
skip-if(B2G) include tab-size/reftest.list
include tab-size/reftest.list
# table-anonymous-boxes/
skip-if(B2G) include table-anonymous-boxes/reftest.list
include table-anonymous-boxes/reftest.list
# table-background/
skip-if(B2G) include table-background/reftest.list
include table-background/reftest.list
# table-bordercollapse/
skip-if(B2G) include table-bordercollapse/reftest.list
include table-bordercollapse/reftest.list
# table-dom/
skip-if(B2G) include table-dom/reftest.list
include table-dom/reftest.list
skip-if(B2G) include table-overflow/reftest.list
include table-overflow/reftest.list
# table-width/
skip-if(B2G) include table-width/reftest.list
include table-width/reftest.list
# text/
include text/reftest.list
# text-decoration/
skip-if(B2G) include text-decoration/reftest.list
include text-decoration/reftest.list
# text-indent/
skip-if(B2G) include text-indent/reftest.list
include text-indent/reftest.list
# text-shadow/
skip-if(Android||B2G) include text-shadow/reftest.list
include text-shadow/reftest.list
# text-svgglyphs/
include text-svgglyphs/reftest.list
# text-transform/
skip-if(B2G) include text-transform/reftest.list
include text-transform/reftest.list
# theme (osx)
skip-if(B2G) include ../../toolkit/themes/osx/reftests/reftest.list
include ../../toolkit/themes/osx/reftests/reftest.list
# -moz-transform/
include transform/reftest.list
@ -315,45 +316,45 @@ include transform/reftest.list
include transform-3d/reftest.list
# unicode/ (verify that we don't do expend effort doing unicode-aware case checks)
skip-if(B2G) include unicode/reftest.list
include unicode/reftest.list
# webcomonents/
include webcomponents/reftest.list
# widget/
skip-if(B2G) include ../../widget/reftests/reftest.list
include ../../widget/reftests/reftest.list
# xml-stylesheet/
skip-if(B2G) include ../../content/test/reftest/xml-stylesheet/reftest.list
include ../../content/test/reftest/xml-stylesheet/reftest.list
# xul-document-load/
skip-if(B2G) include xul-document-load/reftest.list
include xul-document-load/reftest.list
# xul/
skip-if(B2G) include xul/reftest.list
include xul/reftest.list
# webcomonents/
include webcomponents/reftest.list
# xul
skip-if(B2G) include ../xul/reftest/reftest.list
include ../xul/reftest/reftest.list
# xul grid
skip-if(B2G) include ../xul/grid/reftests/reftest.list
include ../xul/grid/reftests/reftest.list
# z-index/
skip-if(B2G) include z-index/reftest.list
include z-index/reftest.list
# reftest(s) to verify content bugfixes
skip-if(B2G) include ../../content/html/document/reftests/reftests.list
skip-if(B2G) include ../../content/html/content/reftests/reftest.list
skip-if(B2G) include ../../dom/imptests/reftest.list
include ../../content/html/document/reftests/reftests.list
include ../../content/html/content/reftests/reftest.list
include ../../dom/imptests/reftest.list
# editor/
skip-if(B2G) include ../../editor/reftests/reftest.list
include ../../editor/reftests/reftest.list
# box-sizing
skip-if(B2G) include box-sizing/reftest.list
include box-sizing/reftest.list
# invalidation - only run on B2G
skip-if(!B2G) include invalidation/reftest.list

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

@ -12,7 +12,7 @@ skip-if(B2G&&browserIsRemote) HTTP == simple-1.html simple-1.html?ref
skip-if(B2G) HTTP == subpixel-1.html#d subpixel-1-ref.html#d
fuzzy-if(Android,4,120) HTTP == text-1.html text-1.html?ref
fuzzy-if(Android,4,120) HTTP == text-2.html?up text-2.html?ref
skip-if(B2G) fuzzy-if(Android&&AndroidVersion<15,251,722) fails-if(Android&&AndroidVersion>=15) HTTP == transformed-1.html transformed-1.html?ref #Bug 900607
skip-if(B2G) fuzzy-if(Android&&AndroidVersion<15,251,722) HTTP == transformed-1.html transformed-1.html?ref
HTTP == transformed-1.html?up transformed-1.html?ref
fuzzy-if(Android,5,20000) == uncovering-1.html uncovering-1-ref.html
fuzzy-if(Android,5,20000) == uncovering-2.html uncovering-2-ref.html

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

@ -23,10 +23,10 @@
== conflicting-widths-2.html conflicting-widths-ref-100xx.html
== conflicting-widths-3.html conflicting-widths-ref-100xx.html
== conflicting-widths-4.html conflicting-widths-ref-100xx.html
== conflicting-widths-5.html conflicting-widths-5-ref.html
fuzzy-if(B2G,9,1) == conflicting-widths-5.html conflicting-widths-5-ref.html # can't see the difference
== conflicting-widths-6.html conflicting-widths-6-ref.html
== conflicting-widths-7.html conflicting-widths-7-ref.html
== conflicting-widths-8.html conflicting-widths-8-ref.html
fuzzy-if(B2G,9,1) == conflicting-widths-7.html conflicting-widths-7-ref.html # can't see the difference
fuzzy-if(B2G,9,1) == conflicting-widths-8.html conflicting-widths-8-ref.html # can't see the difference
== conflicting-widths-9.html conflicting-widths-9-ref.html
== conflicting-widths-10.html conflicting-widths-10-ref.html
== conflicting-percent-widths-1.html conflicting-percent-widths-1-ref.html

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

@ -24,9 +24,9 @@ HTTP(..) == blur-opacity.html blur-opacity-ref.html
== overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
needs-focus != text-shadow-selected-1.html text-shadow-selected-1-notref.html
needs-focus == text-shadow-selected-1.html text-shadow-selected-1-ref.html
fails-if(Android||B2G) needs-focus == text-shadow-selected-1.html text-shadow-selected-1-ref.html # different foreground selection color on Android/B2G
needs-focus != text-shadow-selected-2.html text-shadow-selected-2-notref.html
needs-focus == text-shadow-selected-2.html text-shadow-selected-2-ref.html
fails-if(Android||B2G) needs-focus == text-shadow-selected-2.html text-shadow-selected-2-ref.html # different foreground selection color on Android/B2G
# bug 692744
== text-shadow-on-space-1.html text-shadow-on-space-1-ref.html

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

@ -22,13 +22,13 @@
== moz-css21-table-page-break-inside-avoid-7.html moz-css21-table-page-break-inside-avoid-7-ref.html
== moz-css21-table-page-break-inside-avoid-8.html moz-css21-table-page-break-inside-avoid-6-ref.html
== moz-css21-float-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html
== moz-css21-float-page-break-inside-avoid-2.html moz-css21-float-page-break-inside-avoid-2-ref.html
fails-if(B2G) == moz-css21-float-page-break-inside-avoid-2.html moz-css21-float-page-break-inside-avoid-2-ref.html
== moz-css21-float-page-break-inside-avoid-3.html moz-css21-block-page-break-inside-avoid-ref.html
== moz-css21-float-page-break-inside-avoid-4.html moz-css21-block-page-break-inside-avoid-ref.html
== moz-css21-float-page-break-inside-avoid-5.html moz-css21-float-page-break-inside-avoid-5-ref.html
== moz-css21-float-page-break-inside-avoid-6.html moz-css21-float-page-break-inside-avoid-6-ref.html
== moz-css21-float-page-break-inside-avoid-7.html moz-css21-float-page-break-inside-avoid-7-ref.html
== moz-css21-float-page-break-inside-avoid-8.html moz-css21-float-page-break-inside-avoid-8-ref.html
fails-if(B2G) == moz-css21-float-page-break-inside-avoid-8.html moz-css21-float-page-break-inside-avoid-8-ref.html
== moz-css21-float-page-break-inside-avoid-9.html moz-css21-float-page-break-inside-avoid-9-ref.html
== moz-css21-rowgroup-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html
== moz-css21-rowgroup-page-break-inside-avoid-2.html moz-css21-table-page-break-inside-avoid-ref.html

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

@ -8,6 +8,6 @@
== box-sizing-padding-box-001.xht box-sizing-padding-box-001-ref.xht
== box-sizing-padding-box-002.xht box-sizing-padding-box-002-ref.xht
== box-sizing-padding-box-003.xht box-sizing-padding-box-003-ref.xht
random-if(Android) == box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht
fails-if(B2G) random-if(Android) == box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht
== box-sizing-replaced-002.xht box-sizing-replaced-002-ref.xht
== box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht

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

@ -5,5 +5,5 @@ random-if(Android||B2G) fails-if(winWidget) == menulist-shrinkwrap-2.xul menulis
== textbox-overflow-1.xul textbox-overflow-1-ref.xul # for bug 749658
# accesskeys are not normally displayed on Mac, so skip this test
skip-if(cocoaWidget) == accesskey.xul accesskey-ref.xul
fails-if(cocoaWidget) == tree-row-outline-1.xul tree-row-outline-1-ref.xul
fails-if(cocoaWidget) fails-if(B2G) == tree-row-outline-1.xul tree-row-outline-1-ref.xul
!= tree-row-outline-1.xul tree-row-outline-1-notref.xul

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

@ -38,6 +38,13 @@ function setDefaultPrefs() {
branch.setBoolPref("security.fileuri.strict_origin_policy", false);
// Disable the thumbnailing service
branch.setBoolPref("browser.pagethumbnails.capturing_disabled", true);
// Enable APZC so we can test it
branch.setBoolPref("layers.async-pan-zoom.enabled", true);
// Since our tests are 800px wide, set the assume-designed-for width of all
// pages to be 800px (instead of the default of 980px). This ensures that
// in our 800px window we don't zoom out by default to try to fit the
// assumed 980px content.
branch.setIntPref("browser.viewport.desktopWidth", 800);
// Disable the fade out (over time) of overlay scrollbars, since we
// can't guarantee taking both reftest snapshots at the same point
// during the fade.

12
layout/tools/reftest/bootstrap.js поставляемый
Просмотреть файл

@ -38,6 +38,18 @@ function setDefaultPrefs() {
branch.setIntPref("urlclassifier.updateinterval", 172800);
// Disable high-quality downscaling, since it makes reftests more difficult.
branch.setBoolPref("image.high_quality_downscaling.enabled", false);
// Checking whether two files are the same is slow on Windows.
// Setting this pref makes tests run much faster there.
branch.setBoolPref("security.fileuri.strict_origin_policy", false);
// Disable the thumbnailing service
branch.setBoolPref("browser.pagethumbnails.capturing_disabled", true);
// Enable APZC so we can test it
branch.setBoolPref("layers.async-pan-zoom.enabled", true);
// Since our tests are 800px wide, set the assume-designed-for width of all
// pages to be 800px (instead of the default of 980px). This ensures that
// in our 800px window we don't zoom out by default to try to fit the
// assumed 980px content.
branch.setIntPref("browser.viewport.desktopWidth", 800);
// Disable the fade out (over time) of overlay scrollbars, since we
// can't guarantee taking both reftest snapshots at the same point
// during the fade.

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

@ -4388,10 +4388,11 @@ pref("dom.voicemail.defaultServiceId", 0);
pref("dom.inter-app-communication-api.enabled", false);
// The tables used for Safebrowsing phishing and malware checks.
pref("urlclassifier.malware_table", "goog-malware-shavar");
pref("urlclassifier.phish_table", "goog-phish-shavar");
pref("urlclassifier.malware_table", "goog-malware-shavar,test-malware-simple");
pref("urlclassifier.phish_table", "goog-phish-shavar,test-phish-simple");
pref("urlclassifier.download_block_table", "");
pref("urlclassifier.download_allow_table", "");
pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,goog-downloadwhite-digest256");
// Turn off Spatial navigation by default.
pref("snav.enabled", false);

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

@ -273,7 +273,19 @@ PendingDBLookup::LookupSpecInternal(const nsACString& aSpec)
LOG(("Checking DB service for principal %s [this = %p]", mSpec.get(), this));
nsCOMPtr<nsIUrlClassifierDBService> dbService =
do_GetService(NS_URLCLASSIFIERDBSERVICE_CONTRACTID, &rv);
return dbService->Lookup(principal, this);
nsAutoCString tables;
nsAutoCString allowlist;
Preferences::GetCString(PREF_DOWNLOAD_ALLOW_TABLE, &allowlist);
if (!allowlist.IsEmpty()) {
tables.Append(allowlist);
}
nsAutoCString blocklist;
Preferences::GetCString(PREF_DOWNLOAD_BLOCK_TABLE, &blocklist);
if (!mAllowlistOnly && !blocklist.IsEmpty()) {
tables.Append(",");
tables.Append(blocklist);
}
return dbService->Lookup(principal, tables, this);
}
NS_IMETHODIMP

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

@ -32,6 +32,28 @@ extern PRLogModuleInfo *gUrlClassifierDbServiceLog;
namespace mozilla {
namespace safebrowsing {
void
Classifier::SplitTables(const nsACString& str, nsTArray<nsCString>& tables)
{
tables.Clear();
nsACString::const_iterator begin, iter, end;
str.BeginReading(begin);
str.EndReading(end);
while (begin != end) {
iter = begin;
FindCharInReadable(',', iter, end);
nsDependentCSubstring table = Substring(begin,iter);
if (!table.IsEmpty()) {
tables.AppendElement(Substring(begin, iter));
}
begin = iter;
if (begin != end) {
begin++;
}
}
}
Classifier::Classifier()
: mFreshTime(45 * 60)
{
@ -195,7 +217,9 @@ Classifier::TableRequest(nsACString& aResult)
}
nsresult
Classifier::Check(const nsACString& aSpec, LookupResultArray& aResults)
Classifier::Check(const nsACString& aSpec,
const nsACString& aTables,
LookupResultArray& aResults)
{
Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_CL_CHECK_TIME> timer;
@ -207,10 +231,11 @@ Classifier::Check(const nsACString& aSpec, LookupResultArray& aResults)
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<nsCString> activeTables;
ActiveTables(activeTables);
SplitTables(aTables, activeTables);
nsTArray<LookupCache*> cacheArray;
for (uint32_t i = 0; i < activeTables.Length(); i++) {
LOG(("Checking table %s", activeTables[i].get()));
LookupCache *cache = GetLookupCache(activeTables[i]);
if (cache) {
cacheArray.AppendElement(cache);

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

@ -43,9 +43,11 @@ public:
nsresult ActiveTables(nsTArray<nsCString>& aTables);
/**
* Check a URL against the database.
* Check a URL against the specified tables.
*/
nsresult Check(const nsACString& aSpec, LookupResultArray& aResults);
nsresult Check(const nsACString& aSpec,
const nsACString& tables,
LookupResultArray& aResults);
/**
* Apply the table updates in the array. Takes ownership of
@ -68,6 +70,8 @@ public:
const nsACString& aTableName,
uint32_t aCount,
PrefixArray* aNoiseEntries);
static void SplitTables(const nsACString& str, nsTArray<nsCString>& tables);
private:
void DropStores();
nsresult CreateStoreDirectory();

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

@ -66,17 +66,18 @@ interface nsIUrlClassifierUpdateObserver : nsISupports {
* It provides async methods for querying and updating the database. As the
* methods complete, they call the callback function.
*/
[scriptable, uuid(8a389f21-f821-4e29-9c6b-3de6f33cd7cf)]
[scriptable, uuid(3f9e61e5-01bd-45d0-8dd2-f1abcd20dbb7)]
interface nsIUrlClassifierDBService : nsISupports
{
/**
* Looks up a URI in the database.
* Looks up a URI in the specified tables.
*
* @param principal: The principal containing the URI to search.
* @param c: The callback will be called with a comma-separated list
* of tables to which the key belongs.
*/
void lookup(in nsIPrincipal principal,
in ACString tables,
in nsIUrlClassifierCallback c);
/**
@ -184,7 +185,7 @@ interface nsIUrlClassifierDBService : nsISupports
* Interface for the actual worker thread. Implementations of this need not
* be thread aware and just work on the database.
*/
[scriptable, uuid(0445be75-b114-43ea-89dc-aa16af26e77e)]
[scriptable, uuid(abcd7978-c304-4a7d-a44c-33c2ed5441e7)]
interface nsIUrlClassifierDBServiceWorker : nsIUrlClassifierDBService
{
// Provide a way to forcibly close the db connection.

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

@ -73,6 +73,7 @@ PRLogModuleInfo *gUrlClassifierDbServiceLog = nullptr;
#define PHISH_TABLE_PREF "urlclassifier.phish_table"
#define DOWNLOAD_BLOCK_TABLE_PREF "urlclassifier.download_block_table"
#define DOWNLOAD_ALLOW_TABLE_PREF "urlclassifier.download_allow_table"
#define DISALLOW_COMPLETION_TABLE_PREF "urlclassifier.disallow_completions"
#define CONFIRM_AGE_PREF "urlclassifier.max-complete-age"
#define CONFIRM_AGE_DEFAULT_SEC (45 * 60)
@ -90,24 +91,6 @@ static bool gShuttingDownThread = false;
static mozilla::Atomic<int32_t> gFreshnessGuarantee(CONFIRM_AGE_DEFAULT_SEC);
static void
SplitTables(const nsACString& str, nsTArray<nsCString>& tables)
{
tables.Clear();
nsACString::const_iterator begin, iter, end;
str.BeginReading(begin);
str.EndReading(end);
while (begin != end) {
iter = begin;
FindCharInReadable(',', iter, end);
tables.AppendElement(Substring(begin, iter));
begin = iter;
if (begin != end)
begin++;
}
}
// -------------------------------------------------------------------------
// Actual worker implemenatation
class nsUrlClassifierDBServiceWorker MOZ_FINAL :
@ -123,7 +106,9 @@ public:
nsresult Init(uint32_t aGethashNoise, nsCOMPtr<nsIFile> aCacheDir);
// Queue a lookup for the worker to perform, called in the main thread.
// tables is a comma-separated list of tables to query
nsresult QueueLookup(const nsACString& lookupKey,
const nsACString& tables,
nsIUrlClassifierLookupCallback* callback);
// Handle any queued-up lookups. We call this function during long-running
@ -149,7 +134,9 @@ private:
void ResetUpdate();
// Perform a classifier lookup for a given url.
nsresult DoLookup(const nsACString& spec, nsIUrlClassifierLookupCallback* c);
nsresult DoLookup(const nsACString& spec,
const nsACString& tables,
nsIUrlClassifierLookupCallback* c);
nsresult AddNoise(const Prefix aPrefix,
const nsCString tableName,
@ -192,6 +179,7 @@ private:
public:
TimeStamp mStartTime;
nsCString mKey;
nsCString mTables;
nsCOMPtr<nsIUrlClassifierLookupCallback> mCallback;
};
@ -231,6 +219,7 @@ nsUrlClassifierDBServiceWorker::Init(uint32_t aGethashNoise,
nsresult
nsUrlClassifierDBServiceWorker::QueueLookup(const nsACString& spec,
const nsACString& tables,
nsIUrlClassifierLookupCallback* callback)
{
MutexAutoLock lock(mPendingLookupLock);
@ -241,6 +230,7 @@ nsUrlClassifierDBServiceWorker::QueueLookup(const nsACString& spec,
lookup->mStartTime = TimeStamp::Now();
lookup->mKey = spec;
lookup->mCallback = callback;
lookup->mTables = tables;
return NS_OK;
}
@ -258,6 +248,7 @@ nsUrlClassifierDBServiceWorker::QueueLookup(const nsACString& spec,
*/
nsresult
nsUrlClassifierDBServiceWorker::DoLookup(const nsACString& spec,
const nsACString& tables,
nsIUrlClassifierLookupCallback* c)
{
if (gShuttingDownThread) {
@ -288,7 +279,7 @@ nsUrlClassifierDBServiceWorker::DoLookup(const nsACString& spec,
// we ignore failures from Check because we'd rather return the
// results that were found than fail.
mClassifier->SetFreshTime(gFreshnessGuarantee);
mClassifier->Check(spec, *results);
mClassifier->Check(spec, tables, *results);
LOG(("Found %d results.", results->Length()));
@ -336,7 +327,7 @@ nsUrlClassifierDBServiceWorker::HandlePendingLookups()
mPendingLookups.RemoveElementAt(0);
{
MutexAutoUnlock unlock(mPendingLookupLock);
DoLookup(lookup.mKey, lookup.mCallback);
DoLookup(lookup.mKey, lookup.mTables, lookup.mCallback);
}
double lookupTime = (TimeStamp::Now() - lookup.mStartTime).ToMilliseconds();
Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LOOKUP_TIME,
@ -378,6 +369,7 @@ nsUrlClassifierDBServiceWorker::AddNoise(const Prefix aPrefix,
// Lookup a key in the db.
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::Lookup(nsIPrincipal* aPrincipal,
const nsACString& aTables,
nsIUrlClassifierCallback* c)
{
return HandlePendingLookups();
@ -447,7 +439,7 @@ nsUrlClassifierDBServiceWorker::BeginUpdate(nsIUrlClassifierUpdateObserver *obse
mUpdateStatus = NS_OK;
mUpdateObserver = observer;
SplitTables(tables, mUpdateTables);
Classifier::SplitTables(tables, mUpdateTables);
return NS_OK;
}
@ -1101,6 +1093,9 @@ nsUrlClassifierDBService::Init()
DOWNLOAD_BLOCK_TABLE_PREF));
mGethashTables.AppendElement(Preferences::GetCString(
DOWNLOAD_ALLOW_TABLE_PREF));
nsCString tables;
Preferences::GetCString(DISALLOW_COMPLETION_TABLE_PREF, &tables);
Classifier::SplitTables(tables, mDisallowCompletionsTables);
// Do we *really* need to be able to change all of these at runtime?
Preferences::AddStrongObserver(this, CHECK_MALWARE_PREF);
@ -1111,6 +1106,7 @@ nsUrlClassifierDBService::Init()
Preferences::AddStrongObserver(this, MALWARE_TABLE_PREF);
Preferences::AddStrongObserver(this, DOWNLOAD_BLOCK_TABLE_PREF);
Preferences::AddStrongObserver(this, DOWNLOAD_ALLOW_TABLE_PREF);
Preferences::AddStrongObserver(this, DISALLOW_COMPLETION_TABLE_PREF);
// Force PSM loading on main thread
nsresult rv;
@ -1156,6 +1152,7 @@ nsUrlClassifierDBService::Init()
return NS_OK;
}
// nsChannelClassifier is the only consumer of this interface.
NS_IMETHODIMP
nsUrlClassifierDBService::Classify(nsIPrincipal* aPrincipal,
nsIURIClassifierCallback* c,
@ -1173,7 +1170,19 @@ nsUrlClassifierDBService::Classify(nsIPrincipal* aPrincipal,
new nsUrlClassifierClassifyCallback(c, mCheckMalware, mCheckPhishing);
if (!callback) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = LookupURI(aPrincipal, callback, false, result);
nsAutoCString tables;
nsAutoCString malware;
Preferences::GetCString(MALWARE_TABLE_PREF, &malware);
if (!malware.IsEmpty()) {
tables.Append(malware);
}
nsAutoCString phishing;
Preferences::GetCString(PHISH_TABLE_PREF, &phishing);
if (!phishing.IsEmpty()) {
tables.Append(",");
tables.Append(phishing);
}
nsresult rv = LookupURI(aPrincipal, tables, callback, false, result);
if (rv == NS_ERROR_MALFORMED_URI) {
*result = false;
// The URI had no hostname, don't try to classify it.
@ -1186,16 +1195,18 @@ nsUrlClassifierDBService::Classify(nsIPrincipal* aPrincipal,
NS_IMETHODIMP
nsUrlClassifierDBService::Lookup(nsIPrincipal* aPrincipal,
const nsACString& tables,
nsIUrlClassifierCallback* c)
{
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
bool dummy;
return LookupURI(aPrincipal, c, true, &dummy);
return LookupURI(aPrincipal, tables, c, true, &dummy);
}
nsresult
nsUrlClassifierDBService::LookupURI(nsIPrincipal* aPrincipal,
const nsACString& tables,
nsIUrlClassifierCallback* c,
bool forceLookup,
bool *didLookup)
@ -1262,11 +1273,12 @@ nsUrlClassifierDBService::LookupURI(nsIPrincipal* aPrincipal,
// Queue this lookup and call the lookup function to flush the queue if
// necessary.
rv = mWorker->QueueLookup(key, proxyCallback);
rv = mWorker->QueueLookup(key, tables, proxyCallback);
NS_ENSURE_SUCCESS(rv, rv);
// This seems to just call HandlePendingLookups.
return mWorkerProxy->Lookup(nullptr, nullptr);
nsAutoCString dummy;
return mWorkerProxy->Lookup(nullptr, dummy, nullptr);
}
NS_IMETHODIMP
@ -1385,14 +1397,20 @@ bool
nsUrlClassifierDBService::GetCompleter(const nsACString &tableName,
nsIUrlClassifierHashCompleter **completer)
{
// If we have specified a completer, go ahead and query it. This is only
// used by tests.
if (mCompleters.Get(tableName, completer)) {
return true;
}
if (!mGethashTables.Contains(tableName)) {
// If we don't know about this table at all, or are disallowing completions
// for it, skip completion checks.
if (!mGethashTables.Contains(tableName) ||
mDisallowCompletionsTables.Contains(tableName)) {
return false;
}
// Otherwise, call gethash to find the hash completions.
return NS_SUCCEEDED(CallGetService(NS_URLCLASSIFIERHASHCOMPLETER_CONTRACTID,
completer));
}
@ -1423,6 +1441,11 @@ nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
DOWNLOAD_BLOCK_TABLE_PREF));
mGethashTables.AppendElement(Preferences::GetCString(
DOWNLOAD_ALLOW_TABLE_PREF));
} else if (NS_LITERAL_STRING(DISALLOW_COMPLETION_TABLE_PREF).Equals(aData)) {
mDisallowCompletionsTables.Clear();
nsCString tables;
Preferences::GetCString(DISALLOW_COMPLETION_TABLE_PREF, &tables);
Classifier::SplitTables(tables, mDisallowCompletionsTables);
} else if (NS_LITERAL_STRING(CONFIRM_AGE_PREF).Equals(aData)) {
gFreshnessGuarantee = Preferences::GetInt(CONFIRM_AGE_PREF,
CONFIRM_AGE_DEFAULT_SEC);
@ -1456,6 +1479,7 @@ nsUrlClassifierDBService::Shutdown()
prefs->RemoveObserver(MALWARE_TABLE_PREF, this);
prefs->RemoveObserver(DOWNLOAD_BLOCK_TABLE_PREF, this);
prefs->RemoveObserver(DOWNLOAD_ALLOW_TABLE_PREF, this);
prefs->RemoveObserver(DISALLOW_COMPLETION_TABLE_PREF, this);
prefs->RemoveObserver(CONFIRM_AGE_PREF, this);
}

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

@ -71,6 +71,7 @@ private:
nsUrlClassifierDBService(nsUrlClassifierDBService&);
nsresult LookupURI(nsIPrincipal* aPrincipal,
const nsACString& tables,
nsIUrlClassifierCallback* c,
bool forceCheck, bool *didCheck);
@ -103,6 +104,9 @@ private:
// The list of tables that can use the default hash completer object.
nsTArray<nsCString> mGethashTables;
// The list of tables that should never be hash completed.
nsTArray<nsCString> mDisallowCompletionsTables;
// Thread that we do the updates on.
static nsIThread* gDbBackgroundThread;
};

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

@ -23,16 +23,18 @@ NS_IMPL_ISUPPORTS1(UrlClassifierDBServiceWorkerProxy,
NS_IMETHODIMP
UrlClassifierDBServiceWorkerProxy::Lookup(nsIPrincipal* aPrincipal,
const nsACString& aTables,
nsIUrlClassifierCallback* aCB)
{
nsCOMPtr<nsIRunnable> r = new LookupRunnable(mTarget, aPrincipal, aCB);
nsCOMPtr<nsIRunnable> r = new LookupRunnable(mTarget, aPrincipal, aTables,
aCB);
return DispatchToWorkerThread(r);
}
NS_IMETHODIMP
UrlClassifierDBServiceWorkerProxy::LookupRunnable::Run()
{
(void) mTarget->Lookup(mPrincipal, mCB);
(void) mTarget->Lookup(mPrincipal, mLookupTables, mCB);
return NS_OK;
}

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

@ -34,9 +34,11 @@ public:
public:
LookupRunnable(nsIUrlClassifierDBServiceWorker* aTarget,
nsIPrincipal* aPrincipal,
const nsACString& aTables,
nsIUrlClassifierCallback* aCB)
: mTarget(aTarget)
, mPrincipal(aPrincipal)
, mLookupTables(aTables)
, mCB(aCB)
{ }
@ -45,6 +47,7 @@ public:
private:
nsCOMPtr<nsIUrlClassifierDBServiceWorker> mTarget;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCString mLookupTables;
nsCOMPtr<nsIUrlClassifierCallback> mCB;
};

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

@ -6,7 +6,6 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="doUpdate(testUpdate);">
<p id="display"></p>
<div id="content" style="display: none">
</div>
@ -61,6 +60,11 @@ function doUpdate(update) {
dbService.finishUpdate();
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.malware_table", "test-malware-simple"],
["urlclassifier.phish_table", "test-phish-simple"]]},
function() { doUpdate(testUpdate); });
// Expected finish() call is in "classifierFrame.html".
SimpleTest.waitForExplicitFinish();

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

@ -6,7 +6,6 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="doUpdate(testUpdate);">
<p id="display"></p>
<div id="content" style="display: none">
</div>
@ -73,6 +72,11 @@ function onmessage(event)
is(pieces[0], "success", pieces[1]);
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.malware_table", "test-malware-simple"],
["urlclassifier.phish_table", "test-phish-simple"]]},
function() { doUpdate(testUpdate); });
window.addEventListener("message", onmessage, false);
SimpleTest.waitForExplicitFinish();

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

@ -19,7 +19,7 @@ var Ci = Components.interfaces;
var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
dbService.lookup(document.nodePrincipal, function(arg) {});
dbService.lookup(document.nodePrincipal, "", function(arg) {});
ok(true, "lookup() didn't crash");

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

@ -31,6 +31,9 @@ prefBranch.setIntPref("urlclassifier.gethashnoise", 0);
prefBranch.setBoolPref("browser.safebrowsing.malware.enabled", true);
prefBranch.setBoolPref("browser.safebrowsing.enabled", true);
// Enable all completions for tests
prefBranch.setCharPref("urlclassifier.disallow_completions", "");
function delFile(name) {
try {
// Delete a previously created sqlite file
@ -53,6 +56,8 @@ function cleanUp() {
delFile("safebrowsing/test-malware-simple.pset");
}
var allTables = "test-phish-simple,test-malware-simple";
var dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService);
var streamUpdater = Cc["@mozilla.org/url-classifier/streamupdater;1"]
.getService(Ci.nsIUrlClassifierStreamUpdater);
@ -200,7 +205,7 @@ checkUrls: function(urls, expected, cb)
if (urls.length > 0) {
var fragment = urls.shift();
var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("http://" + fragment, null, null));
dbservice.lookup(principal,
dbservice.lookup(principal, allTables,
function(arg) {
do_check_eq(expected, arg);
doLookup();

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

@ -96,7 +96,7 @@ function checkNoHost()
var exception;
try {
var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("data:text/html,<b>test</b>", null, null));
dbservice.lookup(principal);
dbservice.lookup(principal, allTables);
exception = false;
} catch(e) {
@ -115,7 +115,7 @@ function tablesCallbackWithoutSub(tables)
// there's a leading \n here because splitting left an empty string
// after the trailing newline, which will sort first
do_check_eq(parts.join("\n"),
"\ntesting-malware-simple;a:1\ntesting-phish-simple;a:2");
"\ntest-malware-simple;a:1\ntest-phish-simple;a:2");
checkNoHost();
}
@ -133,12 +133,12 @@ function tablesCallbackWithSub(tables)
// there's a leading \n here because splitting left an empty string
// after the trailing newline, which will sort first
do_check_eq(parts.join("\n"),
"\ntesting-malware-simple;a:1\ntesting-phish-simple;a:2:s:3");
"\ntest-malware-simple;a:1\ntest-phish-simple;a:2:s:3");
// verify that expiring a sub chunk removes its name from the list
var data =
"n:1000\n" +
"i:testing-phish-simple\n" +
"i:test-phish-simple\n" +
"sd:3\n";
doSimpleUpdate(data, expireSubSuccess, testFailure);
@ -157,7 +157,7 @@ function checkDone() {
function phishExists(result) {
dumpn("phishExists: " + result);
try {
do_check_true(result.indexOf("testing-phish-simple") != -1);
do_check_true(result.indexOf("test-phish-simple") != -1);
} finally {
checkDone();
}
@ -166,7 +166,7 @@ function phishExists(result) {
function phishDoesntExist(result) {
dumpn("phishDoesntExist: " + result);
try {
do_check_true(result.indexOf("testing-phish-simple") == -1);
do_check_true(result.indexOf("test-phish-simple") == -1);
} finally {
checkDone();
}
@ -176,7 +176,7 @@ function malwareExists(result) {
dumpn("malwareExists: " + result);
try {
do_check_true(result.indexOf("testing-malware-simple") != -1);
do_check_true(result.indexOf("test-malware-simple") != -1);
} finally {
checkDone();
}
@ -188,19 +188,19 @@ function checkState()
for (var key in phishExpected) {
var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("http://" + key, null, null));
dbservice.lookup(principal, phishExists, true);
dbservice.lookup(principal, allTables, phishExists, true);
numExpecting++;
}
for (var key in phishUnexpected) {
var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("http://" + key, null, null));
dbservice.lookup(principal, phishDoesntExist, true);
dbservice.lookup(principal, allTables, phishDoesntExist, true);
numExpecting++;
}
for (var key in malwareExpected) {
var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("http://" + key, null, null));
dbservice.lookup(principal, malwareExists, true);
dbservice.lookup(principal, allTables, malwareExists, true);
numExpecting++;
}
}
@ -214,7 +214,7 @@ function testSubSuccess(result)
function do_subs() {
var data =
"n:1000\n" +
"i:testing-phish-simple\n" +
"i:test-phish-simple\n" +
"s:3:32:" + chunk3Sub.length + "\n" +
chunk3Sub + "\n" +
"ad:1\n" +
@ -236,7 +236,7 @@ function do_adds() {
var data =
"n:1000\n" +
"i:testing-phish-simple\n" +
"i:test-phish-simple\n" +
"a:1:32:" + chunk1.length + "\n" +
chunk1 + "\n" +
"a:2:32:" + chunk2.length + "\n" +
@ -247,7 +247,7 @@ function do_adds() {
chunk5 + "\n" +
"a:6:32:" + chunk6.length + "\n" +
chunk6 + "\n" +
"i:testing-malware-simple\n" +
"i:test-malware-simple\n" +
"a:1:32:" + chunk2.length + "\n" +
chunk2 + "\n";

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

@ -125,7 +125,8 @@ add_test(function test_update() {
add_test(function test_url_not_whitelisted() {
let uri = createURI("http://example.com");
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
gDbService.lookup(principal, function handleEvent(aEvent) {
gDbService.lookup(principal, "goog-downloadwhite-digest256",
function handleEvent(aEvent) {
// This URI is not on any lists.
do_check_eq("", aEvent);
run_next_test();
@ -137,7 +138,8 @@ add_test(function test_url_whitelisted() {
// 93CA5F48E15E9861CD37C2D95DB43D23CC6E6DE5C3F8FA6E8BE66F97CC518907
let uri = createURI("http://whitelisted.com");
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
gDbService.lookup(principal, function handleEvent(aEvent) {
gDbService.lookup(principal, "goog-downloadwhite-digest256",
function handleEvent(aEvent) {
do_check_eq("goog-downloadwhite-digest256", aEvent);
run_next_test();
});