Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-06-04 15:48:21 +02:00
commit f727e9c4ef
39 changed files with 666 additions and 63 deletions

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "33a8ca00e3128502d0c4c834236be335c0060f43",
"revision": "cd1a16d6212a1867ecf1d1cfcd62f80abf9ae0b1",
"repo_path": "/integration/gaia-central"
}

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -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="1d4f6f7312882e78b57971152de75d1281a26187"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a38a6a5c6fabc97dd16d5360632b5ac5c7e06241"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -137,7 +137,7 @@ var MigrationWizard = {
if (sourceProfiles && sourceProfiles.length == 1)
this._selectedProfile = sourceProfiles[0];
else
this._selectedProfile = "";
this._selectedProfile = null;
}
},
@ -157,27 +157,32 @@ var MigrationWizard = {
// and we canceled the dialog. When that happens, _migrator will be null.
if (this._migrator) {
var sourceProfiles = this._migrator.sourceProfiles;
for (var i = 0; i < sourceProfiles.length; ++i) {
for (let profile of sourceProfiles) {
var item = document.createElement("radio");
item.id = sourceProfiles[i];
item.setAttribute("label", sourceProfiles[i]);
item.id = profile.id;
item.setAttribute("label", profile.name);
profiles.appendChild(item);
}
}
profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile) : profiles.firstChild;
profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile.id) : profiles.firstChild;
},
onSelectProfilePageRewound: function ()
{
var profiles = document.getElementById("profiles");
this._selectedProfile = profiles.selectedItem.id;
this._selectedProfile = this._migrator.sourceProfiles.find(
profile => profile.id == profiles.selectedItem.id
) || null;
},
onSelectProfilePageAdvanced: function ()
{
var profiles = document.getElementById("profiles");
this._selectedProfile = profiles.selectedItem.id;
this._selectedProfile = this._migrator.sourceProfiles.find(
profile => profile.id == profiles.selectedItem.id
) || null;
// If we're automigrating or just doing bookmarks don't show the item selection page
if (this._autoMigrate)

View File

@ -8,7 +8,7 @@
interface nsIArray;
interface nsIProfileStartup;
[scriptable, uuid(44993E0E-74E8-4BEC-9D66-AD8156E0A274)]
[scriptable, uuid(30e5a7ec-f71e-4f41-9dbd-7429c02132ec)]
interface nsIBrowserProfileMigrator : nsISupports
{
/**
@ -30,7 +30,7 @@ interface nsIBrowserProfileMigrator : nsISupports
* @param aStartup helper interface which is non-null if called during startup.
* @param aProfile profile to migrate from, if there is more than one.
*/
void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in wstring aProfile);
void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in jsval aProfile);
/**
* A bit field containing profile items that this migrator
@ -41,7 +41,7 @@ interface nsIBrowserProfileMigrator : nsISupports
* @return bit field containing profile items (see above)
* @note a return value of 0 represents no items rather than ALL.
*/
unsigned short getMigrateData(in wstring aProfile, in boolean aDoingStartup);
unsigned short getMigrateData(in jsval aProfile, in boolean aDoingStartup);
/**
* Whether or not there is any data that can be imported from this

View File

@ -93,7 +93,7 @@ ChromeProfileMigrator.prototype.getResources =
function Chrome_getResources(aProfile) {
if (this._chromeUserDataFolder) {
let profileFolder = this._chromeUserDataFolder.clone();
profileFolder.append(aProfile);
profileFolder.append(aProfile.id);
if (profileFolder.exists()) {
let possibleResources = [GetBookmarksResource(profileFolder),
GetHistoryResource(profileFolder),
@ -112,7 +112,7 @@ Object.defineProperty(ChromeProfileMigrator.prototype, "sourceProfiles", {
if (!this._chromeUserDataFolder)
return [];
let profiles;
let profiles = [];
try {
// Local State is a JSON file that contains profile info.
let localState = this._chromeUserDataFolder.clone();
@ -127,20 +127,30 @@ Object.defineProperty(ChromeProfileMigrator.prototype, "sourceProfiles", {
let inputStream = NetUtil.readInputStreamToString(fstream, fstream.available(),
{ charset: "UTF-8" });
let info_cache = JSON.parse(inputStream).profile.info_cache;
if (info_cache)
profiles = Object.keys(info_cache);
for (let profileFolderName in info_cache) {
let profileFolder = this._chromeUserDataFolder.clone();
profileFolder.append(profileFolderName);
profiles.push({
id: profileFolderName,
name: info_cache[profileFolderName].name || profileFolderName,
});
}
} catch (e) {
Cu.reportError("Error detecting Chrome profiles: " + e);
// If we weren't able to detect any profiles above, fallback to the Default profile.
let defaultProfileFolder = this._chromeUserDataFolder.clone();
defaultProfileFolder.append("Default");
if (defaultProfileFolder.exists())
profiles = ["Default"];
if (defaultProfileFolder.exists()) {
profiles = [{
id: "Default",
name: "Default",
}];
}
}
// Only list profiles from which any data can be imported
return this.__sourceProfiles = profiles.filter(function(profileName) {
let resources = this.getResources(profileName);
return this.__sourceProfiles = profiles.filter(function(profile) {
let resources = this.getResources(profile);
return resources && resources.length > 0;
}, this);
}

View File

@ -92,7 +92,10 @@ this.MigratorPrototype = {
/**
* OVERRIDE IF AND ONLY IF the source supports multiple profiles.
*
* Returns array of profiles (by names) from which data may be imported.
* Returns array of profile objects from which data may be imported. The object
* should have the following keys:
* id - a unique string identifier for the profile
* name - a pretty name to display to the user in the UI
*
* Only profiles from which data can be imported should be listed. Otherwise
* the behavior of the migration wizard isn't well-defined.
@ -313,14 +316,15 @@ this.MigratorPrototype = {
/*** PRIVATE STUFF - DO NOT OVERRIDE ***/
_getMaybeCachedResources: function PMB__getMaybeCachedResources(aProfile) {
let profileKey = aProfile ? aProfile.id : "";
if (this._resourcesByProfile) {
if (aProfile in this._resourcesByProfile)
return this._resourcesByProfile[aProfile];
if (profileKey in this._resourcesByProfile)
return this._resourcesByProfile[profileKey];
}
else {
this._resourcesByProfile = { };
}
return this._resourcesByProfile[aProfile] = this.getResources(aProfile);
return this._resourcesByProfile[profileKey] = this.getResources(aProfile);
}
};

View File

@ -11,7 +11,7 @@ function run_test() {
do_check_true(migrator.sourceExists);
// Ensure bookmarks migration is available.
let availableSources = migrator.getMigrateData("FieldOfFlowers", false);
let availableSources = migrator.getMigrateData(null, false);
do_check_true((availableSources & MigrationUtils.resourceTypes.BOOKMARKS) > 0);
// Wait for the imported bookmarks. Check that "From Internet Explorer"
@ -52,5 +52,5 @@ function run_test() {
}, "Migration:Ended", false);
migrator.migrate(MigrationUtils.resourceTypes.BOOKMARKS, null,
"FieldOfFlowers");
null);
}

View File

@ -1,16 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["Translation"];
this.EXPORTED_SYMBOLS = [
"Translation",
"TranslationProvider",
];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
const TRANSLATION_PREF_SHOWUI = "browser.translation.ui.show";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Metrics.jsm", this);
Cu.import("resource://gre/modules/Task.jsm", this);
const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
const DAILY_LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT};
this.Translation = {
supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
@ -28,16 +38,20 @@ this.Translation = {
},
languageDetected: function(aBrowser, aDetectedLanguage) {
if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) == -1 ||
aDetectedLanguage == this.defaultTargetLanguage)
return;
TranslationHealthReport.recordTranslationOpportunity(aDetectedLanguage);
if (!Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI))
return;
if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) != -1 &&
aDetectedLanguage != this.defaultTargetLanguage) {
if (!aBrowser.translationUI)
aBrowser.translationUI = new TranslationUI(aBrowser);
if (!aBrowser.translationUI)
aBrowser.translationUI = new TranslationUI(aBrowser);
aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
}
aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
}
};
@ -187,3 +201,228 @@ TranslationUI.prototype = {
}
}
};
/**
* Helper methods for recording translation data in FHR.
*/
let TranslationHealthReport = {
/**
* Record a translation opportunity in the health report.
* @param language
* The language of the page.
*/
recordTranslationOpportunity: function (language) {
this._withProvider(provider => provider.recordTranslationOpportunity(language));
},
/**
* Record a translation in the health report.
* @param langFrom
* The language of the page.
* @param langTo
* The language translated to
* @param numCharacters
* The number of characters that were translated
*/
recordTranslation: function (langFrom, langTo, numCharacters) {
this._withProvider(provider => provider.recordTranslation(langFrom, langTo, numCharacters));
},
/**
* Record a change of the detected language in the health report. This should
* only be called when actually executing a translation not every time the
* user changes in the language in the UI.
*
* @param beforeFirstTranslation
* A boolean indicating if we are recording a change of detected
* language before translating the page for the first time. If we
* have already translated the page from the detected language and
* the user has manually adjusted the detected language false should
* be passed.
*/
recordLanguageChange: function (beforeFirstTranslation) {
this._withProvider(provider => provider.recordLanguageChange(beforeFirstTranslation));
},
/**
* Retrieve the translation provider and pass it to the given function.
*
* @param callback
* The function that will be passed the translation provider.
*/
_withProvider: function (callback) {
try {
let reporter = Cc["@mozilla.org/datareporting/service;1"]
.getService().wrappedJSObject.healthReporter;
if (reporter) {
reporter.onInit().then(function () {
callback(reporter.getProvider("org.mozilla.translation"));
}, Cu.reportError);
} else {
callback(null);
}
} catch (ex) {
Cu.reportError(ex);
}
}
};
/**
* Holds usage data about the Translation feature.
*
* This is a special telemetry measurement that is transmitted in the FHR
* payload. Data will only be recorded/transmitted when both telemetry and
* FHR are enabled. Additionally, if telemetry was previously enabled but
* is currently disabled, old recorded data will not be transmitted.
*/
function TranslationMeasurement1() {
Metrics.Measurement.call(this);
this._serializers[this.SERIALIZE_JSON].singular =
this._wrapJSONSerializer(this._serializers[this.SERIALIZE_JSON].singular);
this._serializers[this.SERIALIZE_JSON].daily =
this._wrapJSONSerializer(this._serializers[this.SERIALIZE_JSON].daily);
}
TranslationMeasurement1.prototype = Object.freeze({
__proto__: Metrics.Measurement.prototype,
name: "translation",
version: 1,
fields: {
translationOpportunityCount: DAILY_COUNTER_FIELD,
pageTranslatedCount: DAILY_COUNTER_FIELD,
charactersTranslatedCount: DAILY_COUNTER_FIELD,
translationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
pageTranslatedCountsByLanguage: DAILY_LAST_TEXT_FIELD,
detectedLanguageChangedBefore: DAILY_COUNTER_FIELD,
detectedLanguageChangedAfter: DAILY_COUNTER_FIELD,
},
shouldIncludeField: function (field) {
if (!Services.prefs.getBoolPref("toolkit.telemetry.enabled")) {
// This measurement should only be included when telemetry is
// enabled, so we will not include any fields.
return false;
}
return field in this._fields;
},
_getDailyLastTextFieldAsJSON: function(name, date) {
let id = this.fieldID(name);
return this.storage.getDailyLastTextFromFieldID(id, date).then((data) => {
if (data.hasDay(date)) {
data = JSON.parse(data.getDay(date));
} else {
data = {};
}
return data;
});
},
_wrapJSONSerializer: function (serializer) {
let _parseInPlace = function(o, k) {
if (k in o) {
o[k] = JSON.parse(o[k]);
}
};
return function (data) {
let result = serializer(data);
// Special case the serialization of these fields so that
// they are sent as objects, not stringified objects.
_parseInPlace(result, "translationOpportunityCountsByLanguage");
_parseInPlace(result, "pageTranslatedCountsByLanguage");
return result;
}
}
});
this.TranslationProvider = function () {
Metrics.Provider.call(this);
}
TranslationProvider.prototype = Object.freeze({
__proto__: Metrics.Provider.prototype,
name: "org.mozilla.translation",
measurementTypes: [
TranslationMeasurement1,
],
recordTranslationOpportunity: function (language, date=new Date()) {
let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
TranslationMeasurement1.prototype.version);
return this._enqueueTelemetryStorageTask(function* recordTask() {
yield m.incrementDailyCounter("translationOpportunityCount", date);
let langCounts = yield m._getDailyLastTextFieldAsJSON(
"translationOpportunityCountsByLanguage", date);
langCounts[language] = (langCounts[language] || 0) + 1;
langCounts = JSON.stringify(langCounts);
yield m.setDailyLastText("translationOpportunityCountsByLanguage",
langCounts, date);
}.bind(this));
},
recordTranslation: function (langFrom, langTo, numCharacters, date=new Date()) {
let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
TranslationMeasurement1.prototype.version);
return this._enqueueTelemetryStorageTask(function* recordTask() {
yield m.incrementDailyCounter("pageTranslatedCount", date);
yield m.incrementDailyCounter("charactersTranslatedCount", date,
numCharacters);
let langCounts = yield m._getDailyLastTextFieldAsJSON(
"pageTranslatedCountsByLanguage", date);
let counts = langCounts[langFrom] || {};
counts["total"] = (counts["total"] || 0) + 1;
counts[langTo] = (counts[langTo] || 0) + 1;
langCounts[langFrom] = counts;
langCounts = JSON.stringify(langCounts);
yield m.setDailyLastText("pageTranslatedCountsByLanguage",
langCounts, date);
}.bind(this));
},
recordLanguageChange: function (beforeFirstTranslation) {
let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
TranslationMeasurement1.prototype.version);
return this._enqueueTelemetryStorageTask(function* recordTask() {
if (beforeFirstTranslation) {
yield m.incrementDailyCounter("detectedLanguageChangedBefore");
} else {
yield m.incrementDailyCounter("detectedLanguageChangedAfter");
}
}.bind(this));
},
_enqueueTelemetryStorageTask: function (task) {
if (!Services.prefs.getBoolPref("toolkit.telemetry.enabled")) {
// This measurement should only be included when telemetry is
// enabled, so don't record any data.
return Promise.resolve(null);
}
return this.enqueueStorageOperation(() => {
return Task.spawn(task);
});
}
});

View File

@ -21,5 +21,9 @@ BROWSER_CHROME_MANIFESTS += [
]
XPCSHELL_TESTS_MANIFESTS += [
'test/xpcshell.ini'
'test/unit/xpcshell.ini'
]
EXTRA_PP_COMPONENTS += [
'translation.manifest',
]

View File

@ -4,7 +4,9 @@
// tests the translation infobar, using a fake 'Translation' implementation.
Components.utils.import("resource:///modules/translation/Translation.jsm");
let tmp = {};
Cu.import("resource:///modules/translation/Translation.jsm", tmp);
let {Translation} = tmp;
const kLanguagesPref = "browser.translation.neverForLanguages";
const kShowUIPref = "browser.translation.ui.show";

View File

@ -4,7 +4,9 @@
// tests the translation infobar, using a fake 'Translation' implementation.
Components.utils.import("resource:///modules/translation/Translation.jsm");
let tmp = {};
Cu.import("resource:///modules/translation/Translation.jsm", tmp);
let {Translation} = tmp;
const kShowUIPref = "browser.translation.ui.show";

View File

@ -0,0 +1,269 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://gre/modules/Metrics.jsm", this);
Cu.import("resource:///modules/translation/Translation.jsm", this);
Cu.import("resource://testing-common/services/healthreport/utils.jsm", this);
// At end of test, restore original state.
const ORIGINAL_TELEMETRY_ENABLED = Services.prefs.getBoolPref("toolkit.telemetry.enabled");
function run_test() {
run_next_test();
}
add_test(function setup() {
do_get_profile();
Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
run_next_test();
});
do_register_cleanup(function() {
Services.prefs.setBoolPref("toolkit.telemetry.enabled",
ORIGINAL_TELEMETRY_ENABLED);
});
add_task(function test_constructor() {
let provider = new TranslationProvider();
});
// Provider can initialize and de-initialize properly.
add_task(function* test_init() {
let storage = yield Metrics.Storage("init");
let provider = new TranslationProvider();
yield provider.init(storage);
yield provider.shutdown();
yield storage.close();
});
// Test recording translation opportunities.
add_task(function* test_translation_opportunity() {
let storage = yield Metrics.Storage("opportunity");
let provider = new TranslationProvider();
yield provider.init(storage);
// Initially nothing should be configured.
let now = new Date();
let m = provider.getMeasurement("translation", 1);
let values = yield m.getValues();
Assert.equal(values.days.size, 0);
Assert.ok(!values.days.hasDay(now));
// Record an opportunity.
yield provider.recordTranslationOpportunity("fr", now);
values = yield m.getValues();
Assert.equal(values.days.size, 1);
Assert.ok(values.days.hasDay(now));
let day = values.days.getDay(now);
Assert.ok(day.has("translationOpportunityCount"));
Assert.equal(day.get("translationOpportunityCount"), 1);
Assert.ok(day.has("translationOpportunityCountsByLanguage"));
let countsByLanguage = JSON.parse(day.get("translationOpportunityCountsByLanguage"));
Assert.equal(countsByLanguage["fr"], 1);
// Record more opportunities.
yield provider.recordTranslationOpportunity("fr", now);
yield provider.recordTranslationOpportunity("fr", now);
yield provider.recordTranslationOpportunity("es", now);
values = yield m.getValues();
let day = values.days.getDay(now);
Assert.ok(day.has("translationOpportunityCount"));
Assert.equal(day.get("translationOpportunityCount"), 4);
Assert.ok(day.has("translationOpportunityCountsByLanguage"));
countsByLanguage = JSON.parse(day.get("translationOpportunityCountsByLanguage"));
Assert.equal(countsByLanguage["fr"], 3);
Assert.equal(countsByLanguage["es"], 1);
yield provider.shutdown();
yield storage.close();
});
// Test recording a translation.
add_task(function* test_record_translation() {
let storage = yield Metrics.Storage("translation");
let provider = new TranslationProvider();
yield provider.init(storage);
let now = new Date();
// Record a translation.
yield provider.recordTranslation("fr", "es", 1000, now);
let m = provider.getMeasurement("translation", 1);
let values = yield m.getValues();
Assert.equal(values.days.size, 1);
Assert.ok(values.days.hasDay(now));
let day = values.days.getDay(now);
Assert.ok(day.has("pageTranslatedCount"));
Assert.equal(day.get("pageTranslatedCount"), 1);
Assert.ok(day.has("charactersTranslatedCount"));
Assert.equal(day.get("charactersTranslatedCount"), 1000);
Assert.ok(day.has("pageTranslatedCountsByLanguage"));
let countsByLanguage = JSON.parse(day.get("pageTranslatedCountsByLanguage"));
Assert.ok("fr" in countsByLanguage);
Assert.equal(countsByLanguage["fr"]["total"], 1);
Assert.equal(countsByLanguage["fr"]["es"], 1);
// Record more translations.
yield provider.recordTranslation("fr", "es", 1, now);
yield provider.recordTranslation("fr", "en", 2, now);
yield provider.recordTranslation("es", "en", 4, now);
values = yield m.getValues();
let day = values.days.getDay(now);
Assert.ok(day.has("pageTranslatedCount"));
Assert.equal(day.get("pageTranslatedCount"), 4);
Assert.ok(day.has("charactersTranslatedCount"));
Assert.equal(day.get("charactersTranslatedCount"), 1007);
Assert.ok(day.has("pageTranslatedCountsByLanguage"));
let countsByLanguage = JSON.parse(day.get("pageTranslatedCountsByLanguage"));
Assert.ok("fr" in countsByLanguage);
Assert.equal(countsByLanguage["fr"]["total"], 3);
Assert.equal(countsByLanguage["fr"]["es"], 2);
Assert.equal(countsByLanguage["fr"]["en"], 1);
Assert.ok("es" in countsByLanguage);
Assert.equal(countsByLanguage["es"]["total"], 1);
Assert.equal(countsByLanguage["es"]["en"], 1);
yield provider.shutdown();
yield storage.close();
});
// Test recording changing languages.
add_task(function* test_record_translation() {
let storage = yield Metrics.Storage("translation");
let provider = new TranslationProvider();
yield provider.init(storage);
let now = new Date();
// Record a language change before translation.
yield provider.recordLanguageChange(true);
// Record two language changes after translation.
yield provider.recordLanguageChange(false);
yield provider.recordLanguageChange(false);
let m = provider.getMeasurement("translation", 1);
let values = yield m.getValues();
Assert.equal(values.days.size, 1);
Assert.ok(values.days.hasDay(now));
let day = values.days.getDay(now);
Assert.ok(day.has("detectedLanguageChangedBefore"));
Assert.equal(day.get("detectedLanguageChangedBefore"), 1);
Assert.ok(day.has("detectedLanguageChangedAfter"));
Assert.equal(day.get("detectedLanguageChangedAfter"), 2);
yield provider.shutdown();
yield storage.close();
});
// Test the payload after recording with telemetry enabled.
add_task(function* test_healthreporter_json() {
Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
let reporter = yield getHealthReporter("healthreporter_json");
yield reporter.init();
try {
let now = new Date();
let provider = new TranslationProvider();
yield reporter._providerManager.registerProvider(provider);
yield provider.recordTranslationOpportunity("fr", now);
yield provider.recordLanguageChange(true);
yield provider.recordTranslation("fr", "en", 1000, now);
yield provider.recordLanguageChange(false);
yield provider.recordTranslationOpportunity("es", now);
yield provider.recordTranslation("es", "en", 1000, now);
yield reporter.collectMeasurements();
let payload = yield reporter.getJSONPayload(true);
let today = reporter._formatDate(now);
Assert.ok(today in payload.data.days);
let day = payload.data.days[today];
Assert.ok("org.mozilla.translation.translation" in day);
let translations = day["org.mozilla.translation.translation"];
Assert.equal(translations["translationOpportunityCount"], 2);
Assert.equal(translations["pageTranslatedCount"], 2);
Assert.equal(translations["charactersTranslatedCount"], 2000);
Assert.ok("translationOpportunityCountsByLanguage" in translations);
Assert.equal(translations["translationOpportunityCountsByLanguage"]["fr"], 1);
Assert.equal(translations["translationOpportunityCountsByLanguage"]["es"], 1);
Assert.ok("pageTranslatedCountsByLanguage" in translations);
Assert.ok("fr" in translations["pageTranslatedCountsByLanguage"]);
Assert.equal(translations["pageTranslatedCountsByLanguage"]["fr"]["total"], 1);
Assert.equal(translations["pageTranslatedCountsByLanguage"]["fr"]["en"], 1);
Assert.ok("es" in translations["pageTranslatedCountsByLanguage"]);
Assert.equal(translations["pageTranslatedCountsByLanguage"]["es"]["total"], 1);
Assert.equal(translations["pageTranslatedCountsByLanguage"]["es"]["en"], 1);
Assert.ok("detectedLanguageChangedBefore" in translations);
Assert.equal(translations["detectedLanguageChangedBefore"], 1);
Assert.ok("detectedLanguageChangedAfter" in translations);
Assert.equal(translations["detectedLanguageChangedAfter"], 1);
} finally {
reporter._shutdown();
}
});
// Test the payload after recording with telemetry disabled.
add_task(function* test_healthreporter_json() {
Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
let reporter = yield getHealthReporter("healthreporter_json");
yield reporter.init();
try {
let now = new Date();
let provider = new TranslationProvider();
yield reporter._providerManager.registerProvider(provider);
yield provider.recordTranslationOpportunity("fr", now);
yield provider.recordLanguageChange(true);
yield provider.recordTranslation("fr", "en", 1000, now);
yield provider.recordLanguageChange(false);
yield provider.recordTranslationOpportunity("es", now);
yield provider.recordTranslation("es", "en", 1000, now);
yield reporter.collectMeasurements();
let payload = yield reporter.getJSONPayload(true);
let today = reporter._formatDate(now);
Assert.ok(today in payload.data.days);
let day = payload.data.days[today];
Assert.ok("org.mozilla.translation.translation" in day);
let translations = day["org.mozilla.translation.translation"];
Assert.ok(!("translationOpportunityCount" in translations));
Assert.ok(!("pageTranslatedCount" in translations));
Assert.ok(!("charactersTranslatedCount" in translations));
Assert.ok(!("translationOpportunityCountsByLanguage" in translations));
Assert.ok(!("pageTranslatedCountsByLanguage" in translations));
Assert.ok(!("detectedLanguageChangedBefore" in translations));
Assert.ok(!("detectedLanguageChangedAfter" in translations));
} finally {
reporter._shutdown();
}
});

View File

@ -4,3 +4,4 @@ tail =
firefox-appdir = browser
[test_cld2.js]
[test_healthreport.js]

View File

@ -0,0 +1,3 @@
#ifdef MOZ_SERVICES_HEALTHREPORT
category healthreport-js-provider-default TranslationProvider resource:///modules/translation/Translation.jsm
#endif

View File

@ -22,16 +22,16 @@ const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
const ITCHPAD_URL = "chrome://browser/content/devtools/projecteditor.xul";
// Enabled Plugins
require("projecteditor/plugins/dirty/lib/dirty");
require("projecteditor/plugins/delete/lib/delete");
require("projecteditor/plugins/new/lib/new");
require("projecteditor/plugins/save/lib/save");
require("projecteditor/plugins/image-view/lib/plugin");
require("projecteditor/plugins/app-manager/lib/plugin");
require("projecteditor/plugins/status-bar/lib/plugin");
require("projecteditor/plugins/dirty/dirty");
require("projecteditor/plugins/delete/delete");
require("projecteditor/plugins/new/new");
require("projecteditor/plugins/save/save");
require("projecteditor/plugins/image-view/plugin");
require("projecteditor/plugins/app-manager/plugin");
require("projecteditor/plugins/status-bar/plugin");
// Uncomment to enable logging.
// require("projecteditor/plugins/logging/lib/logging");
// require("projecteditor/plugins/logging/logging");
/**
* This is the main class tying together an instance of the ProjectEditor.

View File

@ -125,12 +125,12 @@
<!ENTITY certificateTab.label "Certificates">
<!ENTITY certSelection.description "When a server requests my personal certificate:">
<!ENTITY certs.auto "Select one automatically">
<!ENTITY certs.auto.accesskey "l">
<!ENTITY certs.auto.accesskey "S">
<!ENTITY certs.ask "Ask me every time">
<!ENTITY certs.ask.accesskey "i">
<!ENTITY certs.ask.accesskey "A">
<!ENTITY viewCerts.label "View Certificates">
<!ENTITY viewCerts.accesskey "s">
<!ENTITY viewCerts.accesskey "C">
<!ENTITY verify2.label "Validation">
<!ENTITY verify2.accesskey "V">
<!ENTITY viewSecurityDevices.label "Security Devices">
<!ENTITY viewSecurityDevices.accesskey "y">
<!ENTITY viewSecurityDevices.accesskey "D">

View File

@ -9,7 +9,7 @@
<!ENTITY dntTrackingNotOkay.label2 "Tell sites that I do not want to be tracked">
<!ENTITY dntTrackingNotOkay.accesskey "n">
<!ENTITY dntTrackingOkay.label2 "Tell sites that I want to be tracked">
<!ENTITY dntTrackingOkay.accesskey "t">
<!ENTITY dntTrackingOkay.accesskey "h">
<!ENTITY doNotTrackInfo.label "Learn More">
<!ENTITY history.label "History">

View File

@ -9,13 +9,13 @@
<!ENTITY warnCloseMultipleTabs.accesskey "m">
<!ENTITY warnOpenManyTabs.label "Warn me when opening multiple tabs might slow down &brandShortName;">
<!ENTITY warnOpenManyTabs.accesskey "o">
<!ENTITY warnOpenManyTabs.accesskey "d">
<!ENTITY restoreTabsOnDemand.label "Dont load tabs until selected">
<!ENTITY restoreTabsOnDemand.accesskey "l">
<!ENTITY restoreTabsOnDemand.accesskey "u">
<!ENTITY switchToNewTabs.label "When I open a link in a new tab, switch to it immediately">
<!ENTITY switchToNewTabs.accesskey "s">
<!ENTITY switchToNewTabs.accesskey "h">
<!ENTITY showTabsInTaskbar.label "Show tab previews in the Windows taskbar">
<!ENTITY showTabsInTaskbar.accesskey "k">

View File

@ -1528,6 +1528,67 @@ Example
}
org.mozilla.translation.translation
-----------------------------------
This daily measurement contains information about the usage of the translation
feature. It is a special telemetry measurement which will only be recorded in
FHR if telemetry is enabled.
Version 1
^^^^^^^^^
Daily counts are reported in the following properties:
translationOpportunityCount
Integer count of the number of opportunities there were to translate a page.
pageTranslatedCount
Integer count of the number of pages translated.
charactersTranslatedCount
Integer count of the number of characters translated.
detectedLanguageChangedBefore
Integer count of the number of times the user manually adjusted the detected
language before translating.
detectedLanguageChangedAfter
Integer count of the number of times the user manually adjusted the detected
language after having first translated the page.
Additional daily counts broken down by language are reported in the following
properties:
translationOpportunityCountsByLanguage
A mapping from language to count of opportunities to translate that
language.
pageTranslatedCountsByLanguage
A mapping from language to the counts of pages translated from that
language. Each language entry will be an object containing a "total" member
along with individual counts for each language translated to.
Example
^^^^^^^
::
"org.mozilla.translation.translation": {
"_v": 1,
"translationOpportunityCount": 134,
"pageTranslatedCount": 6,
"charactersTranslatedCount": "1126",
"detectedLanguageChangedBefore": 1,
"detectedLanguageChangedAfter": 2,
"translationOpportunityCountsByLanguage": {
"fr": 100,
"es": 34
},
"pageTranslatedCountsByLanguage": {
"fr": {
"total": 6,
"es": 5,
"en": 1
}
}
}
org.mozilla.experiments.info
----------------------------------

View File

@ -542,6 +542,9 @@ let WebConsoleUtils = {
get usageCount() {
if (WebConsoleUtils._usageCount < CONSOLE_ENTRY_THRESHOLD) {
WebConsoleUtils._usageCount = Services.prefs.getIntPref("devtools.selfxss.count")
if (Services.prefs.getBoolPref("devtools.chrome.enabled")) {
WebConsoleUtils.usageCount = CONSOLE_ENTRY_THRESHOLD;
}
}
return WebConsoleUtils._usageCount;
},