summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/basilisk/app/Makefile.in2
-rw-r--r--application/basilisk/app/profile/basilisk.js7
-rw-r--r--application/basilisk/base/content/browser.css5
-rw-r--r--application/basilisk/base/content/browser.js12
-rw-r--r--application/basilisk/base/content/browser.xul4
-rw-r--r--application/basilisk/base/content/tab-content.js7
-rw-r--r--application/basilisk/base/content/web-panels.xul15
-rw-r--r--application/basilisk/components/preferences/in-content/content.js31
-rw-r--r--application/basilisk/components/preferences/in-content/content.xul24
-rw-r--r--application/basilisk/components/preferences/jar.mn2
-rw-r--r--application/basilisk/components/preferences/translation.js255
-rw-r--r--application/basilisk/components/preferences/translation.xul88
-rw-r--r--application/basilisk/components/translation/BingTranslator.jsm449
-rw-r--r--application/basilisk/components/translation/Translation.jsm446
-rw-r--r--application/basilisk/components/translation/TranslationContentHandler.jsm181
-rw-r--r--application/basilisk/components/translation/TranslationDocument.jsm683
-rw-r--r--application/basilisk/components/translation/YandexTranslator.jsm343
-rw-r--r--application/basilisk/components/translation/jar.mn6
-rw-r--r--application/basilisk/components/translation/microsoft-translator-attribution.pngbin3422 -> 0 bytes
-rw-r--r--application/basilisk/components/translation/moz.build7
-rw-r--r--application/basilisk/components/translation/translation-infobar.xml441
-rw-r--r--application/basilisk/installer/package-manifest.in4
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/browser.dtd2
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/content.dtd15
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/translation.dtd24
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/translation.dtd75
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/translation.properties12
-rw-r--r--application/basilisk/locales/jar.mn3
-rw-r--r--application/basilisk/themes/linux/browser.css74
-rw-r--r--application/basilisk/themes/linux/preferences/preferences.css6
-rw-r--r--application/basilisk/themes/osx/browser.css133
-rw-r--r--application/basilisk/themes/osx/preferences/preferences.css5
-rw-r--r--application/basilisk/themes/shared/jar.inc.mn4
-rw-r--r--application/basilisk/themes/shared/notification-icons.inc.css24
-rw-r--r--application/basilisk/themes/shared/translation/infobar.inc.css95
-rw-r--r--application/basilisk/themes/shared/translation/translating-16.pngbin21270 -> 0 bytes
-rw-r--r--application/basilisk/themes/shared/translation/translating-16@2x.pngbin29889 -> 0 bytes
-rw-r--r--application/basilisk/themes/shared/translation/translation-16.pngbin889 -> 0 bytes
-rw-r--r--application/basilisk/themes/shared/translation/translation-16@2x.pngbin2076 -> 0 bytes
-rw-r--r--application/basilisk/themes/windows/browser.css81
-rw-r--r--application/basilisk/themes/windows/preferences/preferences.css7
-rw-r--r--application/palemoon/base/content/newtab/newTab.css1
-rw-r--r--application/palemoon/base/content/tabbrowser.xml13
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-1.js17
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-2.js7
-rw-r--r--js/src/jit/BacktrackingAllocator.cpp38
-rw-r--r--js/src/jit/BacktrackingAllocator.h30
-rw-r--r--layout/generic/nsGridContainerFrame.cpp8
-rw-r--r--layout/reftests/css-grid/bug1349571-ref.html90
-rw-r--r--layout/reftests/css-grid/bug1349571.html94
-rw-r--r--layout/reftests/css-grid/bug1356820-ref.html81
-rw-r--r--layout/reftests/css-grid/bug1356820.html81
-rw-r--r--layout/reftests/css-grid/reftest.list2
-rw-r--r--netwerk/base/nsIOService.cpp4
-rw-r--r--netwerk/base/nsNetUtilInlines.h4
-rw-r--r--testing/profiles/prefs_general.js6
-rw-r--r--toolkit/components/reader/AboutReader.jsm1
-rw-r--r--toolkit/components/reader/JSDOMParser.js32
-rw-r--r--toolkit/components/reader/Readability.js214
-rw-r--r--toolkit/components/reader/ReaderMode.jsm2
-rw-r--r--toolkit/components/reader/ReaderWorker.js2
-rw-r--r--toolkit/components/thumbnails/test/test_thumbnails_interfaces.js6
-rw-r--r--toolkit/content/widgets/browser.xml9
-rw-r--r--toolkit/mozapps/extensions/AddonManager.jsm223
-rw-r--r--toolkit/mozapps/extensions/LightweightThemeManager.jsm30
-rw-r--r--toolkit/mozapps/extensions/addonManager.js30
-rw-r--r--toolkit/mozapps/extensions/amInstallTrigger.js2
-rw-r--r--toolkit/mozapps/extensions/amWebInstallListener.js28
-rw-r--r--toolkit/themes/osx/global/notification.css4
-rw-r--r--tools/lint/eslint/modules.json1
70 files changed, 767 insertions, 3865 deletions
diff --git a/application/basilisk/app/Makefile.in b/application/basilisk/app/Makefile.in
index 4a3b9758e..83d6cb36a 100644
--- a/application/basilisk/app/Makefile.in
+++ b/application/basilisk/app/Makefile.in
@@ -87,8 +87,10 @@ tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME)
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
+ifdef MOZ_UPDATER
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
+endif
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
endif
diff --git a/application/basilisk/app/profile/basilisk.js b/application/basilisk/app/profile/basilisk.js
index fd81e8204..eeec29eb9 100644
--- a/application/basilisk/app/profile/basilisk.js
+++ b/application/basilisk/app/profile/basilisk.js
@@ -1266,13 +1266,6 @@ pref("media.gmp-widevinecdm.enabled", true);
// -1 means no experiment is run and we use the preferred value for frecency (6h)
pref("browser.cache.frecency_experiment", 0);
-pref("browser.translation.detectLanguage", false);
-pref("browser.translation.neverForLanguages", "");
-// Show the translation UI bits, like the info bar, notification icon and preferences.
-pref("browser.translation.ui.show", false);
-// Allows to define the translation engine. Bing is default, Yandex may optionally switched on.
-pref("browser.translation.engine", "bing");
-
// Telemetry settings.
// Determines if Telemetry pings can be archived locally.
pref("toolkit.telemetry.archive.enabled", true);
diff --git a/application/basilisk/base/content/browser.css b/application/basilisk/base/content/browser.css
index e951985dc..517c1c5eb 100644
--- a/application/basilisk/base/content/browser.css
+++ b/application/basilisk/base/content/browser.css
@@ -933,11 +933,6 @@ html|*#gcli-output-frame,
transition: none;
}
-/* Translation */
-notification[value="translation"] {
- -moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
-}
-
/** See bug 872317 for why the following rule is necessary. */
#downloads-button {
diff --git a/application/basilisk/base/content/browser.js b/application/basilisk/base/content/browser.js
index 4f4ebb08f..d45956191 100644
--- a/application/basilisk/base/content/browser.js
+++ b/application/basilisk/base/content/browser.js
@@ -45,7 +45,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
["SitePermissions", "resource:///modules/SitePermissions.jsm"],
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
["Task", "resource://gre/modules/Task.jsm"],
- ["Translation", "resource:///modules/translation/Translation.jsm"],
["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
["Weave", "resource://services-sync/main.js"],
["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
@@ -969,7 +968,6 @@ var gBrowserInit = {
// the listener is registered.
DOMLinkHandler.init();
gPageStyleMenu.init();
- LanguageDetectionListener.init();
BrowserOnClick.init();
FeedHandler.init();
DevEdition.init();
@@ -5680,16 +5678,6 @@ function setStyleDisabled(disabled) {
gPageStyleMenu.disableStyle();
}
-
-var LanguageDetectionListener = {
- init: function() {
- window.messageManager.addMessageListener("Translation:DocumentState", msg => {
- Translation.documentStateReceived(msg.target, msg.data);
- });
- }
-};
-
-
var BrowserOffline = {
_inited: false,
diff --git a/application/basilisk/base/content/browser.xul b/application/basilisk/base/content/browser.xul
index 74a90f5e0..3208538c1 100644
--- a/application/basilisk/base/content/browser.xul
+++ b/application/basilisk/base/content/browser.xul
@@ -675,10 +675,6 @@
tooltiptext="&urlbar.webRTCShareScreenNotificationAnchor.tooltip;"/>
<image id="servicesInstall-notification-icon" class="notification-anchor-icon service-icon" role="button"
tooltiptext="&urlbar.servicesNotificationAnchor.tooltip;"/>
- <image id="translate-notification-icon" class="notification-anchor-icon translation-icon" role="button"
- tooltiptext="&urlbar.translateNotificationAnchor.tooltip;"/>
- <image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button"
- tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/>
<image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
</box>
diff --git a/application/basilisk/base/content/tab-content.js b/application/basilisk/base/content/tab-content.js
index 11a9fabce..6d053dd2b 100644
--- a/application/basilisk/base/content/tab-content.js
+++ b/application/basilisk/base/content/tab-content.js
@@ -558,13 +558,6 @@ var PageStyleHandler = {
};
PageStyleHandler.init();
-// Keep a reference to the translation content handler to avoid it it being GC'ed.
-var trHandler = null;
-if (Services.prefs.getBoolPref("browser.translation.detectLanguage")) {
- Cu.import("resource:///modules/translation/TranslationContentHandler.jsm");
- trHandler = new TranslationContentHandler(global, docShell);
-}
-
function gKeywordURIFixup(fixupInfo) {
fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
if (!fixupInfo.consumer) {
diff --git a/application/basilisk/base/content/web-panels.xul b/application/basilisk/base/content/web-panels.xul
index 223b20ed7..ed868c24a 100644
--- a/application/basilisk/base/content/web-panels.xul
+++ b/application/basilisk/base/content/web-panels.xul
@@ -44,6 +44,21 @@
disabled="true"/>
<command id="Browser:Stop" oncommand="PanelBrowserStop();"/>
<command id="Browser:Reload" oncommand="PanelBrowserReload();"/>
+ <command id="Browser:BackOrBackDuplicate"
+ oncommand="getPanelBrowser().webNavigation.goBack(event);"
+ disabled="true">
+ <observes element="Browser:Back" attribute="disabled"/>
+ </command>
+ <command id="Browser:ForwardOrForwardDuplicate"
+ oncommand="getPanelBrowser().webNavigation.goForward(event);"
+ disabled="true">
+ <observes element="Browser:Forward" attribute="disabled"/>
+ </command>
+ <command id="Browser:ReloadOrDuplicate"
+ oncommand="PanelBrowserReload(event)"
+ disabled="true">
+ <observes element="Browser:Reload" attribute="disabled"/>
+ </command>
</commandset>
<popupset id="mainPopupSet">
diff --git a/application/basilisk/components/preferences/in-content/content.js b/application/basilisk/components/preferences/in-content/content.js
index a957b1dd5..2eac10ca4 100644
--- a/application/basilisk/components/preferences/in-content/content.js
+++ b/application/basilisk/components/preferences/in-content/content.js
@@ -31,18 +31,6 @@ var gContentPane = {
menulist.value = FontBuilder.readFontSelection(menulist);
}
- // Show translation preferences if we may:
- const prefName = "browser.translation.ui.show";
- if (Services.prefs.getBoolPref(prefName)) {
- let row = document.getElementById("translationBox");
- row.removeAttribute("hidden");
- // Showing attribution only for Bing Translator.
- Components.utils.import("resource:///modules/translation/Translation.jsm");
- if (Translation.translationEngine == "bing") {
- document.getElementById("bingAttribution").removeAttribute("hidden");
- }
- }
-
if (AlertsServiceDND) {
let notificationsDoNotDisturbRow =
document.getElementById("notificationsDoNotDisturbRow");
@@ -66,10 +54,6 @@ var gContentPane = {
gContentPane.configureColors);
setEventListener("chooseLanguage", "command",
gContentPane.showLanguages);
- setEventListener("translationAttributionImage", "click",
- gContentPane.openTranslationProviderAttribution);
- setEventListener("translateButton", "command",
- gContentPane.showTranslationExceptions);
setEventListener("notificationsDoNotDisturb", "command",
gContentPane.toggleDoNotDisturbNotifications);
@@ -274,21 +258,6 @@ var gContentPane = {
gSubDialog.open("chrome://browser/content/preferences/languages.xul");
},
- /**
- * Displays the translation exceptions dialog where specific site and language
- * translation preferences can be set.
- */
- showTranslationExceptions: function ()
- {
- gSubDialog.open("chrome://browser/content/preferences/translation.xul");
- },
-
- openTranslationProviderAttribution: function ()
- {
- Components.utils.import("resource:///modules/translation/Translation.jsm");
- Translation.openProviderAttribution();
- },
-
toggleDoNotDisturbNotifications: function (event)
{
AlertsServiceDND.manualDoNotDisturb = event.target.checked;
diff --git a/application/basilisk/components/preferences/in-content/content.xul b/application/basilisk/components/preferences/in-content/content.xul
index 9434cba62..fac864411 100644
--- a/application/basilisk/components/preferences/in-content/content.xul
+++ b/application/basilisk/components/preferences/in-content/content.xul
@@ -22,11 +22,6 @@
<preference id="font.language.group"
name="font.language.group"
type="wstring"/>
-
- <!-- Languages -->
- <preference id="browser.translation.detectLanguage"
- name="browser.translation.detectLanguage"
- type="bool"/>
</preferences>
<script type="application/javascript"
@@ -191,23 +186,4 @@
label="&chooseButton.label;"
accesskey="&chooseButton.accesskey;"/>
</hbox>
-
- <hbox id="translationBox" hidden="true">
- <hbox align="center" flex="1">
- <checkbox id="translate" preference="browser.translation.detectLanguage"
- label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
- onsyncfrompreference="return gContentPane.updateButtons('translateButton',
- 'browser.translation.detectLanguage');"/>
- <hbox id="bingAttribution" hidden="true">
- <label>&translation.options.attribution.beforeLogo;</label>
- <separator orient="vertical" class="thin"/>
- <image id="translationAttributionImage" aria-label="Microsoft Translator"
- src="chrome://browser/content/microsoft-translator-attribution.png"/>
- <separator orient="vertical" class="thin"/>
- <label>&translation.options.attribution.afterLogo;</label>
- </hbox>
- </hbox>
- <button id="translateButton" label="&translateExceptions.label;"
- accesskey="&translateExceptions.accesskey;"/>
- </hbox>
</groupbox>
diff --git a/application/basilisk/components/preferences/jar.mn b/application/basilisk/components/preferences/jar.mn
index d233c7865..5b24e89df 100644
--- a/application/basilisk/components/preferences/jar.mn
+++ b/application/basilisk/components/preferences/jar.mn
@@ -31,5 +31,3 @@ browser.jar:
content/browser/preferences/sanitize.js
content/browser/preferences/selectBookmark.xul
content/browser/preferences/selectBookmark.js
- content/browser/preferences/translation.xul
- content/browser/preferences/translation.js
diff --git a/application/basilisk/components/preferences/translation.js b/application/basilisk/components/preferences/translation.js
deleted file mode 100644
index cd570db0e..000000000
--- a/application/basilisk/components/preferences/translation.js
+++ /dev/null
@@ -1,255 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
-/* 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/. */
-
-"use strict";
-
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gLangBundle", () =>
- Services.strings.createBundle("chrome://global/locale/languageNames.properties"));
-
-const kPermissionType = "translate";
-const kLanguagesPref = "browser.translation.neverForLanguages";
-
-function Tree(aId, aData)
-{
- this._data = aData;
- this._tree = document.getElementById(aId);
- this._tree.view = this;
-}
-
-Tree.prototype = {
- get boxObject() {
- return this._tree.treeBoxObject;
- },
- get isEmpty() {
- return !this._data.length;
- },
- get hasSelection() {
- return this.selection.count > 0;
- },
- getSelectedItems: function() {
- let result = [];
-
- let rc = this.selection.getRangeCount();
- for (let i = 0; i < rc; ++i) {
- let min = {}, max = {};
- this.selection.getRangeAt(i, min, max);
- for (let j = min.value; j <= max.value; ++j)
- result.push(this._data[j]);
- }
-
- return result;
- },
-
- // nsITreeView implementation
- get rowCount() {
- return this._data.length;
- },
- getCellText: function (aRow, aColumn) {
- return this._data[aRow];
- },
- isSeparator: function(aIndex) {
- return false;
- },
- isSorted: function() {
- return false;
- },
- isContainer: function(aIndex) {
- return false;
- },
- setTree: function(aTree) {},
- getImageSrc: function(aRow, aColumn) {},
- getProgressMode: function(aRow, aColumn) {},
- getCellValue: function(aRow, aColumn) {},
- cycleHeader: function(column) {},
- getRowProperties: function(row) {
- return "";
- },
- getColumnProperties: function(column) {
- return "";
- },
- getCellProperties: function(row, column) {
- return "";
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.nsITreeView])
-};
-
-function Lang(aCode)
-{
- this.langCode = aCode;
- this._label = gLangBundle.GetStringFromName(aCode);
-}
-
-Lang.prototype = {
- toString: function() {
- return this._label;
- }
-}
-
-var gTranslationExceptions = {
- onLoad: function() {
- if (this._siteTree) {
- // Re-using an open dialog, clear the old observers.
- this.uninit();
- }
-
- // Load site permissions into an array.
- this._sites = [];
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-
- if (perm.type == kPermissionType &&
- perm.capability == Services.perms.DENY_ACTION) {
- this._sites.push(perm.principal.origin);
- }
- }
- Services.obs.addObserver(this, "perm-changed", false);
- this._sites.sort();
-
- this._siteTree = new Tree("sitesTree", this._sites);
- this.onSiteSelected();
-
- this._langs = this.getLanguageExceptions();
- Services.prefs.addObserver(kLanguagesPref, this, false);
- this._langTree = new Tree("languagesTree", this._langs);
- this.onLanguageSelected();
- },
-
- // Get the list of languages we don't translate as an array.
- getLanguageExceptions: function() {
- let langs = Services.prefs.getCharPref(kLanguagesPref);
- if (!langs)
- return [];
-
- let result = langs.split(",").map(code => new Lang(code));
- result.sort();
-
- return result;
- },
-
- observe: function(aSubject, aTopic, aData) {
- if (aTopic == "perm-changed") {
- if (aData == "cleared") {
- if (!this._sites.length)
- return;
- let removed = this._sites.splice(0, this._sites.length);
- this._siteTree.boxObject.rowCountChanged(0, - removed.length);
- }
- else {
- let perm = aSubject.QueryInterface(Ci.nsIPermission);
- if (perm.type != kPermissionType)
- return;
-
- if (aData == "added") {
- if (perm.capability != Services.perms.DENY_ACTION)
- return;
- this._sites.push(perm.principal.origin);
- this._sites.sort();
- let boxObject = this._siteTree.boxObject;
- boxObject.rowCountChanged(0, 1);
- boxObject.invalidate();
- }
- else if (aData == "deleted") {
- let index = this._sites.indexOf(perm.principal.origin);
- if (index == -1)
- return;
- this._sites.splice(index, 1);
- this._siteTree.boxObject.rowCountChanged(index, -1);
- this.onSiteSelected();
- return;
- }
- }
- this.onSiteSelected();
- }
- else if (aTopic == "nsPref:changed") {
- this._langs = this.getLanguageExceptions();
- let change = this._langs.length - this._langTree.rowCount;
- this._langTree._data = this._langs;
- let boxObject = this._langTree.boxObject;
- if (change)
- boxObject.rowCountChanged(0, change);
- boxObject.invalidate();
- this.onLanguageSelected();
- }
- },
-
- _handleButtonDisabling: function(aTree, aIdPart) {
- let empty = aTree.isEmpty;
- document.getElementById("removeAll" + aIdPart + "s").disabled = empty;
- document.getElementById("remove" + aIdPart).disabled =
- empty || !aTree.hasSelection;
- },
-
- onLanguageSelected: function() {
- this._handleButtonDisabling(this._langTree, "Language");
- },
-
- onSiteSelected: function() {
- this._handleButtonDisabling(this._siteTree, "Site");
- },
-
- onLanguageDeleted: function() {
- let langs = Services.prefs.getCharPref(kLanguagesPref);
- if (!langs)
- return;
-
- let removed = this._langTree.getSelectedItems().map(l => l.langCode);
-
- langs = langs.split(",").filter(l => removed.indexOf(l) == -1);
- Services.prefs.setCharPref(kLanguagesPref, langs.join(","));
- },
-
- onAllLanguagesDeleted: function() {
- Services.prefs.setCharPref(kLanguagesPref, "");
- },
-
- onSiteDeleted: function() {
- let removedSites = this._siteTree.getSelectedItems();
- for (let origin of removedSites) {
- let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
- Services.perms.removeFromPrincipal(principal, kPermissionType);
- }
- },
-
- onAllSitesDeleted: function() {
- if (this._siteTree.isEmpty)
- return;
-
- let removedSites = this._sites.splice(0, this._sites.length);
- this._siteTree.boxObject.rowCountChanged(0, -removedSites.length);
-
- for (let origin of removedSites) {
- let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
- Services.perms.removeFromPrincipal(principal, kPermissionType);
- }
-
- this.onSiteSelected();
- },
-
- onSiteKeyPress: function(aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE)
- this.onSiteDeleted();
- },
-
- onLanguageKeyPress: function(aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE)
- this.onLanguageDeleted();
- },
-
- onWindowKeyPress: function(aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
- window.close();
- },
-
- uninit: function() {
- Services.obs.removeObserver(this, "perm-changed");
- Services.prefs.removeObserver(kLanguagesPref, this);
- }
-};
diff --git a/application/basilisk/components/preferences/translation.xul b/application/basilisk/components/preferences/translation.xul
deleted file mode 100644
index b5dfd1b9b..000000000
--- a/application/basilisk/components/preferences/translation.xul
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/translation.dtd">
-
-<window id="TranslationDialog" class="windowDialog"
- windowtype="Browser:TranslationExceptions"
- title="&window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- style="width: &window.width;;"
- onload="gTranslationExceptions.onLoad();"
- onunload="gTranslationExceptions.uninit();"
- persist="screenX screenY width height"
- onkeypress="gTranslationExceptions.onWindowKeyPress(event);">
-
- <script src="chrome://browser/content/preferences/translation.js"/>
-
- <stringbundle id="bundlePreferences"
- src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <keyset>
- <key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
- </keyset>
-
- <vbox class="largeDialogContainer">
- <vbox class="contentPane" flex="1">
- <label id="languagesLabel" control="permissionsTree">&noTranslationForLanguages.label;</label>
- <separator class="thin"/>
- <tree id="languagesTree" flex="1" style="height: 12em;"
- hidecolumnpicker="true"
- onkeypress="gTranslationExceptions.onLanguageKeyPress(event)"
- onselect="gTranslationExceptions.onLanguageSelected();">
- <treecols>
- <treecol id="languageCol" label="&treehead.languageName.label;" flex="1"/>
- </treecols>
- <treechildren/>
- </tree>
- </vbox>
- <hbox align="end">
- <hbox class="actionButtons" flex="1">
- <button id="removeLanguage" disabled="true"
- accesskey="&removeLanguage.accesskey;"
- icon="remove" label="&removeLanguage.label;"
- oncommand="gTranslationExceptions.onLanguageDeleted();"/>
- <button id="removeAllLanguages"
- icon="clear" label="&removeAllLanguages.label;"
- accesskey="&removeAllLanguages.accesskey;"
- oncommand="gTranslationExceptions.onAllLanguagesDeleted();"/>
- <spacer flex="1"/>
- </hbox>
- </hbox>
- <separator/>
- <vbox class="contentPane" flex="1">
- <label id="languagesLabel" control="permissionsTree">&noTranslationForSites.label;</label>
- <separator class="thin"/>
- <tree id="sitesTree" flex="1" style="height: 12em;"
- hidecolumnpicker="true"
- onkeypress="gTranslationExceptions.onSiteKeyPress(event)"
- onselect="gTranslationExceptions.onSiteSelected();">
- <treecols>
- <treecol id="siteCol" label="&treehead.siteName.label;" flex="1"/>
- </treecols>
- <treechildren/>
- </tree>
- </vbox>
- </vbox>
- <hbox align="end">
- <hbox class="actionButtons" flex="1">
- <button id="removeSite" disabled="true"
- accesskey="&removeSite.accesskey;"
- icon="remove" label="&removeSite.label;"
- oncommand="gTranslationExceptions.onSiteDeleted();"/>
- <button id="removeAllSites"
- icon="clear" label="&removeAllSites.label;"
- accesskey="&removeAllSites.accesskey;"
- oncommand="gTranslationExceptions.onAllSitesDeleted();"/>
- <spacer flex="1"/>
- <button oncommand="close();" icon="close"
- label="&button.close.label;" accesskey="&button.close.accesskey;"/>
- </hbox>
- </hbox>
-</window>
diff --git a/application/basilisk/components/translation/BingTranslator.jsm b/application/basilisk/components/translation/BingTranslator.jsm
deleted file mode 100644
index fc1cc942a..000000000
--- a/application/basilisk/components/translation/BingTranslator.jsm
+++ /dev/null
@@ -1,449 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-this.EXPORTED_SYMBOLS = [ "BingTranslator" ];
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://gre/modules/Http.jsm");
-
-// The maximum amount of net data allowed per request on Bing's API.
-const MAX_REQUEST_DATA = 5000; // Documentation says 10000 but anywhere
- // close to that is refused by the service.
-
-// The maximum number of chunks allowed to be translated in a single
-// request.
-const MAX_REQUEST_CHUNKS = 1000; // Documentation says 2000.
-
-// Self-imposed limit of 15 requests. This means that a page that would need
-// to be broken in more than 15 requests won't be fully translated.
-// The maximum amount of data that we will translate for a single page
-// is MAX_REQUESTS * MAX_REQUEST_DATA.
-const MAX_REQUESTS = 15;
-
-/**
- * Translates a webpage using Bing's Translation API.
- *
- * @param translationDocument The TranslationDocument object that represents
- * the webpage to be translated
- * @param sourceLanguage The source language of the document
- * @param targetLanguage The target language for the translation
- *
- * @returns {Promise} A promise that will resolve when the translation
- * task is finished.
- */
-this.BingTranslator = function(translationDocument, sourceLanguage, targetLanguage) {
- this.translationDocument = translationDocument;
- this.sourceLanguage = sourceLanguage;
- this.targetLanguage = targetLanguage;
- this._pendingRequests = 0;
- this._partialSuccess = false;
- this._serviceUnavailable = false;
- this._translatedCharacterCount = 0;
-};
-
-this.BingTranslator.prototype = {
- /**
- * Performs the translation, splitting the document into several chunks
- * respecting the data limits of the API.
- *
- * @returns {Promise} A promise that will resolve when the translation
- * task is finished.
- */
- translate: function() {
- return Task.spawn(function *() {
- let currentIndex = 0;
- this._onFinishedDeferred = Promise.defer();
-
- // Let's split the document into various requests to be sent to
- // Bing's Translation API.
- for (let requestCount = 0; requestCount < MAX_REQUESTS; requestCount++) {
- // Generating the text for each request can be expensive, so
- // let's take the opportunity of the chunkification process to
- // allow for the event loop to attend other pending events
- // before we continue.
- yield CommonUtils.laterTickResolvingPromise();
-
- // Determine the data for the next request.
- let request = this._generateNextTranslationRequest(currentIndex);
-
- // Create a real request to the server, and put it on the
- // pending requests list.
- let bingRequest = new BingRequest(request.data,
- this.sourceLanguage,
- this.targetLanguage);
- this._pendingRequests++;
- bingRequest.fireRequest().then(this._chunkCompleted.bind(this),
- this._chunkFailed.bind(this));
-
- currentIndex = request.lastIndex;
- if (request.finished) {
- break;
- }
- }
-
- return this._onFinishedDeferred.promise;
- }.bind(this));
- },
-
- /**
- * Resets the expiration time of the current token, in order to
- * force the token manager to ask for a new token during the next request.
- */
- _resetToken : function() {
- // Force the token manager to get update token
- BingTokenManager._currentExpiryTime = 0;
- },
-
- /**
- * Function called when a request sent to the server completed successfully.
- * This function handles calling the function to parse the result and the
- * function to resolve the promise returned by the public `translate()`
- * method when there's no pending request left.
- *
- * @param request The BingRequest sent to the server.
- */
- _chunkCompleted: function(bingRequest) {
- if (this._parseChunkResult(bingRequest)) {
- this._partialSuccess = true;
- // Count the number of characters successfully translated.
- this._translatedCharacterCount += bingRequest.characterCount;
- }
-
- this._checkIfFinished();
- },
-
- /**
- * Function called when a request sent to the server has failed.
- * This function handles deciding if the error is transient or means the
- * service is unavailable (zero balance on the key or request credentials are
- * not in an active state) and calling the function to resolve the promise
- * returned by the public `translate()` method when there's no pending.
- * request left.
- *
- * @param aError [optional] The XHR object of the request that failed.
- */
- _chunkFailed: function(aError) {
- if (aError instanceof Ci.nsIXMLHttpRequest &&
- [400, 401].indexOf(aError.status) != -1) {
- let body = aError.responseText;
- if (body && body.includes("TranslateApiException") &&
- (body.includes("balance") || body.includes("active state")))
- this._serviceUnavailable = true;
- }
-
- this._checkIfFinished();
- },
-
- /**
- * Function called when a request sent to the server has completed.
- * This function handles resolving the promise
- * returned by the public `translate()` method when all chunks are completed.
- */
- _checkIfFinished: function() {
- // Check if all pending requests have been
- // completed and then resolves the promise.
- // If at least one chunk was successful, the
- // promise will be resolved positively which will
- // display the "Success" state for the infobar. Otherwise,
- // the "Error" state will appear.
- if (--this._pendingRequests == 0) {
- if (this._partialSuccess) {
- this._onFinishedDeferred.resolve({
- characterCount: this._translatedCharacterCount
- });
- } else {
- let error = this._serviceUnavailable ? "unavailable" : "failure";
- this._onFinishedDeferred.reject(error);
- }
- }
- },
-
- /**
- * This function parses the result returned by Bing's Http.svc API,
- * which is a XML file that contains a number of elements. To our
- * particular interest, the only part of the response that matters
- * are the <TranslatedText> nodes, which contains the resulting
- * items that were sent to be translated.
- *
- * @param request The request sent to the server.
- * @returns boolean True if parsing of this chunk was successful.
- */
- _parseChunkResult: function(bingRequest) {
- let results;
- try {
- let doc = bingRequest.networkRequest.responseXML;
- results = doc.querySelectorAll("TranslatedText");
- } catch (e) {
- return false;
- }
-
- let len = results.length;
- if (len != bingRequest.translationData.length) {
- // This should never happen, but if the service returns a different number
- // of items (from the number of items submitted), we can't use this chunk
- // because all items would be paired incorrectly.
- return false;
- }
-
- let error = false;
- for (let i = 0; i < len; i++) {
- try {
- let result = results[i].firstChild.nodeValue;
- let root = bingRequest.translationData[i][0];
-
- if (root.isSimpleRoot) {
- // Workaround for Bing's service problem in which "&" chars in
- // plain-text TranslationItems are double-escaped.
- result = result.replace(/&amp;/g, "&");
- }
-
- root.parseResult(result);
- } catch (e) { error = true; }
- }
-
- return !error;
- },
-
- /**
- * This function will determine what is the data to be used for
- * the Nth request we are generating, based on the input params.
- *
- * @param startIndex What is the index, in the roots list, that the
- * chunk should start.
- */
- _generateNextTranslationRequest: function(startIndex) {
- let currentDataSize = 0;
- let currentChunks = 0;
- let output = [];
- let rootsList = this.translationDocument.roots;
-
- for (let i = startIndex; i < rootsList.length; i++) {
- let root = rootsList[i];
- let text = this.translationDocument.generateTextForItem(root);
- if (!text) {
- continue;
- }
-
- text = escapeXML(text);
- let newCurSize = currentDataSize + text.length;
- let newChunks = currentChunks + 1;
-
- if (newCurSize > MAX_REQUEST_DATA ||
- newChunks > MAX_REQUEST_CHUNKS) {
-
- // If we've reached the API limits, let's stop accumulating data
- // for this request and return. We return information useful for
- // the caller to pass back on the next call, so that the function
- // can keep working from where it stopped.
- return {
- data: output,
- finished: false,
- lastIndex: i
- };
- }
-
- currentDataSize = newCurSize;
- currentChunks = newChunks;
- output.push([root, text]);
- }
-
- return {
- data: output,
- finished: true,
- lastIndex: 0
- };
- }
-};
-
-/**
- * Represents a request (for 1 chunk) sent off to Bing's service.
- *
- * @params translationData The data to be used for this translation,
- * generated by the generateNextTranslationRequest...
- * function.
- * @param sourceLanguage The source language of the document.
- * @param targetLanguage The target language for the translation.
- *
- */
-function BingRequest(translationData, sourceLanguage, targetLanguage) {
- this.translationData = translationData;
- this.sourceLanguage = sourceLanguage;
- this.targetLanguage = targetLanguage;
- this.characterCount = 0;
-}
-
-BingRequest.prototype = {
- /**
- * Initiates the request
- */
- fireRequest: function() {
- return Task.spawn(function *() {
- // Prepare authentication.
- let token = yield BingTokenManager.getToken();
- let auth = "Bearer " + token;
-
- // Prepare URL.
- let url = getUrlParam("https://api.microsofttranslator.com/v2/Http.svc/TranslateArray",
- "browser.translation.bing.translateArrayURL");
-
- // Prepare request headers.
- let headers = [["Content-type", "text/xml"], ["Authorization", auth]];
-
- // Prepare the request body.
- let requestString =
- '<TranslateArrayRequest>' +
- '<AppId/>' +
- '<From>' + this.sourceLanguage + '</From>' +
- '<Options>' +
- '<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/html</ContentType>' +
- '<ReservedFlags xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" />' +
- '</Options>' +
- '<Texts xmlns:s="http://schemas.microsoft.com/2003/10/Serialization/Arrays">';
-
- for (let [, text] of this.translationData) {
- requestString += '<s:string>' + text + '</s:string>';
- this.characterCount += text.length;
- }
-
- requestString += '</Texts>' +
- '<To>' + this.targetLanguage + '</To>' +
- '</TranslateArrayRequest>';
-
- // Set up request options.
- let deferred = Promise.defer();
- let options = {
- onLoad: (function(responseText, xhr) {
- deferred.resolve(this);
- }).bind(this),
- onError: function(e, responseText, xhr) {
- deferred.reject(xhr);
- },
- postData: requestString,
- headers: headers
- };
-
- // Fire the request.
- let request = httpRequest(url, options);
-
- // Override the response MIME type.
- request.overrideMimeType("text/xml");
- this.networkRequest = request;
- return deferred.promise;
- }.bind(this));
- }
-};
-
-/**
- * Authentication Token manager for the API
- */
-var BingTokenManager = {
- _currentToken: null,
- _currentExpiryTime: 0,
- _pendingRequest: null,
-
- /**
- * Get a valid, non-expired token to be used for the API calls.
- *
- * @returns {Promise} A promise that resolves with the token
- * string once it is obtained. The token returned
- * can be the same one used in the past if it is still
- * valid.
- */
- getToken: function() {
- if (this._pendingRequest) {
- return this._pendingRequest;
- }
-
- let remainingMs = this._currentExpiryTime - new Date();
- // Our existing token is still good for more than a minute, let's use it.
- if (remainingMs > 60 * 1000) {
- return Promise.resolve(this._currentToken);
- }
-
- return this._getNewToken();
- },
-
- /**
- * Generates a new token from the server.
- *
- * @returns {Promise} A promise that resolves with the token
- * string once it is obtained.
- */
- _getNewToken: function() {
- let url = getUrlParam("https://datamarket.accesscontrol.windows.net/v2/OAuth2-13",
- "browser.translation.bing.authURL");
- let params = [
- ["grant_type", "client_credentials"],
- ["scope", "http://api.microsofttranslator.com"],
- ["client_id",
- getUrlParam("%BING_API_CLIENTID%", "browser.translation.bing.clientIdOverride")],
- ["client_secret",
- getUrlParam("%BING_API_KEY%", "browser.translation.bing.apiKeyOverride")]
- ];
-
- let deferred = Promise.defer();
- let options = {
- onLoad: function(responseText, xhr) {
- BingTokenManager._pendingRequest = null;
- try {
- let json = JSON.parse(responseText);
-
- if (json.error) {
- deferred.reject(json.error);
- return;
- }
-
- let token = json.access_token;
- let expires_in = json.expires_in;
- BingTokenManager._currentToken = token;
- BingTokenManager._currentExpiryTime = new Date(Date.now() + expires_in * 1000);
- deferred.resolve(token);
- } catch (e) {
- deferred.reject(e);
- }
- },
- onError: function(e, responseText, xhr) {
- BingTokenManager._pendingRequest = null;
- deferred.reject(e);
- },
- postData: params
- };
-
- this._pendingRequest = deferred.promise;
- httpRequest(url, options);
-
- return deferred.promise;
- }
-};
-
-/**
- * Escape a string to be valid XML content.
- */
-function escapeXML(aStr) {
- return aStr.toString()
- .replace(/&/g, "&amp;")
- .replace(/\"/g, "&quot;")
- .replace(/\'/g, "&apos;")
- .replace(/</g, "&lt;")
- .replace(/>/g, "&gt;");
-}
-
-/**
- * Fetch an auth token (clientID or client secret), which may be overridden by
- * a pref if it's set.
- */
-function getUrlParam(paramValue, prefName) {
- if (Services.prefs.getPrefType(prefName))
- paramValue = Services.prefs.getCharPref(prefName);
- paramValue = Services.urlFormatter.formatURL(paramValue);
- return paramValue;
-}
diff --git a/application/basilisk/components/translation/Translation.jsm b/application/basilisk/components/translation/Translation.jsm
deleted file mode 100644
index 15a847c13..000000000
--- a/application/basilisk/components/translation/Translation.jsm
+++ /dev/null
@@ -1,446 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
- "Translation",
- "TranslationTelemetry",
-];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-const TRANSLATION_PREF_SHOWUI = "browser.translation.ui.show";
-const TRANSLATION_PREF_DETECT_LANG = "browser.translation.detectLanguage";
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm", this);
-
-this.Translation = {
- STATE_OFFER: 0,
- STATE_TRANSLATING: 1,
- STATE_TRANSLATED: 2,
- STATE_ERROR: 3,
- STATE_UNAVAILABLE: 4,
-
- serviceUnavailable: false,
-
- supportedSourceLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
- supportedTargetLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
-
- _defaultTargetLanguage: "",
- get defaultTargetLanguage() {
- if (!this._defaultTargetLanguage) {
- this._defaultTargetLanguage = Cc["@mozilla.org/chrome/chrome-registry;1"]
- .getService(Ci.nsIXULChromeRegistry)
- .getSelectedLocale("global")
- .split("-")[0];
- }
- return this._defaultTargetLanguage;
- },
-
- documentStateReceived: function(aBrowser, aData) {
- if (aData.state == this.STATE_OFFER) {
- if (aData.detectedLanguage == this.defaultTargetLanguage) {
- // Detected language is the same as the user's locale.
- return;
- }
-
- if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1) {
- // Detected language is not part of the supported languages.
- TranslationTelemetry.recordMissedTranslationOpportunity(aData.detectedLanguage);
- return;
- }
-
- TranslationTelemetry.recordTranslationOpportunity(aData.detectedLanguage);
- }
-
- if (!Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI))
- return;
-
- if (!aBrowser.translationUI)
- aBrowser.translationUI = new TranslationUI(aBrowser);
- let trUI = aBrowser.translationUI;
-
- // Set all values before showing a new translation infobar.
- trUI._state = Translation.serviceUnavailable ? Translation.STATE_UNAVAILABLE
- : aData.state;
- trUI.detectedLanguage = aData.detectedLanguage;
- trUI.translatedFrom = aData.translatedFrom;
- trUI.translatedTo = aData.translatedTo;
- trUI.originalShown = aData.originalShown;
-
- trUI.showURLBarIcon();
-
- if (trUI.shouldShowInfoBar(aBrowser.currentURI))
- trUI.showTranslationInfoBar();
- },
-
- openProviderAttribution: function() {
- let attribution = this.supportedEngines[this.translationEngine];
- Cu.import("resource:///modules/RecentWindow.jsm");
- RecentWindow.getMostRecentBrowserWindow().openUILinkIn(attribution, "tab");
- },
-
- /**
- * The list of translation engines and their attributions.
- */
- supportedEngines: {
- "bing" : "http://aka.ms/MicrosoftTranslatorAttribution",
- "yandex" : "http://translate.yandex.com/"
- },
-
- /**
- * Fallback engine (currently Bing Translator) if the preferences seem
- * confusing.
- */
- get defaultEngine() {
- return this.supportedEngines.keys[0];
- },
-
- /**
- * Returns the name of the preferred translation engine.
- */
- get translationEngine() {
- let engine = Services.prefs.getCharPref("browser.translation.engine");
- return Object.keys(this.supportedEngines).indexOf(engine) == -1 ? this.defaultEngine : engine;
- },
-};
-
-/* TranslationUI objects keep the information related to translation for
- * a specific browser. This object is passed to the translation
- * infobar so that it can initialize itself. The properties exposed to
- * the infobar are:
- * - detectedLanguage, code of the language detected on the web page.
- * - state, the state in which the infobar should be displayed
- * - translatedFrom, if already translated, source language code.
- * - translatedTo, if already translated, target language code.
- * - translate, method starting the translation of the current page.
- * - showOriginalContent, method showing the original page content.
- * - showTranslatedContent, method showing the translation for an
- * already translated page whose original content is shown.
- * - originalShown, boolean indicating if the original or translated
- * version of the page is shown.
- */
-function TranslationUI(aBrowser) {
- this.browser = aBrowser;
-}
-
-TranslationUI.prototype = {
- get browser() {
- return this._browser;
- },
- set browser(aBrowser) {
- if (this._browser)
- this._browser.messageManager.removeMessageListener("Translation:Finished", this);
- aBrowser.messageManager.addMessageListener("Translation:Finished", this);
- this._browser = aBrowser;
- },
- translate: function(aFrom, aTo) {
- if (aFrom == aTo ||
- (this.state == Translation.STATE_TRANSLATED &&
- this.translatedFrom == aFrom && this.translatedTo == aTo)) {
- // Nothing to do.
- return;
- }
-
- if (this.state == Translation.STATE_OFFER) {
- if (this.detectedLanguage != aFrom)
- TranslationTelemetry.recordDetectedLanguageChange(true);
- } else {
- if (this.translatedFrom != aFrom)
- TranslationTelemetry.recordDetectedLanguageChange(false);
- if (this.translatedTo != aTo)
- TranslationTelemetry.recordTargetLanguageChange();
- }
-
- this.state = Translation.STATE_TRANSLATING;
- this.translatedFrom = aFrom;
- this.translatedTo = aTo;
-
- this.browser.messageManager.sendAsyncMessage(
- "Translation:TranslateDocument",
- { from: aFrom, to: aTo }
- );
- },
-
- showURLBarIcon: function() {
- let chromeWin = this.browser.ownerGlobal;
- let PopupNotifications = chromeWin.PopupNotifications;
- let removeId = this.originalShown ? "translated" : "translate";
- let notification =
- PopupNotifications.getNotification(removeId, this.browser);
- if (notification)
- PopupNotifications.remove(notification);
-
- let callback = (aTopic, aNewBrowser) => {
- if (aTopic == "swapping") {
- let infoBarVisible =
- this.notificationBox.getNotificationWithValue("translation");
- aNewBrowser.translationUI = this;
- this.browser = aNewBrowser;
- if (infoBarVisible)
- this.showTranslationInfoBar();
- return true;
- }
-
- if (aTopic != "showing")
- return false;
- let notification = this.notificationBox.getNotificationWithValue("translation");
- if (notification)
- notification.close();
- else
- this.showTranslationInfoBar();
- return true;
- };
-
- let addId = this.originalShown ? "translate" : "translated";
- PopupNotifications.show(this.browser, addId, null,
- addId + "-notification-icon", null, null,
- {dismissed: true, eventCallback: callback});
- },
-
- _state: 0,
- get state() {
- return this._state;
- },
- set state(val) {
- let notif = this.notificationBox.getNotificationWithValue("translation");
- if (notif)
- notif.state = val;
- this._state = val;
- },
-
- originalShown: true,
- showOriginalContent: function() {
- this.originalShown = true;
- this.showURLBarIcon();
- this.browser.messageManager.sendAsyncMessage("Translation:ShowOriginal");
- TranslationTelemetry.recordShowOriginalContent();
- },
-
- showTranslatedContent: function() {
- this.originalShown = false;
- this.showURLBarIcon();
- this.browser.messageManager.sendAsyncMessage("Translation:ShowTranslation");
- },
-
- get notificationBox() {
- return this.browser.ownerGlobal.gBrowser.getNotificationBox(this.browser);
- },
-
- showTranslationInfoBar: function() {
- let notificationBox = this.notificationBox;
- let notif = notificationBox.appendNotification("", "translation", null,
- notificationBox.PRIORITY_INFO_HIGH);
- notif.init(this);
- return notif;
- },
-
- shouldShowInfoBar: function(aURI) {
- // Never show the infobar automatically while the translation
- // service is temporarily unavailable.
- if (Translation.serviceUnavailable)
- return false;
-
- // Check if we should never show the infobar for this language.
- let neverForLangs =
- Services.prefs.getCharPref("browser.translation.neverForLanguages");
- if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1) {
- TranslationTelemetry.recordAutoRejectedTranslationOffer();
- return false;
- }
-
- // or if we should never show the infobar for this domain.
- let perms = Services.perms;
- if (perms.testExactPermission(aURI, "translate") == perms.DENY_ACTION) {
- TranslationTelemetry.recordAutoRejectedTranslationOffer();
- return false;
- }
-
- return true;
- },
-
- receiveMessage: function(msg) {
- switch (msg.name) {
- case "Translation:Finished":
- if (msg.data.success) {
- this.originalShown = false;
- this.state = Translation.STATE_TRANSLATED;
- this.showURLBarIcon();
-
- // Record the number of characters translated.
- TranslationTelemetry.recordTranslation(msg.data.from, msg.data.to,
- msg.data.characterCount);
- } else if (msg.data.unavailable) {
- Translation.serviceUnavailable = true;
- this.state = Translation.STATE_UNAVAILABLE;
- } else {
- this.state = Translation.STATE_ERROR;
- }
- break;
- }
- },
-
- infobarClosed: function() {
- if (this.state == Translation.STATE_OFFER)
- TranslationTelemetry.recordDeniedTranslationOffer();
- }
-};
-
-/**
- * Uses telemetry histograms for collecting statistics on the usage of the
- * translation component.
- *
- * NOTE: Metrics are only recorded if the user enabled the telemetry option.
- */
-this.TranslationTelemetry = {
-
- init: function () {
- // Constructing histograms.
- const plain = (id) => Services.telemetry.getHistogramById(id);
- const keyed = (id) => Services.telemetry.getKeyedHistogramById(id);
- this.HISTOGRAMS = {
- OPPORTUNITIES : () => plain("TRANSLATION_OPPORTUNITIES"),
- OPPORTUNITIES_BY_LANG : () => keyed("TRANSLATION_OPPORTUNITIES_BY_LANGUAGE"),
- PAGES : () => plain("TRANSLATED_PAGES"),
- PAGES_BY_LANG : () => keyed("TRANSLATED_PAGES_BY_LANGUAGE"),
- CHARACTERS : () => plain("TRANSLATED_CHARACTERS"),
- DENIED : () => plain("DENIED_TRANSLATION_OFFERS"),
- AUTO_REJECTED : () => plain("AUTO_REJECTED_TRANSLATION_OFFERS"),
- SHOW_ORIGINAL : () => plain("REQUESTS_OF_ORIGINAL_CONTENT"),
- TARGET_CHANGES : () => plain("CHANGES_OF_TARGET_LANGUAGE"),
- DETECTION_CHANGES : () => plain("CHANGES_OF_DETECTED_LANGUAGE"),
- SHOW_UI : () => plain("SHOULD_TRANSLATION_UI_APPEAR"),
- DETECT_LANG : () => plain("SHOULD_AUTO_DETECT_LANGUAGE"),
- };
-
- // Capturing the values of flags at the startup.
- this.recordPreferences();
- },
-
- /**
- * Record a translation opportunity in the health report.
- * @param language
- * The language of the page.
- */
- recordTranslationOpportunity: function (language) {
- return this._recordOpportunity(language, true);
- },
-
- /**
- * Record a missed translation opportunity in the health report.
- * A missed opportunity is when the language detected is not part
- * of the supported languages.
- * @param language
- * The language of the page.
- */
- recordMissedTranslationOpportunity: function (language) {
- return this._recordOpportunity(language, false);
- },
-
- /**
- * Record an automatically rejected translation offer in the health
- * report. A translation offer is automatically rejected when a user
- * has previously clicked "Never translate this language" or "Never
- * translate this site", which results in the infobar not being shown for
- * the translation opportunity.
- *
- * These translation opportunities should still be recorded in addition to
- * recording the automatic rejection of the offer.
- */
- recordAutoRejectedTranslationOffer: function () {
- if (!this._canRecord) return;
- this.HISTOGRAMS.AUTO_REJECTED().add();
- },
-
- /**
- * 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) {
- if (!this._canRecord) return;
- this.HISTOGRAMS.PAGES().add();
- this.HISTOGRAMS.PAGES_BY_LANG().add(langFrom + " -> " + langTo);
- this.HISTOGRAMS.CHARACTERS().add(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.
- */
- recordDetectedLanguageChange: function (beforeFirstTranslation) {
- if (!this._canRecord) return;
- this.HISTOGRAMS.DETECTION_CHANGES().add(beforeFirstTranslation);
- },
-
- /**
- * Record a change of the target 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.
- */
- recordTargetLanguageChange: function () {
- if (!this._canRecord) return;
- this.HISTOGRAMS.TARGET_CHANGES().add();
- },
-
- /**
- * Record a denied translation offer.
- */
- recordDeniedTranslationOffer: function () {
- if (!this._canRecord) return;
- this.HISTOGRAMS.DENIED().add();
- },
-
- /**
- * Record a "Show Original" command use.
- */
- recordShowOriginalContent: function () {
- if (!this._canRecord) return;
- this.HISTOGRAMS.SHOW_ORIGINAL().add();
- },
-
- /**
- * Record the state of translation preferences.
- */
- recordPreferences: function () {
- if (!this._canRecord) return;
- if (Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI)) {
- this.HISTOGRAMS.SHOW_UI().add(1);
- }
- if (Services.prefs.getBoolPref(TRANSLATION_PREF_DETECT_LANG)) {
- this.HISTOGRAMS.DETECT_LANG().add(1);
- }
- },
-
- _recordOpportunity: function(language, success) {
- if (!this._canRecord) return;
- this.HISTOGRAMS.OPPORTUNITIES().add(success);
- this.HISTOGRAMS.OPPORTUNITIES_BY_LANG().add(language, success);
- },
-
- /**
- * A shortcut for reading the telemetry preference.
- *
- */
- _canRecord: function () {
- return Services.prefs.getBoolPref("toolkit.telemetry.enabled");
- }
-};
-
-this.TranslationTelemetry.init();
diff --git a/application/basilisk/components/translation/TranslationContentHandler.jsm b/application/basilisk/components/translation/TranslationContentHandler.jsm
deleted file mode 100644
index 3b0d59ddd..000000000
--- a/application/basilisk/components/translation/TranslationContentHandler.jsm
+++ /dev/null
@@ -1,181 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [ "TranslationContentHandler" ];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
- "resource:///modules/translation/LanguageDetector.jsm");
-
-const STATE_OFFER = 0;
-const STATE_TRANSLATED = 2;
-const STATE_ERROR = 3;
-
-this.TranslationContentHandler = function(global, docShell) {
- let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebProgress);
- webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
-
- global.addEventListener("pageshow", this);
-
- global.addMessageListener("Translation:TranslateDocument", this);
- global.addMessageListener("Translation:ShowTranslation", this);
- global.addMessageListener("Translation:ShowOriginal", this);
- this.global = global;
-}
-
-TranslationContentHandler.prototype = {
- handleEvent: function(aEvent) {
- // We are only listening to pageshow events.
- let target = aEvent.target;
-
- // Only handle top-level frames.
- let win = target.defaultView;
- if (win.parent !== win)
- return;
-
- let content = this.global.content;
- if (!content.detectedLanguage)
- return;
-
- let data = {};
- let trDoc = content.translationDocument;
- if (trDoc) {
- data.state = trDoc.translationError ? STATE_ERROR : STATE_TRANSLATED;
- data.translatedFrom = trDoc.translatedFrom;
- data.translatedTo = trDoc.translatedTo;
- data.originalShown = trDoc.originalShown;
- } else {
- data.state = STATE_OFFER;
- data.originalShown = true;
- }
- data.detectedLanguage = content.detectedLanguage;
-
- this.global.sendAsyncMessage("Translation:DocumentState", data);
- },
-
- /* nsIWebProgressListener implementation */
- onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
- if (!aWebProgress.isTopLevel ||
- !(aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) ||
- !this.global.content)
- return;
-
- let url = aRequest.name;
- if (!url.startsWith("http://") && !url.startsWith("https://"))
- return;
-
- let content = this.global.content;
- if (content.detectedLanguage)
- return;
-
- // Grab a 60k sample of text from the page.
- let encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
- .createInstance(Ci.nsIDocumentEncoder);
- encoder.init(content.document, "text/plain", encoder.SkipInvisibleContent);
- let string = encoder.encodeToStringWithMaxLength(60 * 1024);
-
- // Language detection isn't reliable on very short strings.
- if (string.length < 100)
- return;
-
- LanguageDetector.detectLanguage(string).then(result => {
- // Bail if we're not confident.
- if (!result.confident) {
- return;
- }
-
- // The window might be gone by now.
- if (Cu.isDeadWrapper(content)) {
- return;
- }
-
- content.detectedLanguage = result.language;
-
- let data = {
- state: STATE_OFFER,
- originalShown: true,
- detectedLanguage: result.language
- };
- this.global.sendAsyncMessage("Translation:DocumentState", data);
- });
- },
-
- // Unused methods.
- onProgressChange: function() {},
- onLocationChange: function() {},
- onStatusChange: function() {},
- onSecurityChange: function() {},
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
- Ci.nsISupportsWeakReference]),
-
- receiveMessage: function(msg) {
- switch (msg.name) {
- case "Translation:TranslateDocument":
- {
- Cu.import("resource:///modules/translation/TranslationDocument.jsm");
-
- // If a TranslationDocument already exists for this document, it should
- // be used instead of creating a new one so that we can use the original
- // content of the page for the new translation instead of the newly
- // translated text.
- let translationDocument = this.global.content.translationDocument ||
- new TranslationDocument(this.global.content.document);
-
- let preferredEngine = Services.prefs.getCharPref("browser.translation.engine");
- let translator = null;
- if (preferredEngine == "yandex") {
- Cu.import("resource:///modules/translation/YandexTranslator.jsm");
- translator = new YandexTranslator(translationDocument,
- msg.data.from,
- msg.data.to);
- } else {
- Cu.import("resource:///modules/translation/BingTranslator.jsm");
- translator = new BingTranslator(translationDocument,
- msg.data.from,
- msg.data.to);
- }
-
- this.global.content.translationDocument = translationDocument;
- translationDocument.translatedFrom = msg.data.from;
- translationDocument.translatedTo = msg.data.to;
- translationDocument.translationError = false;
-
- translator.translate().then(
- result => {
- this.global.sendAsyncMessage("Translation:Finished", {
- characterCount: result.characterCount,
- from: msg.data.from,
- to: msg.data.to,
- success: true
- });
- translationDocument.showTranslation();
- },
- error => {
- translationDocument.translationError = true;
- let data = {success: false};
- if (error == "unavailable")
- data.unavailable = true;
- this.global.sendAsyncMessage("Translation:Finished", data);
- }
- );
- break;
- }
-
- case "Translation:ShowOriginal":
- this.global.content.translationDocument.showOriginal();
- break;
-
- case "Translation:ShowTranslation":
- this.global.content.translationDocument.showTranslation();
- break;
- }
- }
-};
diff --git a/application/basilisk/components/translation/TranslationDocument.jsm b/application/basilisk/components/translation/TranslationDocument.jsm
deleted file mode 100644
index 058d07a49..000000000
--- a/application/basilisk/components/translation/TranslationDocument.jsm
+++ /dev/null
@@ -1,683 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-this.EXPORTED_SYMBOLS = [ "TranslationDocument" ];
-
-const SHOW_ELEMENT = Ci.nsIDOMNodeFilter.SHOW_ELEMENT;
-const SHOW_TEXT = Ci.nsIDOMNodeFilter.SHOW_TEXT;
-const TEXT_NODE = Ci.nsIDOMNode.TEXT_NODE;
-
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://gre/modules/Task.jsm");
-
-/**
- * This class represents a document that is being translated,
- * and it is responsible for parsing the document,
- * generating the data structures translation (the list of
- * translation items and roots), and managing the original
- * and translated texts on the translation items.
- *
- * @param document The document to be translated
- */
-this.TranslationDocument = function(document) {
- this.itemsMap = new Map();
- this.roots = [];
- this._init(document);
-};
-
-this.TranslationDocument.prototype = {
- translatedFrom: "",
- translatedTo: "",
- translationError: false,
- originalShown: true,
-
- /**
- * Initializes the object and populates
- * the roots lists.
- *
- * @param document The document to be translated
- */
- _init: function(document) {
- let window = document.defaultView;
- let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
-
- // Get all the translation nodes in the document's body:
- // a translation node is a node from the document which
- // contains useful content for translation, and therefore
- // must be included in the translation process.
- let nodeList = winUtils.getTranslationNodes(document.body);
-
- let length = nodeList.length;
-
- for (let i = 0; i < length; i++) {
- let node = nodeList.item(i);
- let isRoot = nodeList.isTranslationRootAtIndex(i);
-
- // Create a TranslationItem object for this node.
- // This function will also add it to the this.roots array.
- this._createItemForNode(node, i, isRoot);
- }
-
- // At first all roots are stored in the roots list, and only after
- // the process has finished we're able to determine which roots are
- // simple, and which ones are not.
-
- // A simple root is defined by a root with no children items, which
- // basically represents an element from a page with only text content
- // inside.
-
- // This distinction is useful for optimization purposes: we treat a
- // simple root as plain-text in the translation process and with that
- // we are able to reduce their data payload sent to the translation service.
-
- for (let root of this.roots) {
- if (root.children.length == 0 &&
- root.nodeRef.childElementCount == 0) {
- root.isSimpleRoot = true;
- }
- }
- },
-
- /**
- * Creates a TranslationItem object, which should be called
- * for each node returned by getTranslationNodes.
- *
- * @param node The DOM node for this item.
- * @param id A unique, numeric id for this item.
- * @parem isRoot A boolean saying whether this item is a root.
- *
- * @returns A TranslationItem object.
- */
- _createItemForNode: function(node, id, isRoot) {
- if (this.itemsMap.has(node)) {
- return this.itemsMap.get(node);
- }
-
- let item = new TranslationItem(node, id, isRoot);
-
- if (isRoot) {
- // Root items do not have a parent item.
- this.roots.push(item);
- } else {
- let parentItem = this.itemsMap.get(node.parentNode);
- if (parentItem) {
- parentItem.children.push(item);
- }
- }
-
- this.itemsMap.set(node, item);
- return item;
- },
-
- /**
- * Generate the text string that represents a TranslationItem object.
- * Besides generating the string, it's also stored in the "original"
- * field of the TranslationItem object, which needs to be stored for
- * later to be used in the "Show Original" functionality.
- * If this function had already been called for the given item (determined
- * by the presence of the "original" array in the item), the text will
- * be regenerated from the "original" data instead of from the related
- * DOM nodes (because the nodes might contain translated data).
- *
- * @param item A TranslationItem object
- *
- * @returns A string representation of the TranslationItem.
- */
- generateTextForItem: function(item) {
- if (item.original) {
- return regenerateTextFromOriginalHelper(item);
- }
-
- if (item.isSimpleRoot) {
- let text = item.nodeRef.firstChild.nodeValue.trim();
- item.original = [text];
- return text;
- }
-
- let str = "";
- item.original = [];
- let wasLastItemPlaceholder = false;
-
- for (let child of item.nodeRef.childNodes) {
- if (child.nodeType == TEXT_NODE) {
- let x = child.nodeValue.trim();
- if (x != "") {
- item.original.push(x);
- str += x;
- wasLastItemPlaceholder = false;
- }
- continue;
- }
-
- let objInMap = this.itemsMap.get(child);
- if (objInMap && !objInMap.isRoot) {
- // If this childNode is present in the itemsMap, it means
- // it's a translation node: it has useful content for translation.
- // In this case, we need to stringify this node.
- // However, if this item is a root, we should skip it here in this
- // object's child list (and just add a placeholder for it), because
- // it will be stringfied separately for being a root.
- item.original.push(objInMap);
- str += this.generateTextForItem(objInMap);
- wasLastItemPlaceholder = false;
- } else if (!wasLastItemPlaceholder) {
- // Otherwise, if this node doesn't contain any useful content,
- // or if it is a root itself, we can replace it with a placeholder node.
- // We can't simply eliminate this node from our string representation
- // because that could change the HTML structure (e.g., it would
- // probably merge two separate text nodes).
- // It's not necessary to add more than one placeholder in sequence;
- // we can optimize them away.
- item.original.push(TranslationItem_NodePlaceholder);
- str += '<br>';
- wasLastItemPlaceholder = true;
- }
- }
-
- return generateTranslationHtmlForItem(item, str);
- },
-
- /**
- * Changes the document to display its translated
- * content.
- */
- showTranslation: function() {
- this.originalShown = false;
- this._swapDocumentContent("translation");
- },
-
- /**
- * Changes the document to display its original
- * content.
- */
- showOriginal: function() {
- this.originalShown = true;
- this._swapDocumentContent("original");
- },
-
- /**
- * Swap the document with the resulting translation,
- * or back with the original content.
- *
- * @param target A string that is either "translation"
- * or "original".
- */
- _swapDocumentContent: function(target) {
- Task.spawn(function *() {
- // Let the event loop breath on every 100 nodes
- // that are replaced.
- const YIELD_INTERVAL = 100;
- let count = YIELD_INTERVAL;
-
- for (let root of this.roots) {
- root.swapText(target);
- if (count-- == 0) {
- count = YIELD_INTERVAL;
- yield CommonUtils.laterTickResolvingPromise();
- }
- }
- }.bind(this));
- }
-};
-
-/**
- * This class represents an item for translation. It's basically our
- * wrapper class around a node returned by getTranslationNode, with
- * more data and structural information on it.
- *
- * At the end of the translation process, besides the properties below,
- * a TranslationItem will contain two other properties: one called "original"
- * and one called "translation". They are twin objects, one which reflect
- * the structure of that node in its original state, and the other in its
- * translated state.
- *
- * The "original" array is generated in the generateTextForItem function,
- * and the "translation" array is generated when the translation results
- * are parsed.
- *
- * They are both arrays, which contain a mix of strings and references to
- * child TranslationItems. The references in both arrays point to the * same *
- * TranslationItem object, but they might appear in different orders between the
- * "original" and "translation" arrays.
- *
- * An example:
- *
- * English: <div id="n1">Welcome to <b id="n2">Mozilla's</b> website</div>
- * Portuguese: <div id="n1">Bem vindo a pagina <b id="n2">da Mozilla</b></div>
- *
- * TranslationItem n1 = {
- * id: 1,
- * original: ["Welcome to", ptr to n2, "website"]
- * translation: ["Bem vindo a pagina", ptr to n2]
- * }
- *
- * TranslationItem n2 = {
- * id: 2,
- * original: ["Mozilla's"],
- * translation: ["da Mozilla"]
- * }
- */
-function TranslationItem(node, id, isRoot) {
- this.nodeRef = node;
- this.id = id;
- this.isRoot = isRoot;
- this.children = [];
-}
-
-TranslationItem.prototype = {
- isRoot: false,
- isSimpleRoot: false,
-
- toString: function() {
- let rootType = "";
- if (this.isRoot) {
- if (this.isSimpleRoot) {
- rootType = " (simple root)";
- }
- else {
- rootType = " (non simple root)";
- }
- }
- return "[object TranslationItem: <" + this.nodeRef.localName + ">"
- + rootType + "]";
- },
-
- /**
- * This function will parse the result of the translation of one translation
- * item. If this item was a simple root, all we sent was a plain-text version
- * of it, so the result is also straightforward text.
- *
- * For non-simple roots, we sent a simplified HTML representation of that
- * node, and we'll first parse that into an HTML doc and then call the
- * parseResultNode helper function to parse it.
- *
- * While parsing, the result is stored in the "translation" field of the
- * TranslationItem, which will be used to display the final translation when
- * all items are finished. It remains stored too to allow back-and-forth
- * switching between the "Show Original" and "Show Translation" functions.
- *
- * @param result A string with the textual result received from the server,
- * which can be plain-text or a serialized HTML doc.
- */
- parseResult: function(result) {
- if (this.isSimpleRoot) {
- this.translation = [result];
- return;
- }
-
- let domParser = Cc["@mozilla.org/xmlextras/domparser;1"]
- .createInstance(Ci.nsIDOMParser);
-
- let doc = domParser.parseFromString(result, "text/html");
- parseResultNode(this, doc.body.firstChild);
- },
-
- /**
- * This function finds a child TranslationItem
- * with the given id.
- * @param id The id to look for, in the format "n#"
- * @returns A TranslationItem with the given id, or null if
- * it was not found.
- */
- getChildById: function(id) {
- for (let child of this.children) {
- if (("n" + child.id) == id) {
- return child;
- }
- }
- return null;
- },
-
- /**
- * Swap the text of this TranslationItem between
- * its original and translated states.
- *
- * @param target A string that is either "translation"
- * or "original".
- */
- swapText: function(target) {
- swapTextForItem(this, target);
- }
-};
-
-/**
- * This object represents a placeholder item for translation. It's similar to
- * the TranslationItem class, but it represents nodes that have no meaningful
- * content for translation. These nodes will be replaced by "<br>" in a
- * translation request. It's necessary to keep them to use it as a mark
- * for correct positioning and spliting of text nodes.
- */
-const TranslationItem_NodePlaceholder = {
- toString: function() {
- return "[object TranslationItem_NodePlaceholder]";
- }
-};
-
-/**
- * Generate the outer HTML representation for a given item.
- *
- * @param item A TranslationItem object.
- * param content The inner content for this item.
- * @returns string The outer HTML needed for translation
- * of this item.
- */
-function generateTranslationHtmlForItem(item, content) {
- let localName = item.isRoot ? "div" : "b";
- return '<' + localName + ' id=n' + item.id + '>' +
- content +
- "</" + localName + ">";
-}
-
- /**
- * Regenerate the text string that represents a TranslationItem object,
- * with data from its "original" array. The array must have already
- * been created by TranslationDocument.generateTextForItem().
- *
- * @param item A TranslationItem object
- *
- * @returns A string representation of the TranslationItem.
- */
-function regenerateTextFromOriginalHelper(item) {
- if (item.isSimpleRoot) {
- return item.original[0];
- }
-
- let str = "";
- for (let child of item.original) {
- if (child instanceof TranslationItem) {
- str += regenerateTextFromOriginalHelper(child);
- } else if (child === TranslationItem_NodePlaceholder) {
- str += "<br>";
- } else {
- str += child;
- }
- }
-
- return generateTranslationHtmlForItem(item, str);
-}
-
-/**
- * Helper function to parse a HTML doc result.
- * How it works:
- *
- * An example result string is:
- *
- * <div id="n1">Hello <b id="n2">World</b> of Mozilla.</div>
- *
- * For an element node, we look at its id and find the corresponding
- * TranslationItem that was associated with this node, and then we
- * walk down it repeating the process.
- *
- * For text nodes we simply add it as a string.
- */
-function parseResultNode(item, node) {
- item.translation = [];
- for (let child of node.childNodes) {
- if (child.nodeType == TEXT_NODE) {
- item.translation.push(child.nodeValue);
- } else if (child.localName == "br") {
- item.translation.push(TranslationItem_NodePlaceholder);
- } else {
- let translationItemChild = item.getChildById(child.id);
-
- if (translationItemChild) {
- item.translation.push(translationItemChild);
- parseResultNode(translationItemChild, child);
- }
- }
- }
-}
-
-/**
- * Helper function to swap the text of a TranslationItem
- * between its original and translated states.
- * How it works:
- *
- * The function iterates through the target array (either the `original` or
- * `translation` array from the TranslationItem), while also keeping a pointer
- * to a current position in the child nodes from the actual DOM node that we
- * are modifying. This pointer is moved forward after each item of the array
- * is translated. If, at any given time, the pointer doesn't match the expected
- * node that was supposed to be seen, it means that the original and translated
- * contents have a different ordering, and thus we need to adjust that.
- *
- * A full example of the reordering process, swapping from Original to
- * Translation:
- *
- * Original (en): <div>I <em>miss</em> <b>you</b></div>
- *
- * Translation (fr): <div><b>Tu</b> me <em>manques</em></div>
- *
- * Step 1:
- * pointer points to firstChild of the DOM node, textnode "I "
- * first item in item.translation is [object TranslationItem <b>]
- *
- * pointer does not match the expected element, <b>. So let's move <b> to the
- * pointer position.
- *
- * Current state of the DOM:
- * <div><b>you</b>I <em>miss</em> </div>
- *
- * Step 2:
- * pointer moves forward to nextSibling, textnode "I " again.
- * second item in item.translation is the string " me "
- *
- * pointer points to a text node, and we were expecting a text node. Match!
- * just replace the text content.
- *
- * Current state of the DOM:
- * <div><b>you</b> me <em>miss</em> </div>
- *
- * Step 3:
- * pointer moves forward to nextSibling, <em>miss</em>
- * third item in item.translation is [object TranslationItem <em>]
- *
- * pointer points to the expected node. Match! Nothing to do.
- *
- * Step 4:
- * all items in this item.translation were transformed. The remaining
- * text nodes are cleared to "", and domNode.normalize() removes them.
- *
- * Current state of the DOM:
- * <div><b>you</b> me <em>miss</em></div>
- *
- * Further steps:
- * After that, the function will visit the child items (from the visitStack),
- * and the text inside the <b> and <em> nodes will be swapped as well,
- * yielding the final result:
- *
- * <div><b>Tu</b> me <em>manques</em></div>
- *
- *
- * @param item A TranslationItem object
- * @param target A string that is either "translation"
- * or "original".
- */
-function swapTextForItem(item, target) {
- // visitStack is the stack of items that we still need to visit.
- // Let's start the process by adding the root item.
- let visitStack = [ item ];
-
- while (visitStack.length > 0) {
- let curItem = visitStack.shift();
-
- let domNode = curItem.nodeRef;
- if (!domNode) {
- // Skipping this item due to a missing node.
- continue;
- }
-
- if (!curItem[target]) {
- // Translation not found for this item. This could be due to
- // an error in the server response. For example, if a translation
- // was broken in various chunks, and one of the chunks failed,
- // the items from that chunk will be missing its "translation"
- // field.
- continue;
- }
-
- domNode.normalize();
-
- // curNode points to the child nodes of the DOM node that we are
- // modifying. During most of the process, while the target array is
- // being iterated (in the for loop below), it should walk together with
- // the array and be pointing to the correct node that needs to modified.
- // If it's not pointing to it, that means some sort of node reordering
- // will be necessary to produce the correct translation.
- // Note that text nodes don't need to be reordered, as we can just replace
- // the content of one text node with another.
- //
- // curNode starts in the firstChild...
- let curNode = domNode.firstChild;
-
- // ... actually, let's make curNode start at the first useful node (either
- // a non-blank text node or something else). This is not strictly necessary,
- // as the reordering algorithm would correctly handle this case. However,
- // this better aligns the resulting translation with the DOM content of the
- // page, avoiding cases that would need to be unecessarily reordered.
- //
- // An example of how this helps:
- //
- // ---- Original: <div> <b>Hello </b> world.</div>
- // ^textnode 1 ^item 1 ^textnode 2
- //
- // - Translation: <div><b>Hallo </b> Welt.</div>
- //
- // Transformation process without this optimization:
- // 1 - start pointer at textnode 1
- // 2 - move item 1 to first position inside the <div>
- //
- // Node now looks like: <div><b>Hello </b>[ ][ world.]</div>
- // textnode 1^ ^textnode 2
- //
- // 3 - replace textnode 1 with " Welt."
- // 4 - clear remaining text nodes (in this case, textnode 2)
- //
- // Transformation process with this optimization:
- // 1 - start pointer at item 1
- // 2 - item 1 is already in position
- // 3 - replace textnode 2 with " Welt."
- //
- // which completely avoids any node reordering, and requires only one
- // text change instead of two (while also leaving the page closer to
- // its original state).
- while (curNode &&
- curNode.nodeType == TEXT_NODE &&
- curNode.nodeValue.trim() == "") {
- curNode = curNode.nextSibling;
- }
-
- // Now let's walk through all items in the `target` array of the
- // TranslationItem. This means either the TranslationItem.original or
- // TranslationItem.translation array.
- for (let targetItem of curItem[target]) {
-
- if (targetItem instanceof TranslationItem) {
- // If the array element is another TranslationItem object, let's
- // add it to the stack to be visited.
- visitStack.push(targetItem);
-
- let targetNode = targetItem.nodeRef;
-
- // If the node is not in the expected position, let's reorder
- // it into position...
- if (curNode != targetNode &&
- // ...unless the page has reparented this node under a totally
- // different node (or removed it). In this case, all bets are off
- // on being able to do anything correctly, so it's better not to
- // bring back the node to this parent.
- targetNode.parentNode == domNode) {
-
- // We don't need to null-check curNode because insertBefore(..., null)
- // does what we need in that case: reorder this node to the end
- // of child nodes.
- domNode.insertBefore(targetNode, curNode);
- curNode = targetNode;
- }
-
- // Move pointer forward. Since we do not add empty text nodes to the
- // list of translation items, we must skip them here too while
- // traversing the DOM in order to get better alignment between the
- // text nodes and the translation items.
- if (curNode) {
- curNode = getNextSiblingSkippingEmptyTextNodes(curNode);
- }
-
- } else if (targetItem === TranslationItem_NodePlaceholder) {
- // If the current item is a placeholder node, we need to move
- // our pointer "past" it, jumping from one side of a block of
- // elements + empty text nodes to the other side. Even if
- // non-placeholder elements exists inside the jumped block,
- // they will be pulled correctly later in the process when the
- // targetItem for those nodes are handled.
-
- while (curNode &&
- (curNode.nodeType != TEXT_NODE ||
- curNode.nodeValue.trim() == "")) {
- curNode = curNode.nextSibling;
- }
-
- } else {
- // Finally, if it's a text item, we just need to find the next
- // text node to use. Text nodes don't need to be reordered, so
- // the first one found can be used.
- while (curNode && curNode.nodeType != TEXT_NODE) {
- curNode = curNode.nextSibling;
- }
-
- // If none was found and we reached the end of the child nodes,
- // let's create a new one.
- if (!curNode) {
- // We don't know if the original content had a space or not,
- // so the best bet is to create the text node with " " which
- // will add one space at the beginning and one at the end.
- curNode = domNode.appendChild(domNode.ownerDocument.createTextNode(" "));
- }
-
- // A trailing and a leading space must be preserved because
- // they are meaningful in HTML.
- let preSpace = /^\s/.test(curNode.nodeValue) ? " " : "";
- let endSpace = /\s$/.test(curNode.nodeValue) ? " " : "";
-
- curNode.nodeValue = preSpace + targetItem + endSpace;
- curNode = getNextSiblingSkippingEmptyTextNodes(curNode);
- }
- }
-
- // The translated version of a node might have less text nodes than its
- // original version. If that's the case, let's clear the remaining nodes.
- if (curNode) {
- clearRemainingNonEmptyTextNodesFromElement(curNode);
- }
-
- // And remove any garbage "" nodes left after clearing.
- domNode.normalize();
- }
-}
-
-function getNextSiblingSkippingEmptyTextNodes(startSibling) {
- let item = startSibling.nextSibling;
- while (item &&
- item.nodeType == TEXT_NODE &&
- item.nodeValue.trim() == "") {
- item = item.nextSibling;
- }
- return item;
-}
-
-function clearRemainingNonEmptyTextNodesFromElement(startSibling) {
- let item = startSibling;
- while (item) {
- if (item.nodeType == TEXT_NODE &&
- item.nodeValue != "") {
- item.nodeValue = "";
- }
- item = item.nextSibling;
- }
-}
diff --git a/application/basilisk/components/translation/YandexTranslator.jsm b/application/basilisk/components/translation/YandexTranslator.jsm
deleted file mode 100644
index ab92e0962..000000000
--- a/application/basilisk/components/translation/YandexTranslator.jsm
+++ /dev/null
@@ -1,343 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-this.EXPORTED_SYMBOLS = [ "YandexTranslator" ];
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://gre/modules/Http.jsm");
-
-// The maximum amount of net data allowed per request on Bing's API.
-const MAX_REQUEST_DATA = 5000; // Documentation says 10000 but anywhere
- // close to that is refused by the service.
-
-// The maximum number of chunks allowed to be translated in a single
-// request.
-const MAX_REQUEST_CHUNKS = 1000; // Documentation says 2000.
-
-// Self-imposed limit of 15 requests. This means that a page that would need
-// to be broken in more than 15 requests won't be fully translated.
-// The maximum amount of data that we will translate for a single page
-// is MAX_REQUESTS * MAX_REQUEST_DATA.
-const MAX_REQUESTS = 15;
-
-const YANDEX_RETURN_CODE_OK = 200;
-
-const YANDEX_ERR_KEY_INVALID = 401; // Invalid API key
-const YANDEX_ERR_KEY_BLOCKED = 402; // This API key has been blocked
-const YANDEX_ERR_DAILY_REQ_LIMIT_EXCEEDED = 403; // Daily limit for requests reached
-const YANDEX_ERR_DAILY_CHAR_LIMIT_EXCEEDED = 404; // Daily limit of chars reached
-const YANDEX_ERR_TEXT_TOO_LONG = 413; // The text size exceeds the maximum
-const YANDEX_ERR_UNPROCESSABLE_TEXT = 422; // The text could not be translated
-const YANDEX_ERR_LANG_NOT_SUPPORTED = 501; // The specified translation direction is not supported
-
-// Errors that should activate the service unavailable handling
-const YANDEX_PERMANENT_ERRORS = [
- YANDEX_ERR_KEY_INVALID,
- YANDEX_ERR_KEY_BLOCKED,
- YANDEX_ERR_DAILY_REQ_LIMIT_EXCEEDED,
- YANDEX_ERR_DAILY_CHAR_LIMIT_EXCEEDED,
-];
-
-/**
- * Translates a webpage using Yandex's Translation API.
- *
- * @param translationDocument The TranslationDocument object that represents
- * the webpage to be translated
- * @param sourceLanguage The source language of the document
- * @param targetLanguage The target language for the translation
- *
- * @returns {Promise} A promise that will resolve when the translation
- * task is finished.
- */
-this.YandexTranslator = function(translationDocument, sourceLanguage, targetLanguage) {
- this.translationDocument = translationDocument;
- this.sourceLanguage = sourceLanguage;
- this.targetLanguage = targetLanguage;
- this._pendingRequests = 0;
- this._partialSuccess = false;
- this._serviceUnavailable = false;
- this._translatedCharacterCount = 0;
-};
-
-this.YandexTranslator.prototype = {
- /**
- * Performs the translation, splitting the document into several chunks
- * respecting the data limits of the API.
- *
- * @returns {Promise} A promise that will resolve when the translation
- * task is finished.
- */
- translate: function() {
- return Task.spawn(function *() {
- let currentIndex = 0;
- this._onFinishedDeferred = Promise.defer();
-
- // Let's split the document into various requests to be sent to
- // Yandex's Translation API.
- for (let requestCount = 0; requestCount < MAX_REQUESTS; requestCount++) {
- // Generating the text for each request can be expensive, so
- // let's take the opportunity of the chunkification process to
- // allow for the event loop to attend other pending events
- // before we continue.
- yield CommonUtils.laterTickResolvingPromise();
-
- // Determine the data for the next request.
- let request = this._generateNextTranslationRequest(currentIndex);
-
- // Create a real request to the server, and put it on the
- // pending requests list.
- let yandexRequest = new YandexRequest(request.data,
- this.sourceLanguage,
- this.targetLanguage);
- this._pendingRequests++;
- yandexRequest.fireRequest().then(this._chunkCompleted.bind(this),
- this._chunkFailed.bind(this));
-
- currentIndex = request.lastIndex;
- if (request.finished) {
- break;
- }
- }
-
- return this._onFinishedDeferred.promise;
- }.bind(this));
- },
-
- /**
- * Function called when a request sent to the server completed successfully.
- * This function handles calling the function to parse the result and the
- * function to resolve the promise returned by the public `translate()`
- * method when there are no pending requests left.
- *
- * @param request The YandexRequest sent to the server
- */
- _chunkCompleted: function(yandexRequest) {
- if (this._parseChunkResult(yandexRequest)) {
- this._partialSuccess = true;
- // Count the number of characters successfully translated.
- this._translatedCharacterCount += yandexRequest.characterCount;
- }
-
- this._checkIfFinished();
- },
-
- /**
- * Function called when a request sent to the server has failed.
- * This function handles deciding if the error is transient or means the
- * service is unavailable (zero balance on the key or request credentials are
- * not in an active state) and calling the function to resolve the promise
- * returned by the public `translate()` method when there are no pending
- * requests left.
- *
- * @param aError [optional] The XHR object of the request that failed.
- */
- _chunkFailed: function(aError) {
- if (aError instanceof Ci.nsIXMLHttpRequest) {
- let body = aError.responseText;
- let json = { code: 0 };
- try {
- json = JSON.parse(body);
- } catch (e) {}
-
- if (json.code && YANDEX_PERMANENT_ERRORS.indexOf(json.code) != -1)
- this._serviceUnavailable = true;
- }
-
- this._checkIfFinished();
- },
-
- /**
- * Function called when a request sent to the server has completed.
- * This function handles resolving the promise
- * returned by the public `translate()` method when all chunks are completed.
- */
- _checkIfFinished: function() {
- // Check if all pending requests have been
- // completed and then resolves the promise.
- // If at least one chunk was successful, the
- // promise will be resolved positively which will
- // display the "Success" state for the infobar. Otherwise,
- // the "Error" state will appear.
- if (--this._pendingRequests == 0) {
- if (this._partialSuccess) {
- this._onFinishedDeferred.resolve({
- characterCount: this._translatedCharacterCount
- });
- } else {
- let error = this._serviceUnavailable ? "unavailable" : "failure";
- this._onFinishedDeferred.reject(error);
- }
- }
- },
-
- /**
- * This function parses the result returned by Yandex's Translation API,
- * which returns a JSON result that contains a number of elements. The
- * API is documented here:
- * http://api.yandex.com/translate/doc/dg/reference/translate.xml
- *
- * @param request The request sent to the server.
- * @returns boolean True if parsing of this chunk was successful.
- */
- _parseChunkResult: function(yandexRequest) {
- let results;
- try {
- let result = JSON.parse(yandexRequest.networkRequest.responseText);
- if (result.code != 200) {
- Services.console.logStringMessage("YandexTranslator: Result is " + result.code);
- return false;
- }
- results = result.text
- } catch (e) {
- return false;
- }
-
- let len = results.length;
- if (len != yandexRequest.translationData.length) {
- // This should never happen, but if the service returns a different number
- // of items (from the number of items submitted), we can't use this chunk
- // because all items would be paired incorrectly.
- return false;
- }
-
- let error = false;
- for (let i = 0; i < len; i++) {
- try {
- let result = results[i];
- let root = yandexRequest.translationData[i][0];
- root.parseResult(result);
- } catch (e) { error = true; }
- }
-
- return !error;
- },
-
- /**
- * This function will determine what is the data to be used for
- * the Nth request we are generating, based on the input params.
- *
- * @param startIndex What is the index, in the roots list, that the
- * chunk should start.
- */
- _generateNextTranslationRequest: function(startIndex) {
- let currentDataSize = 0;
- let currentChunks = 0;
- let output = [];
- let rootsList = this.translationDocument.roots;
-
- for (let i = startIndex; i < rootsList.length; i++) {
- let root = rootsList[i];
- let text = this.translationDocument.generateTextForItem(root);
- if (!text) {
- continue;
- }
-
- let newCurSize = currentDataSize + text.length;
- let newChunks = currentChunks + 1;
-
- if (newCurSize > MAX_REQUEST_DATA ||
- newChunks > MAX_REQUEST_CHUNKS) {
-
- // If we've reached the API limits, let's stop accumulating data
- // for this request and return. We return information useful for
- // the caller to pass back on the next call, so that the function
- // can keep working from where it stopped.
- return {
- data: output,
- finished: false,
- lastIndex: i
- };
- }
-
- currentDataSize = newCurSize;
- currentChunks = newChunks;
- output.push([root, text]);
- }
-
- return {
- data: output,
- finished: true,
- lastIndex: 0
- };
- }
-};
-
-/**
- * Represents a request (for 1 chunk) sent off to Yandex's service.
- *
- * @params translationData The data to be used for this translation,
- * generated by the generateNextTranslationRequest...
- * function.
- * @param sourceLanguage The source language of the document.
- * @param targetLanguage The target language for the translation.
- *
- */
-function YandexRequest(translationData, sourceLanguage, targetLanguage) {
- this.translationData = translationData;
- this.sourceLanguage = sourceLanguage;
- this.targetLanguage = targetLanguage;
- this.characterCount = 0;
-}
-
-YandexRequest.prototype = {
- /**
- * Initiates the request
- */
- fireRequest: function() {
- return Task.spawn(function *() {
- // Prepare URL.
- let url = getUrlParam("https://translate.yandex.net/api/v1.5/tr.json/translate",
- "browser.translation.yandex.translateURLOverride");
-
- // Prepare the request body.
- let apiKey = getUrlParam("%YANDEX_API_KEY%", "browser.translation.yandex.apiKeyOverride");
- let params = [
- ["key", apiKey],
- ["format", "html"],
- ["lang", this.sourceLanguage + "-" + this.targetLanguage],
- ];
-
- for (let [, text] of this.translationData) {
- params.push(["text", text]);
- this.characterCount += text.length;
- }
-
- // Set up request options.
- let deferred = Promise.defer();
- let options = {
- onLoad: (function(responseText, xhr) {
- deferred.resolve(this);
- }).bind(this),
- onError: function(e, responseText, xhr) {
- deferred.reject(xhr);
- },
- postData: params
- };
-
- // Fire the request.
- this.networkRequest = httpRequest(url, options);
-
- return deferred.promise;
- }.bind(this));
- }
-};
-
-/**
- * Fetch an auth token (clientID or client secret), which may be overridden by
- * a pref if it's set.
- */
-function getUrlParam(paramValue, prefName) {
- if (Services.prefs.getPrefType(prefName))
- paramValue = Services.prefs.getCharPref(prefName);
- paramValue = Services.urlFormatter.formatURL(paramValue);
- return paramValue;
-}
diff --git a/application/basilisk/components/translation/jar.mn b/application/basilisk/components/translation/jar.mn
deleted file mode 100644
index be744cb9e..000000000
--- a/application/basilisk/components/translation/jar.mn
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-browser.jar:
- content/browser/translation-infobar.xml
- content/browser/microsoft-translator-attribution.png
diff --git a/application/basilisk/components/translation/microsoft-translator-attribution.png b/application/basilisk/components/translation/microsoft-translator-attribution.png
deleted file mode 100644
index d9d277461..000000000
--- a/application/basilisk/components/translation/microsoft-translator-attribution.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/components/translation/moz.build b/application/basilisk/components/translation/moz.build
index ac0165230..32421e430 100644
--- a/application/basilisk/components/translation/moz.build
+++ b/application/basilisk/components/translation/moz.build
@@ -3,14 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES.translation = [
- 'BingTranslator.jsm',
'cld2/cld-worker.js',
'cld2/cld-worker.js.mem',
'LanguageDetector.jsm',
- 'Translation.jsm',
- 'TranslationContentHandler.jsm',
- 'TranslationDocument.jsm',
- 'YandexTranslator.jsm'
]
-
-JAR_MANIFESTS += ['jar.mn']
diff --git a/application/basilisk/components/translation/translation-infobar.xml b/application/basilisk/components/translation/translation-infobar.xml
deleted file mode 100644
index db0695c03..000000000
--- a/application/basilisk/components/translation/translation-infobar.xml
+++ /dev/null
@@ -1,441 +0,0 @@
-<?xml version="1.0"?>
-<!-- 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/. -->
-
-<!DOCTYPE bindings [
-<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
-%notificationDTD;
-<!ENTITY % translationDTD SYSTEM "chrome://browser/locale/translation.dtd" >
-%translationDTD;
-]>
-
-<bindings id="translationBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
- <binding id="translationbar" extends="chrome://global/content/bindings/notification.xml#notification" role="xul:alert">
- <resources>
- <stylesheet src="chrome://global/skin/notification.css"/>
- </resources>
- <content>
- <xul:hbox class="notification-inner" flex="1" xbl:inherits="type">
- <xul:hbox anonid="details" align="center" flex="1">
- <xul:image class="translate-infobar-element messageImage"
- anonid="messageImage"/>
- <xul:panel anonid="welcomePanel" class="translation-welcome-panel"
- type="arrow" align="start">
- <xul:image class="translation-welcome-logo"/>
- <xul:vbox flex="1" class="translation-welcome-content">
- <xul:description class="translation-welcome-headline"
- anonid="welcomeHeadline"/>
- <xul:description class="translation-welcome-body" anonid="welcomeBody"/>
- <xul:hbox align="center">
- <xul:label anonid="learnMore" class="plain text-link"
- onclick="openUILinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();"/>
- <xul:spacer flex="1"/>
- <xul:button class="translate-infobar-element" anonid="thanksButton"
- onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
- </xul:hbox>
- </xul:vbox>
- </xul:panel>
- <xul:deck anonid="translationStates" selectedIndex="0">
-
- <!-- offer to translate -->
- <xul:hbox class="translate-offer-box" align="center">
- <xul:label class="translate-infobar-element" value="&translation.thisPageIsIn.label;"/>
- <xul:menulist class="translate-infobar-element" anonid="detectedLanguage">
- <xul:menupopup/>
- </xul:menulist>
- <xul:label class="translate-infobar-element" value="&translation.translateThisPage.label;"/>
- <xul:button class="translate-infobar-element"
- label="&translation.translate.button;"
- anonid="translate"
- oncommand="document.getBindingParent(this).translate();"/>
- <xul:button class="translate-infobar-element"
- label="&translation.notNow.button;" anonid="notNow"
- oncommand="document.getBindingParent(this).closeCommand();"/>
- </xul:hbox>
-
- <!-- translating -->
- <xul:vbox class="translating-box" pack="center">
- <xul:label class="translate-infobar-element"
- value="&translation.translatingContent.label;"/>
- </xul:vbox>
-
- <!-- translated -->
- <xul:hbox class="translated-box" align="center">
- <xul:label class="translate-infobar-element"
- value="&translation.translatedFrom.label;"/>
- <xul:menulist class="translate-infobar-element"
- anonid="fromLanguage"
- oncommand="document.getBindingParent(this).translate()">
- <xul:menupopup/>
- </xul:menulist>
- <xul:label class="translate-infobar-element"
- value="&translation.translatedTo.label;"/>
- <xul:menulist class="translate-infobar-element"
- anonid="toLanguage"
- oncommand="document.getBindingParent(this).translate()">
- <xul:menupopup/>
- </xul:menulist>
- <xul:label class="translate-infobar-element"
- value="&translation.translatedToSuffix.label;"/>
- <xul:button anonid="showOriginal"
- class="translate-infobar-element"
- label="&translation.showOriginal.button;"
- oncommand="document.getBindingParent(this).showOriginal();"/>
- <xul:button anonid="showTranslation"
- class="translate-infobar-element"
- label="&translation.showTranslation.button;"
- oncommand="document.getBindingParent(this).showTranslation();"/>
- </xul:hbox>
-
- <!-- error -->
- <xul:hbox class="translation-error" align="center">
- <xul:label class="translate-infobar-element"
- value="&translation.errorTranslating.label;"/>
- <xul:button class="translate-infobar-element"
- label="&translation.tryAgain.button;"
- anonid="tryAgain"
- oncommand="document.getBindingParent(this).translate();"/>
- </xul:hbox>
-
- <!-- unavailable -->
- <xul:vbox class="translation-unavailable" pack="center">
- <xul:label class="translate-infobar-element"
- value="&translation.serviceUnavailable.label;"/>
- </xul:vbox>
-
- </xul:deck>
- <xul:spacer flex="1"/>
-
- <xul:button type="menu"
- class="translate-infobar-element options-menu-button"
- anonid="options"
- label="&translation.options.menu;">
- <xul:menupopup class="translation-menupopup cui-widget-panel cui-widget-panelview
- cui-widget-panelWithFooter PanelUI-subView"
- onpopupshowing="document.getBindingParent(this).optionsShowing();">
- <xul:menuitem anonid="neverForLanguage"
- oncommand="document.getBindingParent(this).neverForLanguage();"/>
- <xul:menuitem anonid="neverForSite"
- oncommand="document.getBindingParent(this).neverForSite();"
- label="&translation.options.neverForSite.label;"
- accesskey="&translation.options.neverForSite.accesskey;"/>
- <xul:menuseparator/>
- <xul:menuitem oncommand="openPreferences('paneContent');"
- label="&translation.options.preferences.label;"
- accesskey="&translation.options.preferences.accesskey;"/>
- <xul:menuitem class="subviewbutton panel-subview-footer"
- oncommand="document.getBindingParent(this).openProviderAttribution();">
- <xul:deck anonid="translationEngine" selectedIndex="0">
- <xul:hbox class="translation-attribution">
- <xul:label>&translation.options.attribution.beforeLogo;</xul:label>
- <xul:image src="chrome://browser/content/microsoft-translator-attribution.png"
- aria-label="Microsoft Translator"/>
- <xul:label>&translation.options.attribution.afterLogo;</xul:label>
- </xul:hbox>
- <xul:label class="translation-attribution">&translation.options.attribution.yandexTranslate;</xul:label>
- </xul:deck>
- </xul:menuitem>
- </xul:menupopup>
- </xul:button>
-
- </xul:hbox>
- <xul:toolbarbutton ondblclick="event.stopPropagation();"
- anonid="closeButton"
- class="messageCloseButton close-icon tabbable"
- xbl:inherits="hidden=hideclose"
- tooltiptext="&closeNotification.tooltip;"
- oncommand="document.getBindingParent(this).closeCommand();"/>
- </xul:hbox>
- </content>
- <implementation>
- <property name="state"
- onget="return this._getAnonElt('translationStates').selectedIndex;">
- <setter>
- <![CDATA[
- let deck = this._getAnonElt('translationStates');
-
- let activeElt = document.activeElement;
- if (activeElt && deck.contains(activeElt))
- activeElt.blur();
-
- let stateName;
- for (let name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
- if (Translation["STATE_" + name] == val) {
- stateName = name.toLowerCase();
- break;
- }
- }
- this.setAttribute("state", stateName);
-
- if (val == Translation.STATE_TRANSLATED)
- this._handleButtonHiding();
-
- deck.selectedIndex = val;
- ]]>
- </setter>
- </property>
-
- <method name="init">
- <parameter name="aTranslation"/>
- <body>
- <![CDATA[
- this.translation = aTranslation;
- let bundle = Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService)
- .createBundle("chrome://global/locale/languageNames.properties");
- let sortByLocalizedName = function(aList) {
- return aList.map(code => [code, bundle.GetStringFromName(code)])
- .sort((a, b) => a[1].localeCompare(b[1]));
- };
-
- // Fill the lists of supported source languages.
- let detectedLanguage = this._getAnonElt("detectedLanguage");
- let fromLanguage = this._getAnonElt("fromLanguage");
- let sourceLanguages =
- sortByLocalizedName(Translation.supportedSourceLanguages);
- for (let [code, name] of sourceLanguages) {
- detectedLanguage.appendItem(name, code);
- fromLanguage.appendItem(name, code);
- }
- detectedLanguage.value = this.translation.detectedLanguage;
-
- // translatedFrom is only set if we have already translated this page.
- if (aTranslation.translatedFrom)
- fromLanguage.value = aTranslation.translatedFrom;
-
- // Fill the list of supported target languages.
- let toLanguage = this._getAnonElt("toLanguage");
- let targetLanguages =
- sortByLocalizedName(Translation.supportedTargetLanguages);
- for (let [code, name] of targetLanguages)
- toLanguage.appendItem(name, code);
-
- if (aTranslation.translatedTo)
- toLanguage.value = aTranslation.translatedTo;
-
- if (aTranslation.state)
- this.state = aTranslation.state;
-
- // Show attribution for the preferred translator.
- let engineIndex = Object.keys(Translation.supportedEngines)
- .indexOf(Translation.translationEngine);
- if (engineIndex != -1) {
- this._getAnonElt('translationEngine').selectedIndex = engineIndex;
- }
-
- const kWelcomePref = "browser.translation.ui.welcomeMessageShown";
- if (Services.prefs.prefHasUserValue(kWelcomePref) ||
- this.translation.browser != gBrowser.selectedBrowser)
- return;
-
- this.addEventListener("transitionend", function onShown() {
- this.removeEventListener("transitionend", onShown);
-
- // These strings are hardcoded because they need to reach beta
- // without riding the trains.
- let localizedStrings = {
- en: ["Hey look! It's something new!",
- "Now the Web is even more accessible with our new in-page translation feature. Click the translate button to try it!",
- "Learn more.",
- "Thanks"],
- "es-AR": ["\xA1Mir\xE1! \xA1Hay algo nuevo!",
- "Ahora la web es a\xFAn m\xE1s accesible con nuestra nueva funcionalidad de traducci\xF3n integrada. \xA1Hac\xE9 clic en el bot\xF3n traducir para probarla!",
- "Conoc\xE9 m\xE1s.",
- "Gracias"],
- "es-ES": ["\xA1Mira! \xA1Hay algo nuevo!",
- "Con la nueva funcionalidad de traducci\xF3n integrada, ahora la Web es a\xFAn m\xE1s accesible. \xA1Pulsa el bot\xF3n Traducir y pru\xE9bala!",
- "M\xE1s informaci\xF3n.",
- "Gracias"],
- pl: ["Sp\xF3jrz tutaj! To co\u015B nowego!",
- "Sie\u0107 sta\u0142a si\u0119 w\u0142a\u015Bnie jeszcze bardziej dost\u0119pna dzi\u0119ki opcji bezpo\u015Bredniego t\u0142umaczenia stron. Kliknij przycisk t\u0142umaczenia, aby spr\xF3bowa\u0107!",
- "Dowiedz si\u0119 wi\u0119cej",
- "Dzi\u0119kuj\u0119"],
- tr: ["Bak\u0131n, burada yeni bir \u015Fey var!",
- "Yeni sayfa i\xE7i \xE7eviri \xF6zelli\u011Fimiz sayesinde Web art\u0131k \xE7ok daha anla\u015F\u0131l\u0131r olacak. Denemek i\xE7in \xC7evir d\xFC\u011Fmesine t\u0131klay\u0131n!",
- "Daha fazla bilgi al\u0131n.",
- "Te\u015Fekk\xFCrler"],
- vi: ["Nh\xECn n\xE0y! \u0110\u1ED3 m\u1EDBi!",
- "Gi\u1EDD \u0111\xE2y ch\xFAng ta c\xF3 th\u1EC3 ti\u1EBFp c\u1EADn web d\u1EC5 d\xE0ng h\u01A1n n\u1EEFa v\u1EDBi t\xEDnh n\u0103ng d\u1ECBch ngay trong trang. Hay nh\u1EA5n n\xFAt d\u1ECBch \u0111\u1EC3 th\u1EED!",
- "T\xECm hi\u1EC3u th\xEAm.",
- "C\u1EA3m \u01A1n"]
- };
-
- let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
- .getService(Ci.nsIXULChromeRegistry)
- .getSelectedLocale("browser");
- if (!(locale in localizedStrings))
- locale = "en";
- let strings = localizedStrings[locale];
-
- this._getAnonElt("welcomeHeadline").setAttribute("value", strings[0]);
- this._getAnonElt("welcomeBody").textContent = strings[1];
- this._getAnonElt("learnMore").setAttribute("value", strings[2]);
- this._getAnonElt("thanksButton").setAttribute("label", strings[3]);
-
- let panel = this._getAnonElt("welcomePanel");
- panel.openPopup(this._getAnonElt("messageImage"),
- "bottomcenter topleft");
-
- Services.prefs.setBoolPref(kWelcomePref, true);
- });
- ]]>
- </body>
- </method>
-
- <method name="_getAnonElt">
- <parameter name="aAnonId"/>
- <body>
- return document.getAnonymousElementByAttribute(this, "anonid", aAnonId);
- </body>
- </method>
-
- <method name="translate">
- <body>
- <![CDATA[
- if (this.state == Translation.STATE_OFFER) {
- this._getAnonElt("fromLanguage").value =
- this._getAnonElt("detectedLanguage").value;
- this._getAnonElt("toLanguage").value =
- Translation.defaultTargetLanguage;
- }
-
- this.translation.translate(this._getAnonElt("fromLanguage").value,
- this._getAnonElt("toLanguage").value);
- ]]>
- </body>
- </method>
-
- <!-- To be called when the infobar should be closed per user's wish (e.g.
- by clicking the notification's close button -->
- <method name="closeCommand">
- <body>
- <![CDATA[
- this.close();
- this.translation.infobarClosed();
- ]]>
- </body>
- </method>
- <method name="_handleButtonHiding">
- <body>
- <![CDATA[
- let originalShown = this.translation.originalShown;
- this._getAnonElt("showOriginal").hidden = originalShown;
- this._getAnonElt("showTranslation").hidden = !originalShown;
- ]]>
- </body>
- </method>
-
- <method name="showOriginal">
- <body>
- <![CDATA[
- this.translation.showOriginalContent();
- this._handleButtonHiding();
- ]]>
- </body>
- </method>
-
- <method name="showTranslation">
- <body>
- <![CDATA[
- this.translation.showTranslatedContent();
- this._handleButtonHiding();
- ]]>
- </body>
- </method>
-
- <method name="optionsShowing">
- <body>
- <![CDATA[
- // Get the source language name.
- let lang;
- if (this.state == Translation.STATE_OFFER)
- lang = this._getAnonElt("detectedLanguage").value;
- else {
- lang = this._getAnonElt("fromLanguage").value;
-
- // If we have never attempted to translate the page before the
- // service became unavailable, "fromLanguage" isn't set.
- if (!lang && this.state == Translation.STATE_UNAVAILABLE)
- lang = this.translation.detectedLanguage;
- }
-
- let langBundle =
- Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService)
- .createBundle("chrome://global/locale/languageNames.properties");
- let langName = langBundle.GetStringFromName(lang);
-
- // Set the label and accesskey on the menuitem.
- let bundle =
- Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService)
- .createBundle("chrome://browser/locale/translation.properties");
- let item = this._getAnonElt("neverForLanguage");
- const kStrId = "translation.options.neverForLanguage";
- item.setAttribute("label",
- bundle.formatStringFromName(kStrId + ".label",
- [langName], 1));
- item.setAttribute("accesskey",
- bundle.GetStringFromName(kStrId + ".accesskey"));
- item.langCode = lang;
-
- // We may need to disable the menuitems if they have already been used.
- // Check if translation is already disabled for this language:
- let neverForLangs =
- Services.prefs.getCharPref("browser.translation.neverForLanguages");
- item.disabled = neverForLangs.split(",").indexOf(lang) != -1;
-
- // Check if translation is disabled for the domain:
- let uri = this.translation.browser.currentURI;
- let perms = Services.perms;
- item = this._getAnonElt("neverForSite");
- item.disabled =
- perms.testExactPermission(uri, "translate") == perms.DENY_ACTION;
- ]]>
- </body>
- </method>
-
- <method name="neverForLanguage">
- <body>
- <![CDATA[
- const kPrefName = "browser.translation.neverForLanguages";
-
- let val = Services.prefs.getCharPref(kPrefName);
- if (val)
- val += ",";
- val += this._getAnonElt("neverForLanguage").langCode;
-
- Services.prefs.setCharPref(kPrefName, val);
-
- this.closeCommand();
- ]]>
- </body>
- </method>
-
- <method name="neverForSite">
- <body>
- <![CDATA[
- let uri = this.translation.browser.currentURI;
- let perms = Services.perms;
- perms.add(uri, "translate", perms.DENY_ACTION);
-
- this.closeCommand();
- ]]>
- </body>
- </method>
-
- <method name="openProviderAttribution">
- <body>
- <![CDATA[
- Translation.openProviderAttribution();
- ]]>
- </body>
- </method>
-
- </implementation>
- </binding>
-</bindings>
diff --git a/application/basilisk/installer/package-manifest.in b/application/basilisk/installer/package-manifest.in
index c446d3687..35060ea5e 100644
--- a/application/basilisk/installer/package-manifest.in
+++ b/application/basilisk/installer/package-manifest.in
@@ -35,7 +35,9 @@
#ifdef XP_MACOSX
; Mac bundle stuff
@APPNAME@/Contents/Info.plist
+#ifdef MOZ_UPDATER
@APPNAME@/Contents/Library/LaunchServices
+#endif
@APPNAME@/Contents/PkgInfo
@RESPATH@/firefox.icns
@RESPATH@/document.icns
@@ -114,7 +116,7 @@
@BINPATH@/browser/VisualElements/VisualElements_150.png
@BINPATH@/browser/VisualElements/VisualElements_70.png
#else
-@BINPATH@/@MOZ_APP_NAME@-bin
+@RESPATH@/@MOZ_APP_NAME@-bin
@BINPATH@/@MOZ_APP_NAME@
#endif
@RESPATH@/application.ini
diff --git a/application/basilisk/locales/en-US/chrome/browser/browser.dtd b/application/basilisk/locales/en-US/chrome/browser/browser.dtd
index f75aa46a7..09da91dee 100644
--- a/application/basilisk/locales/en-US/chrome/browser/browser.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/browser.dtd
@@ -207,8 +207,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY urlbar.webRTCShareScreenNotificationAnchor.tooltip "Manage sharing your windows or screen with the site">
<!ENTITY urlbar.servicesNotificationAnchor.tooltip "Open install message panel">
-<!ENTITY urlbar.translateNotificationAnchor.tooltip "Translate this page">
-<!ENTITY urlbar.translatedNotificationAnchor.tooltip "Manage page translation">
<!ENTITY urlbar.emeNotificationAnchor.tooltip "Manage use of DRM software">
<!ENTITY urlbar.cameraBlocked.tooltip "You have blocked your camera for this website.">
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/content.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/content.dtd
index 5d58ffa37..d1d83b3bc 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/content.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/content.dtd
@@ -38,21 +38,6 @@
<!ENTITY chooseButton.label "Choose…">
<!ENTITY chooseButton.accesskey "o">
-<!ENTITY translateWebPages.label "Translate web content">
-<!ENTITY translateWebPages.accesskey "T">
-<!ENTITY translateExceptions.label "Exceptions…">
-<!ENTITY translateExceptions.accesskey "x">
-
-<!-- LOCALIZATION NOTE (translation.options.attribution.beforeLogo,
- - translation.options.attribution.afterLogo):
- - These 2 strings are displayed before and after a 'Microsoft Translator'
- - logo.
- - The translations for these strings should match the translations in
- - browser/translation.dtd
- -->
-<!ENTITY translation.options.attribution.beforeLogo "Translations by">
-<!ENTITY translation.options.attribution.afterLogo "">
-
<!ENTITY drmContent.label "DRM content">
<!ENTITY playDRMContent.label "Play DRM content">
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/translation.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/translation.dtd
deleted file mode 100644
index fc5fb2b7b..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/translation.dtd
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- 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/. -->
-
-<!ENTITY window.title "Exceptions - Translation">
-<!ENTITY window.width "36em">
-<!ENTITY windowClose.key "w">
-
-<!ENTITY noTranslationForLanguages.label "Translation will not be offered for the following languages:">
-<!ENTITY treehead.languageName.label "Languages">
-<!ENTITY removeLanguage.label "Remove Language">
-<!ENTITY removeLanguage.accesskey "R">
-<!ENTITY removeAllLanguages.label "Remove All Languages">
-<!ENTITY removeAllLanguages.accesskey "e">
-
-<!ENTITY noTranslationForSites.label "Translation will not be offered for the following sites:">
-<!ENTITY treehead.siteName.label "Sites">
-<!ENTITY removeSite.label "Remove Site">
-<!ENTITY removeSite.accesskey "S">
-<!ENTITY removeAllSites.label "Remove All Sites">
-<!ENTITY removeAllSites.accesskey "i">
-
-<!ENTITY button.close.label "Close">
-<!ENTITY button.close.accesskey "C">
diff --git a/application/basilisk/locales/en-US/chrome/browser/translation.dtd b/application/basilisk/locales/en-US/chrome/browser/translation.dtd
deleted file mode 100644
index ca8bb9d51..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/translation.dtd
+++ /dev/null
@@ -1,75 +0,0 @@
-<!-- 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/. -->
-
-<!-- LOCALIZATION NOTE (translation.thisPageIsIn.label,
- - translation.translateThisPage.label):
- - These 2 strings are used to construct a sentence that contains a dropdown
- - showing the detected language of the current web page.
- - In en-US it looks like this:
- - This page is in [detected language] Translate this page?
- - "detected language" here is a language name coming from the
- - global/languageNames.properties file; for some locales it may not be in
- - the correct grammar case to keep the same structure of the original
- - sentence. -->
-<!ENTITY translation.thisPageIsIn.label "This page is in">
-<!ENTITY translation.translateThisPage.label "Translate this page?">
-<!ENTITY translation.translate.button "Translate">
-<!ENTITY translation.notNow.button "Not Now">
-
-<!ENTITY translation.translatingContent.label "Translating page content…">
-
-<!-- LOCALIZATION NOTE (translation.translatedFrom.label,
- - translation.translatedTo.label,
- - translation.translatedToSuffix.label):
- - These 3 strings are used to construct a sentence that contains 2 dropdowns
- - showing the source and target language of a translated web page.
- - In en-US it looks like this:
- - This page has been translated from [from language] to [to language]
- - "from language" and "to language" here are language names coming from the
- - global/languageNames.properties file; for some locales they may not be in
- - the correct grammar case to keep the same structure of the original
- - sentence.
- -
- - translation.translatedToSuffix.label (empty in en-US) is for locales that
- - need to display some text after the second drop down for the sentence to
- - be grammatically correct. -->
-<!ENTITY translation.translatedFrom.label "This page has been translated from">
-<!ENTITY translation.translatedTo.label "to">
-<!ENTITY translation.translatedToSuffix.label "">
-
-<!ENTITY translation.showOriginal.button "Show Original">
-<!ENTITY translation.showTranslation.button "Show Translation">
-
-<!ENTITY translation.errorTranslating.label "There has been an error translating this page.">
-<!ENTITY translation.tryAgain.button "Try Again">
-
-<!ENTITY translation.serviceUnavailable.label "Translation is not available at the moment. Please try again later.">
-
-<!ENTITY translation.options.menu "Options">
-<!-- LOCALIZATION NOTE (translation.options.neverForSite.accesskey,
- - translation.options.preferences.accesskey):
- - The accesskey values used here should not clash with the value used for
- - translation.options.neverForLanguage.accesskey in translation.properties
- -->
-<!ENTITY translation.options.neverForSite.label "Never translate this site">
-<!ENTITY translation.options.neverForSite.accesskey "e">
-<!ENTITY translation.options.preferences.label "Translation preferences">
-<!ENTITY translation.options.preferences.accesskey "T">
-
-<!-- LOCALIZATION NOTE (translation.options.attribution.beforeLogo,
- - translation.options.attribution.afterLogo):
- - These 2 strings are displayed before and after a 'Microsoft Translator'
- - logo.
- -->
-<!ENTITY translation.options.attribution.beforeLogo "Translations by">
-<!ENTITY translation.options.attribution.afterLogo "">
-
-<!-- LOCALIZATION NOTE (translation.options.attribution.poweredByYandex,
- translation.options.attribution.beforeLogo,
- - translation.options.attribution.afterLogo):
- - translation.options.attribution.poweredByYandex is displayed instead of
- - the other two strings when yandex translation engine is preferred by the
- - user.
- -->
-<!ENTITY translation.options.attribution.yandexTranslate "Powered by Yandex.Translate">
diff --git a/application/basilisk/locales/en-US/chrome/browser/translation.properties b/application/basilisk/locales/en-US/chrome/browser/translation.properties
deleted file mode 100644
index e62edbd0a..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/translation.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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/.
-
-# LOCALIZATION NOTE (translation.options.neverForLanguage.label):
-# %S is a language name coming from the global/languageNames.properties file.
-translation.options.neverForLanguage.label=Never translate %S
-
-# LOCALIZATION NOTE (translation.options.neverForLanguage.accesskey):
-# The accesskey value used here should not clash with the values used for
-# translation.options.*.accesskey in translation.dtd
-translation.options.neverForLanguage.accesskey=N
diff --git a/application/basilisk/locales/jar.mn b/application/basilisk/locales/jar.mn
index 9a847c7ed..5c5a72a1f 100644
--- a/application/basilisk/locales/jar.mn
+++ b/application/basilisk/locales/jar.mn
@@ -42,8 +42,6 @@
locale/browser/shellservice.properties (%chrome/browser/shellservice.properties)
locale/browser/tabbrowser.properties (%chrome/browser/tabbrowser.properties)
locale/browser/taskbar.properties (%chrome/browser/taskbar.properties)
- locale/browser/translation.dtd (%chrome/browser/translation.dtd)
- locale/browser/translation.properties (%chrome/browser/translation.properties)
locale/browser/webrtcIndicator.properties (%chrome/browser/webrtcIndicator.properties)
locale/browser/downloads/downloads.dtd (%chrome/browser/downloads/downloads.dtd)
locale/browser/downloads/downloads.properties (%chrome/browser/downloads/downloads.properties)
@@ -88,7 +86,6 @@
locale/browser/preferences/sync.dtd (%chrome/browser/preferences/sync.dtd)
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
locale/browser/preferences/search.dtd (%chrome/browser/preferences/search.dtd)
- locale/browser/preferences/translation.dtd (%chrome/browser/preferences/translation.dtd)
locale/browser/syncBrand.dtd (%chrome/browser/syncBrand.dtd)
locale/browser/syncSetup.dtd (%chrome/browser/syncSetup.dtd)
locale/browser/syncSetup.properties (%chrome/browser/syncSetup.properties)
diff --git a/application/basilisk/themes/linux/browser.css b/application/basilisk/themes/linux/browser.css
index f9bd0bbd0..fbc5b651b 100644
--- a/application/basilisk/themes/linux/browser.css
+++ b/application/basilisk/themes/linux/browser.css
@@ -840,80 +840,6 @@ menuitem.bookmark-item {
outline: 1px dotted -moz-DialogText;
}
-/* Translation infobar */
-
-%include ../shared/translation/infobar.inc.css
-
-notification[value="translation"] {
- min-height: 40px;
-}
-
-notification[value="translation"],
-notification[value="translation"] button,
-notification[value="translation"] menulist {
- min-height: 30px;
- color: #5A5959;
-}
-
-notification[value="translation"] {
- background-color: #F2F1F0;
-}
-
-notification[value="translation"] button,
-notification[value="translation"] menulist {
- padding-inline-end: 1ch;
-}
-
-notification[value="translation"] menulist {
- border: 1px solid #C1C1C1;
- background-color: #FFF;
-}
-
-notification[value="translation"] button {
- border: 1px solid #C1C1C1;
- background-color: #F2F1F0;
-}
-
-notification[value="translation"] button,
-notification[value="translation"] menulist,
-notification[value="translation"] menulist > .menulist-label-box {
- margin-inline-start: 1ch;
- margin-inline-end: 1ch;
-}
-
-notification[value="translation"] button:hover,
-notification[value="translation"] button:active,
-notification[value="translation"] menulist:hover,
-notification[value="translation"] menulist:active {
- background-color: #E2E1E0;
-}
-
-notification[value="translation"] button[anonid="translate"] {
- color: #FFF;
- background-image: linear-gradient(#9FB938, #8DA726);
- box-shadow: none;
- border: 1px solid #829C1C;
-}
-
-notification[value="translation"] button[anonid="translate"]:hover,
-notification[value="translation"] button[anonid="translate"]:active {
- background-image: linear-gradient(#8DA726, #8DA726);
-}
-
-notification[value="translation"] button > .button-box,
-notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker {
- padding: 0;
- margin-inline-start: 3ch;
-}
-
-notification[value="translation"] button:not([type="menu"]) > .button-box {
- margin-inline-end: 3ch;
-}
-
-notification[value="translation"] menulist > .menulist-dropmarker {
- display: block;
-}
-
/* AutoComplete */
%include ../shared/autocomplete.inc.css
diff --git a/application/basilisk/themes/linux/preferences/preferences.css b/application/basilisk/themes/linux/preferences/preferences.css
index 45e2dc23d..5c1b102fa 100644
--- a/application/basilisk/themes/linux/preferences/preferences.css
+++ b/application/basilisk/themes/linux/preferences/preferences.css
@@ -20,12 +20,6 @@
font-weight: bold;
}
-/* Content Pane */
-#translationAttributionImage {
- width: 70px;
- cursor: pointer;
-}
-
/* Modeless Window Dialogs */
.windowDialog,
.windowDialog prefpane {
diff --git a/application/basilisk/themes/osx/browser.css b/application/basilisk/themes/osx/browser.css
index 808bb20b1..70f1f6162 100644
--- a/application/basilisk/themes/osx/browser.css
+++ b/application/basilisk/themes/osx/browser.css
@@ -2920,139 +2920,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
0 0 3px 2px -moz-mac-focusring;
}
-/* Translation */
-
-%include ../shared/translation/infobar.inc.css
-
-notification[value="translation"] {
- color: #484848;
- background-color: #EFEFEF;
- background-image: none;
- border-top: none;
- border-bottom: 1px solid #c4c4c4;
- padding-top: 1px;
- padding-bottom: 1px;
- min-height: 35px;
-}
-
-.translate-infobar-element {
- margin-top: 0 !important;
- margin-bottom: 0 !important;
-}
-
-button.translate-infobar-element {
- background: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.1)) repeat scroll 0% 0% padding-box transparent;
- color: #333333;
- border: 1px solid;
- border-color: rgba(23, 51, 78, 0.15) rgba(23, 51, 78, 0.17) rgba(23, 51, 78, 0.2);
- box-shadow: 0px 0px 2px rgba(255, 255, 255, 0.5) inset, 0px 1px 0px rgba(255, 255, 255, 0.2);
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- min-height: 22px;
- min-width: 0;
- padding: 0 0.8em !important;
- margin-left: 0.25em;
- margin-right: 0.25em;
-}
-
-button.translate-infobar-element .button-text {
- margin-left: 0 !important;
- margin-right: 0 !important;
-}
-
-label.translate-infobar-element {
- padding-top: 2px;
-}
-
-button.translate-infobar-element:hover {
- background: #f0f0f0;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.1) inset, 0 0 0 1px hsla(0,0%,100%,.05) inset, 0 1px 0 hsla(210,54%,20%,.01), 0 0 4px hsla(206,100%,20%,.1);
-}
-
-button.translate-infobar-element:active {
- box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset, 0 0 1px hsla(211,79%,6%,.2) inset;
- transition-duration: 0ms;
-}
-
-button.translate-infobar-element[anonid="translate"] {
- color: #ffffff;
- background: linear-gradient(#4cb1ff, #1793e5);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset, 0 0 0 1px hsla(0,0%,100%,.1) inset, 0 1px 0 hsla(210,54%,20%,.03);
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
- padding: 0 1.1em !important;;
-}
-
-button.translate-infobar-element[anonid="translate"]:hover {
- background-image: linear-gradient(#66bdff, #0d9eff);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset, 0 0 0 1px hsla(0,0%,100%,.1) inset, 0 1px 0 hsla(210,54%,20%,.03), 0 0 4px hsla(206,100%,20%,.2);
-}
-
-button.translate-infobar-element.options-menu-button {
- padding-inline-start: 0.5em !important;
- padding-inline-end: 0em !important;
-}
-
-button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker {
- display: -moz-box;
- list-style-image: url("chrome://global/skin/icons/glyph-dropdown.png");
- padding: 0 !important;
- margin: 0 !important;
-}
-
-@media (min-resolution: 2dppx) {
- button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker {
- list-style-image: url("chrome://global/skin/icons/glyph-dropdown@2x.png");
- }
-
- button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker > .dropmarker-icon {
- width: 8px;
- }
-}
-
-menulist.translate-infobar-element {
- text-shadow: 0 1px 1px #FEFFFE;
- border: 1px solid;
- border-color: rgba(23, 51, 78, 0.15) rgba(23, 51, 78, 0.17) rgba(23, 51, 78, 0.2);
- box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 #FFFFFF;
- background-color: #F1F1F1;
- background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.1));
- color: #333333;
- padding: 0;
- min-height: 22px !important;
-}
-
-menulist.translate-infobar-element > .menulist-label-box {
- padding-top: 1px;
- padding-inline-start: 0.3em;
- margin-top: 0;
- margin-bottom: 0;
-}
-
-menulist.translate-infobar-element:hover {
- background: #f0f0f0;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.1) inset, 0 0 0 1px hsla(0,0%,100%,.05) inset, 0 1px 0 hsla(210,54%,20%,.01), 0 0 4px hsla(206,100%,20%,.1);
-}
-
-menulist.translate-infobar-element[open="true"] {
- background-image: linear-gradient(rgba(255,255,255,0.1),
- rgba(255,255,255,0.6));
-}
-
-menulist.translate-infobar-element > .menulist-dropmarker {
- display: -moz-box;
- list-style-image: url("chrome://global/skin/icons/glyph-dropdown.png");
-}
-
-@media (min-resolution: 2dppx) {
- menulist.translate-infobar-element > .menulist-dropmarker {
- list-style-image: url("chrome://global/skin/icons/glyph-dropdown@2x.png");
- }
-
- menulist.translate-infobar-element > .menulist-dropmarker > .dropmarker-icon {
- width: 8px;
- }
-}
-
.popup-notification-body[popupid="addon-progress"],
.popup-notification-body[popupid="addon-install-confirmation"] {
width: 28em;
diff --git a/application/basilisk/themes/osx/preferences/preferences.css b/application/basilisk/themes/osx/preferences/preferences.css
index 4f17ec58d..a8dcadc55 100644
--- a/application/basilisk/themes/osx/preferences/preferences.css
+++ b/application/basilisk/themes/osx/preferences/preferences.css
@@ -49,11 +49,6 @@ caption {
border-bottom: 1px solid #ccc;
}
-#translationAttributionImage {
- width: 70px;
- cursor: pointer;
-}
-
#browserUseCurrent,
#browserUseBookmark,
#browserUseBlank {
diff --git a/application/basilisk/themes/shared/jar.inc.mn b/application/basilisk/themes/shared/jar.inc.mn
index 588cf5364..361edd311 100644
--- a/application/basilisk/themes/shared/jar.inc.mn
+++ b/application/basilisk/themes/shared/jar.inc.mn
@@ -108,10 +108,6 @@
skin/classic/browser/theme-switcher-icon.png (../shared/theme-switcher-icon.png)
skin/classic/browser/theme-switcher-icon@2x.png (../shared/theme-switcher-icon@2x.png)
skin/classic/browser/toolbarbutton-dropdown-arrow.png (../shared/toolbarbutton-dropdown-arrow.png)
- skin/classic/browser/translating-16.png (../shared/translation/translating-16.png)
- skin/classic/browser/translating-16@2x.png (../shared/translation/translating-16@2x.png)
- skin/classic/browser/translation-16.png (../shared/translation/translation-16.png)
- skin/classic/browser/translation-16@2x.png (../shared/translation/translation-16@2x.png)
skin/classic/browser/undoCloseTab.png (../shared/undoCloseTab.png)
skin/classic/browser/undoCloseTab@2x.png (../shared/undoCloseTab@2x.png)
skin/classic/browser/update-badge.svg (../shared/update-badge.svg)
diff --git a/application/basilisk/themes/shared/notification-icons.inc.css b/application/basilisk/themes/shared/notification-icons.inc.css
index f641e72c1..99451ba98 100644
--- a/application/basilisk/themes/shared/notification-icons.inc.css
+++ b/application/basilisk/themes/shared/notification-icons.inc.css
@@ -266,27 +266,3 @@ html|*#webRTC-previewVideo {
opacity: 1;
}
}
-
-/* TRANSLATION */
-
-.translation-icon {
- list-style-image: url(chrome://browser/skin/translation-16.png);
- -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-
-.translation-icon.in-use {
- -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-
-%ifdef XP_MACOSX
-@media (min-resolution: 1.1dppx) {
- .translation-icon {
- list-style-image: url(chrome://browser/skin/translation-16@2x.png);
- -moz-image-region: rect(0px, 32px, 32px, 0px);
- }
-
- .translation-icon.in-use {
- -moz-image-region: rect(0px, 64px, 32px, 32px);
- }
-}
-%endif
diff --git a/application/basilisk/themes/shared/translation/infobar.inc.css b/application/basilisk/themes/shared/translation/infobar.inc.css
deleted file mode 100644
index 50d1acc01..000000000
--- a/application/basilisk/themes/shared/translation/infobar.inc.css
+++ /dev/null
@@ -1,95 +0,0 @@
-%if 0
-/* 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/. */
-%endif
-notification[value="translation"] .messageImage {
- list-style-image: url(chrome://browser/skin/translation-16.png);
- -moz-image-region: rect(0, 32px, 16px, 16px);
-}
-
-@media (min-resolution: 1.25dppx) {
- notification[value="translation"] .messageImage {
- list-style-image: url(chrome://browser/skin/translation-16@2x.png);
- -moz-image-region: rect(0, 64px, 32px, 32px);
- }
-}
-
-notification[value="translation"][state="translating"] .messageImage {
- list-style-image: url(chrome://browser/skin/translating-16.png);
- -moz-image-region: auto;
-}
-
-@media (min-resolution: 1.25dppx) {
- notification[value="translation"][state="translating"] .messageImage {
- list-style-image: url(chrome://browser/skin/translating-16@2x.png);
- }
-}
-
-notification[value="translation"] hbox[anonid="details"] {
- overflow: hidden;
-}
-
-notification[value="translation"] button,
-notification[value="translation"] menulist {
- -moz-appearance: none;
- border-width: 1px;
- -moz-border-top-colors: none;
- -moz-border-right-colors: none;
- -moz-border-bottom-colors: none;
- -moz-border-left-colors: none;
- border-radius: 2px;
- min-width: 0;
- box-shadow: 0 1px rgba(255, 255, 255, 0.5), 0 1px rgba(255, 255, 255, 0.5) inset;
-}
-
-notification[value="translation"] menulist > .menulist-dropmarker {
- -moz-appearance: toolbarbutton-dropdown;
- border: none;
- background-color: transparent;
- margin: auto;
- padding: 5px 0;
-}
-
-.translation-menupopup arrowscrollbox {
- padding-bottom: 0;
-}
-
-.translation-attribution {
- cursor: pointer;
- -moz-box-align: end;
- font-size: small;
-}
-
-.translation-attribution > label {
- margin-bottom: 0;
-}
-
-.translation-attribution > image {
- width: 70px;
-}
-
-.translation-welcome-panel {
- width: 305px;
-}
-
-.translation-welcome-logo {
- height: 32px;
- width: 32px;
- list-style-image: url(chrome://browser/skin/translation-16@2x.png);
- -moz-image-region: rect(0, 64px, 32px, 32px);
-}
-
-.translation-welcome-content {
- margin-inline-start: 16px;
-}
-
-.translation-welcome-headline {
- font-size: larger;
- font-weight: bold;
-}
-
-.translation-welcome-body {
- padding: 1em 0;
- margin: 0 0;
-}
diff --git a/application/basilisk/themes/shared/translation/translating-16.png b/application/basilisk/themes/shared/translation/translating-16.png
deleted file mode 100644
index 71ca37c22..000000000
--- a/application/basilisk/themes/shared/translation/translating-16.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/themes/shared/translation/translating-16@2x.png b/application/basilisk/themes/shared/translation/translating-16@2x.png
deleted file mode 100644
index ab6184047..000000000
--- a/application/basilisk/themes/shared/translation/translating-16@2x.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/themes/shared/translation/translation-16.png b/application/basilisk/themes/shared/translation/translation-16.png
deleted file mode 100644
index 4b42dedcf..000000000
--- a/application/basilisk/themes/shared/translation/translation-16.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/themes/shared/translation/translation-16@2x.png b/application/basilisk/themes/shared/translation/translation-16@2x.png
deleted file mode 100644
index 2105a3e4a..000000000
--- a/application/basilisk/themes/shared/translation/translation-16@2x.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/themes/windows/browser.css b/application/basilisk/themes/windows/browser.css
index 2ed3e7e6a..334265e60 100644
--- a/application/basilisk/themes/windows/browser.css
+++ b/application/basilisk/themes/windows/browser.css
@@ -2113,87 +2113,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
outline: 1px dotted -moz-DialogText;
}
-/* Translation infobar */
-
-%include ../shared/translation/infobar.inc.css
-
-notification[value="translation"] {
- min-height: 40px;
-}
-
-@media (-moz-windows-default-theme) {
- notification[value="translation"],
- notification[value="translation"] button,
- notification[value="translation"] menulist {
- min-height: 30px;
- color: #545454;
- }
-
- notification[value="translation"] {
- background-color: #EEE;
- }
-
- notification[value="translation"] button,
- notification[value="translation"] menulist {
- padding-inline-end: 1ch;
- }
-
- notification[value="translation"] menulist {
- border: 1px solid #C1C1C1;
- background-color: #FFF;
- }
-
- notification[value="translation"] button {
- border: 1px solid #C1C1C1;
- background-color: #FBFBFB;
- }
-
- notification[value="translation"] button,
- notification[value="translation"] menulist,
- notification[value="translation"] menulist > .menulist-label-box {
- margin-inline-start: 1ch;
- margin-inline-end: 1ch;
- }
-
- notification[value="translation"] button:hover,
- notification[value="translation"] button:active,
- notification[value="translation"] menulist:hover,
- notification[value="translation"] menulist:active {
- background-color: #EBEBEB;
- }
-
- notification[value="translation"] button[anonid="translate"] {
- color: #FFF;
- background-color: #0095DD;
- box-shadow: none;
- border: 1px solid #006B9D;
- }
-
- notification[value="translation"] button[anonid="translate"]:hover,
- notification[value="translation"] button[anonid="translate"]:active {
- background-color: #008ACB;
- }
-
- notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker,
- notification[value="translation"] menulist > .menulist-dropmarker {
- list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png");
- }
-
- notification[value="translation"] button > .button-box,
- notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker {
- padding: 0;
- margin-inline-start: 3ch;
- }
-
- notification[value="translation"] button:not([type="menu"]) > .button-box {
- margin-inline-end: 3ch;
- }
-}
-
-.translation-menupopup {
- -moz-appearance: none;
-}
-
/* Bookmarks roots menu-items */
#subscribeToPageMenuitem:not([disabled]),
#subscribeToPageMenupopup {
diff --git a/application/basilisk/themes/windows/preferences/preferences.css b/application/basilisk/themes/windows/preferences/preferences.css
index bd1ec3083..c6c063b53 100644
--- a/application/basilisk/themes/windows/preferences/preferences.css
+++ b/application/basilisk/themes/windows/preferences/preferences.css
@@ -15,13 +15,6 @@
#isNotDefaultLabel {
font-weight: bold;
}
-
-/* Content Pane */
-#translationAttributionImage {
- width: 70px;
- cursor: pointer;
-}
-
/* Modeless Window Dialogs */
.windowDialog,
.windowDialog prefpane {
diff --git a/application/palemoon/base/content/newtab/newTab.css b/application/palemoon/base/content/newtab/newTab.css
index fe745d2fd..3c7cfa102 100644
--- a/application/palemoon/base/content/newtab/newTab.css
+++ b/application/palemoon/base/content/newtab/newTab.css
@@ -301,7 +301,6 @@ input[type=button] {
color: black;
border-color: hsla(220,54%,20%,.15) hsla(220,54%,20%,.17) hsla(220,54%,20%,.2);
border-radius: 0 2px 2px 0;
- border-inline-start: 1px solid transparent;
box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
0 1px 0 hsla(0,0%,100%,.2);
cursor: pointer;
diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml
index 19e1d4659..dc6cb0a9d 100644
--- a/application/palemoon/base/content/tabbrowser.xml
+++ b/application/palemoon/base/content/tabbrowser.xml
@@ -2950,19 +2950,6 @@
onget="return this.mCurrentBrowser.docShell"
readonly="true"/>
- <property name="messageManager"
- readonly="true">
- <getter>
- <![CDATA[
- let frameLoader = this.mCurrentBrowser.frameLoader;
- if (!frameLoader) {
- return null;
- }
- return frameLoader.messageManager;
- ]]>
- </getter>
- </property>
-
<property name="webNavigation"
onget="return this.mCurrentBrowser.webNavigation"
readonly="true"/>
diff --git a/js/src/jit-test/tests/ion/bug1493900-1.js b/js/src/jit-test/tests/ion/bug1493900-1.js
new file mode 100644
index 000000000..643c1943d
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-1.js
@@ -0,0 +1,17 @@
+function f() {
+ var objs = [];
+ for (var i = 0; i < 100; i++) {
+ objs[i] = {};
+ }
+ var o = objs[0];
+ var a = new Float64Array(1024);
+ function g(a, b) {
+ let p = b;
+ for (; p.x < 0; p = p.x) {
+ while (p === p) {}
+ }
+ for (var i = 0; i < 10000; ++i) {}
+ }
+ g(a, o);
+}
+f();
diff --git a/js/src/jit-test/tests/ion/bug1493900-2.js b/js/src/jit-test/tests/ion/bug1493900-2.js
new file mode 100644
index 000000000..7e7f5fdec
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-2.js
@@ -0,0 +1,7 @@
+function f(a, b) {
+ for (; b.x < 0; b = b.x) {
+ while (b === b) {};
+ }
+ for (var i = 0; i < 99999; ++i) {}
+}
+f(0, 0);
diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp
index 741ed1592..645aefc4f 100644
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -1736,6 +1736,18 @@ BacktrackingAllocator::deadRange(LiveRange* range)
}
bool
+BacktrackingAllocator::moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type)
+{
+ if (successor->mir()->numPredecessors() > 1) {
+ MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
+ return moveAtExit(predecessor, from, to, type);
+ }
+
+ return moveAtEntry(successor, from, to, type);
+}
+
+bool
BacktrackingAllocator::resolveControlFlow()
{
// Add moves to handle changing assignments for vregs over their lifetime.
@@ -1846,15 +1858,11 @@ BacktrackingAllocator::resolveControlFlow()
if (!alloc().ensureBallast()) {
return false;
}
- if (mSuccessor->numPredecessors() > 1) {
- MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
- if (!moveAtExit(predecessor, from, to, def->type())) {
- return false;
- }
- } else {
- if (!moveAtEntry(successor, from, to, def->type())) {
- return false;
- }
+
+ // Note: we have to use moveAtEdge both here and below (for edge
+ // resolution) to avoid conflicting moves. See bug 1493900.
+ if (!moveAtEdge(predecessor, successor, from, to, def->type())) {
+ return false;
}
}
}
@@ -1884,16 +1892,12 @@ BacktrackingAllocator::resolveControlFlow()
if (targetRange->covers(exitOf(predecessor)))
continue;
- if (!alloc().ensureBallast())
+ if (!alloc().ensureBallast()) {
return false;
+ }
LiveRange* from = reg.rangeFor(exitOf(predecessor), true);
- if (successor->mir()->numPredecessors() > 1) {
- MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
- if (!moveAtExit(predecessor, from, targetRange, reg.type()))
- return false;
- } else {
- if (!moveAtEntry(successor, from, targetRange, reg.type()))
- return false;
+ if (!moveAtEdge(predecessor, successor, from, targetRange, reg.type())) {
+ return false;
}
}
}
diff --git a/js/src/jit/BacktrackingAllocator.h b/js/src/jit/BacktrackingAllocator.h
index 9910498fb..c6cf26695 100644
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -108,8 +108,9 @@ class Requirement
}
MOZ_ASSERT(newRequirement.kind() == Requirement::REGISTER);
- if (kind() == Requirement::FIXED)
+ if (kind() == Requirement::FIXED) {
return allocation().isRegister();
+ }
*this = newRequirement;
return true;
@@ -353,10 +354,12 @@ class LiveRange : public TempObject
// Comparator for use in range splay trees.
static int compare(LiveRange* v0, LiveRange* v1) {
// LiveRange includes 'from' but excludes 'to'.
- if (v0->to() <= v1->from())
+ if (v0->to() <= v1->from()) {
return -1;
- if (v0->from() >= v1->to())
+ }
+ if (v0->from() >= v1->to()) {
return 1;
+ }
return 0;
}
};
@@ -642,10 +645,12 @@ class BacktrackingAllocator : protected RegisterAllocator
// Comparator for use in splay tree.
static int compare(CallRange* v0, CallRange* v1) {
- if (v0->range.to <= v1->range.from)
+ if (v0->range.to <= v1->range.from) {
return -1;
- if (v0->range.from >= v1->range.to)
+ }
+ if (v0->range.from >= v1->range.to) {
return 1;
+ }
return 0;
}
};
@@ -744,36 +749,43 @@ class BacktrackingAllocator : protected RegisterAllocator
MOZ_MUST_USE bool moveInput(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getInputMoveGroup(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAfter(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getMoveGroupAfter(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtExit(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getExitMoveGroup(alloc());
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtEntry(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getEntryMoveGroup(alloc());
return addMove(moves, from, to, type);
}
+ MOZ_MUST_USE bool moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type);
+
// Debugging methods.
void dumpAllocations();
diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp
index 8f117b5ab..fbd61f783 100644
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -3714,8 +3714,11 @@ MeasuringReflow(nsIFrame* aChild,
parent->Properties().Set(
nsContainerFrame::DebugReflowingWithInfiniteISize(), true);
#endif
- uint32_t riFlags = ReflowInput::COMPUTE_SIZE_SHRINK_WRAP |
- ReflowInput::COMPUTE_SIZE_USE_AUTO_BSIZE;
+ auto wm = aChild->GetWritingMode();
+ uint32_t riFlags = ReflowInput::COMPUTE_SIZE_USE_AUTO_BSIZE;
+ if (aAvailableSize.ISize(wm) == INFINITE_ISIZE_COORD) {
+ riFlags |= ReflowInput::COMPUTE_SIZE_SHRINK_WRAP;
+ }
if (aIMinSizeClamp != NS_MAXSIZE) {
riFlags |= ReflowInput::I_CLAMP_MARGIN_BOX_MIN_SIZE;
}
@@ -3730,7 +3733,6 @@ MeasuringReflow(nsIFrame* aChild,
ReflowOutput childSize(childRI);
nsReflowStatus childStatus;
const uint32_t flags = NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW;
- WritingMode wm = childRI.GetWritingMode();
parent->ReflowChild(aChild, pc, childSize, childRI, wm,
LogicalPoint(wm), nsSize(), flags, childStatus);
parent->FinishReflowChild(aChild, pc, childSize, &childRI, wm,
diff --git a/layout/reftests/css-grid/bug1349571-ref.html b/layout/reftests/css-grid/bug1349571-ref.html
new file mode 100644
index 000000000..42efd731a
--- /dev/null
+++ b/layout/reftests/css-grid/bug1349571-ref.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Testcase for bug 1349571</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+.container {
+ display: grid;
+ grid: 250px / 500px;
+ border: 3px solid;
+ width: 500px;
+}
+
+.responsive-container {
+ background: lightgrey;
+}
+
+ </style>
+<script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head>
+<body>
+
+<div class="container">
+ <div class="responsive-container"></div>
+</div>
+
+
+
+</body></html> \ No newline at end of file
diff --git a/layout/reftests/css-grid/bug1349571.html b/layout/reftests/css-grid/bug1349571.html
new file mode 100644
index 000000000..f836fe36e
--- /dev/null
+++ b/layout/reftests/css-grid/bug1349571.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Testcase for bug 1349571</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+.container {
+ display: grid;
+ grid-template-columns: 1fr;
+ border: 3px solid;
+ width: 500px;
+}
+
+.responsive-container {
+ padding-bottom: 50%;
+ height: 0;
+ background: lightgrey;
+}
+
+ </style>
+<script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head>
+<body>
+
+<div class="container">
+ <div>
+ <div class="responsive-container"></div>
+ </div>
+</div>
+
+
+
+</body></html> \ No newline at end of file
diff --git a/layout/reftests/css-grid/bug1356820-ref.html b/layout/reftests/css-grid/bug1356820-ref.html
new file mode 100644
index 000000000..b203ba203
--- /dev/null
+++ b/layout/reftests/css-grid/bug1356820-ref.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head><body><div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; width: 5em; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="width: 5em; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; writing-mode:vertical-lr; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+</body></html> \ No newline at end of file
diff --git a/layout/reftests/css-grid/bug1356820.html b/layout/reftests/css-grid/bug1356820.html
new file mode 100644
index 000000000..2f2f36014
--- /dev/null
+++ b/layout/reftests/css-grid/bug1356820.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head><body><div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; min-width: 0;">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="min-width: 0;">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; min-height: 0; writing-mode:vertical-lr">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+</body></html> \ No newline at end of file
diff --git a/layout/reftests/css-grid/reftest.list b/layout/reftests/css-grid/reftest.list
index c2ee57c1a..3087ca49b 100644
--- a/layout/reftests/css-grid/reftest.list
+++ b/layout/reftests/css-grid/reftest.list
@@ -280,3 +280,5 @@ asserts(1-10) == grid-fragmentation-dyn4-021.html grid-fragmentation-021-ref.htm
== grid-fragmentation-dyn2-031.html grid-fragmentation-031-ref.html
== bug1306106.html bug1306106-ref.html
== grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html
+== bug1349571.html bug1349571-ref.html
+== bug1356820.html bug1356820-ref.html
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
index e13541acf..435294315 100644
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -789,7 +789,9 @@ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
// creating a new channel by calling NewChannel().
if (NS_FAILED(rv)) {
rv = handler->NewChannel(aURI, getter_AddRefs(channel));
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
// The protocol handler does not implement NewChannel2, so
// maybe we need to wrap the channel (see comment in MaybeWrap
// function).
diff --git a/netwerk/base/nsNetUtilInlines.h b/netwerk/base/nsNetUtilInlines.h
index 7003814d5..b831ec2e7 100644
--- a/netwerk/base/nsNetUtilInlines.h
+++ b/netwerk/base/nsNetUtilInlines.h
@@ -224,7 +224,9 @@ NS_NewChannelInternal(nsIChannel **outChannel,
aUri,
aLoadInfo,
getter_AddRefs(channel));
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
if (aLoadGroup) {
rv = channel->SetLoadGroup(aLoadGroup);
diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js
index 515828d29..bf1534c12 100644
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -284,12 +284,6 @@ user_pref("apz.content_response_timeout", 60000);
// Make sure SSL Error reports don't hit the network
user_pref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/ssl_error_reports.sjs?succeed");
-// Make sure Translation won't hit the network.
-user_pref("browser.translation.bing.authURL", "http://%(server)s/browser/browser/components/translation/test/bing.sjs");
-user_pref("browser.translation.bing.translateArrayURL", "http://%(server)s/browser/browser/components/translation/test/bing.sjs");
-user_pref("browser.translation.yandex.translateURLOverride", "http://%(server)s/browser/browser/components/translation/test/yandex.sjs");
-user_pref("browser.translation.engine", "bing");
-
// Make sure we don't try to load snippets from the network.
user_pref("browser.aboutHomeSnippets.updateUrl", "nonexistent://test");
diff --git a/toolkit/components/reader/AboutReader.jsm b/toolkit/components/reader/AboutReader.jsm
index c5d04476d..6ec959eba 100644
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -14,7 +14,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AsyncPrefs", "resource://gre/modules/AsyncPrefs.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NarrateControls", "resource://gre/modules/narrate/NarrateControls.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Rect", "resource://gre/modules/Geometry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
diff --git a/toolkit/components/reader/JSDOMParser.js b/toolkit/components/reader/JSDOMParser.js
index dd9d37230..debdb08eb 100644
--- a/toolkit/components/reader/JSDOMParser.js
+++ b/toolkit/components/reader/JSDOMParser.js
@@ -618,6 +618,13 @@
};
var Element = function (tag) {
+ // We use this to find the closing tag.
+ this._matchingTag = tag;
+ // We're explicitly a non-namespace aware parser, we just pretend it's all HTML.
+ var lastColonIndex = tag.lastIndexOf(":");
+ if (lastColonIndex != -1) {
+ tag = tag.substring(lastColonIndex + 1);
+ }
this.attributes = [];
this.childNodes = [];
this.children = [];
@@ -785,7 +792,13 @@
break;
}
}
- }
+ },
+
+ hasAttribute: function (name) {
+ return this.attributes.some(function (attr) {
+ return attr.name == name;
+ });
+ },
};
var Style = function (node) {
@@ -1062,9 +1075,10 @@
return null;
// Read any text as Text node
+ var textNode;
if (c !== "<") {
--this.currentChar;
- var textNode = new Text();
+ textNode = new Text();
var n = this.html.indexOf("<", this.currentChar);
if (n === -1) {
textNode.innerHTML = this.html.substring(this.currentChar, this.html.length);
@@ -1076,6 +1090,18 @@
return textNode;
}
+ if (this.match("![CDATA[")) {
+ var endChar = this.html.indexOf("]]>", this.currentChar);
+ if (endChar === -1) {
+ this.error("unclosed CDATA section");
+ return null;
+ }
+ textNode = new Text();
+ textNode.textContent = this.html.substring(this.currentChar, endChar);
+ this.currentChar = endChar + ("]]>").length;
+ return textNode;
+ }
+
c = this.peekNext();
// Read Comment node. Normally, Comment nodes know their inner
@@ -1107,7 +1133,7 @@
// If this isn't a void Element, read its child nodes
if (!closed) {
this.readChildren(node);
- var closingTag = "</" + localName + ">";
+ var closingTag = "</" + node._matchingTag + ">";
if (!this.match(closingTag)) {
this.error("expected '" + closingTag + "' and got " + this.html.substr(this.currentChar, closingTag.length));
return null;
diff --git a/toolkit/components/reader/Readability.js b/toolkit/components/reader/Readability.js
index 064d2ae88..c2bba0cd3 100644
--- a/toolkit/components/reader/Readability.js
+++ b/toolkit/components/reader/Readability.js
@@ -29,14 +29,19 @@
/**
* Public constructor.
- * @param {Object} uri The URI descriptor object.
* @param {HTMLDocument} doc The document to parse.
* @param {Object} options The options object.
*/
-function Readability(uri, doc, options) {
+function Readability(doc, options) {
+ // In some older versions, people passed a URI as the first argument. Cope:
+ if (options && options.documentElement) {
+ doc = options;
+ options = arguments[2];
+ } else if (!doc || !doc.documentElement) {
+ throw new Error("First argument to Readability constructor should be a document object.");
+ }
options = options || {};
- this._uri = uri;
this._doc = doc;
this._articleTitle = null;
this._articleByline = null;
@@ -47,7 +52,7 @@ function Readability(uri, doc, options) {
this._debug = !!options.debug;
this._maxElemsToParse = options.maxElemsToParse || this.DEFAULT_MAX_ELEMS_TO_PARSE;
this._nbTopCandidates = options.nbTopCandidates || this.DEFAULT_N_TOP_CANDIDATES;
- this._wordThreshold = options.wordThreshold || this.DEFAULT_WORD_THRESHOLD;
+ this._charThreshold = options.charThreshold || this.DEFAULT_CHAR_THRESHOLD;
this._classesToPreserve = this.CLASSES_TO_PRESERVE.concat(options.classesToPreserve || []);
// Start with all flags set
@@ -93,6 +98,10 @@ Readability.prototype = {
FLAG_WEIGHT_CLASSES: 0x2,
FLAG_CLEAN_CONDITIONALLY: 0x4,
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
+ ELEMENT_NODE: 1,
+ TEXT_NODE: 3,
+
// Max number of nodes supported by this parser. Default: 0 (no limit)
DEFAULT_MAX_ELEMS_TO_PARSE: 0,
@@ -103,13 +112,13 @@ Readability.prototype = {
// Element tags to score by default.
DEFAULT_TAGS_TO_SCORE: "section,h2,h3,h4,h5,h6,p,td,pre".toUpperCase().split(","),
- // The default number of words an article must have in order to return a result
- DEFAULT_WORD_THRESHOLD: 500,
+ // The default number of chars an article must have in order to return a result
+ DEFAULT_CHAR_THRESHOLD: 500,
// All of the regular expressions in use within readability.
// Defined up here so we don't instantiate them repeatedly in loops.
REGEXPS: {
- unlikelyCandidates: /banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
+ unlikelyCandidates: /-ad-|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
okMaybeItsACandidate: /and|article|body|column|main|shadow/i,
positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
@@ -132,8 +141,19 @@ Readability.prototype = {
DEPRECATED_SIZE_ATTRIBUTE_ELEMS: [ "TABLE", "TH", "TD", "HR", "PRE" ],
+ // The commented out elements qualify as phrasing content but tend to be
+ // removed by readability when put into paragraphs, so we ignore them here.
+ PHRASING_ELEMS: [
+ // "CANVAS", "IFRAME", "SVG", "VIDEO",
+ "ABBR", "AUDIO", "B", "BDO", "BR", "BUTTON", "CITE", "CODE", "DATA",
+ "DATALIST", "DFN", "EM", "EMBED", "I", "IMG", "INPUT", "KBD", "LABEL",
+ "MARK", "MATH", "METER", "NOSCRIPT", "OBJECT", "OUTPUT", "PROGRESS", "Q",
+ "RUBY", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG", "SUB",
+ "SUP", "TEXTAREA", "TIME", "VAR", "WBR"
+ ],
+
// These are the classes that readability sets itself.
- CLASSES_TO_PRESERVE: [ "readability-styled", "page" ],
+ CLASSES_TO_PRESERVE: [ "page" ],
/**
* Run any post-process modifications to article content as necessary.
@@ -216,6 +236,21 @@ Readability.prototype = {
},
/**
+ * Iterate over a NodeList, return true if all of the provided iterate
+ * function calls return true, false otherwise.
+ *
+ * For convenience, the current object context is applied to the
+ * provided iterate function.
+ *
+ * @param NodeList nodeList The NodeList.
+ * @param Function fn The iterate function.
+ * @return Boolean
+ */
+ _everyNode: function(nodeList, fn) {
+ return Array.prototype.every.call(nodeList, fn, this);
+ },
+
+ /**
* Concat all nodelists passed as arguments.
*
* @return ...NodeList
@@ -327,7 +362,7 @@ Readability.prototype = {
var origTitle = "";
try {
- curTitle = origTitle = doc.title;
+ curTitle = origTitle = doc.title.trim();
// If they had an element with id "title" in their HTML
if (typeof curTitle !== "string")
@@ -355,8 +390,9 @@ Readability.prototype = {
doc.getElementsByTagName('h1'),
doc.getElementsByTagName('h2')
);
+ var trimmedTitle = curTitle.trim();
var match = this._someNode(headings, function(heading) {
- return heading.textContent === curTitle;
+ return heading.textContent.trim() === trimmedTitle;
});
// If we don't, let's extract the title out of the original title string.
@@ -421,7 +457,7 @@ Readability.prototype = {
_nextElement: function (node) {
var next = node;
while (next
- && (next.nodeType != Node.ELEMENT_NODE)
+ && (next.nodeType != this.ELEMENT_NODE)
&& this.REGEXPS.whitespace.test(next.textContent)) {
next = next.nextSibling;
}
@@ -464,16 +500,22 @@ Readability.prototype = {
while (next) {
// If we've hit another <br><br>, we're done adding children to this <p>.
if (next.tagName == "BR") {
- var nextElem = this._nextElement(next);
+ var nextElem = this._nextElement(next.nextSibling);
if (nextElem && nextElem.tagName == "BR")
break;
}
+ if (!this._isPhrasingContent(next)) break;
+
// Otherwise, make this node a child of the new <p>.
var sibling = next.nextSibling;
p.appendChild(next);
next = sibling;
}
+
+ while (p.lastChild && this._isWhitespace(p.lastChild)) p.removeChild(p.lastChild);
+
+ if (p.parentNode.tagName === "P") this._setNodeTag(p.parentNode, "DIV");
}
});
},
@@ -523,6 +565,7 @@ Readability.prototype = {
this._clean(articleContent, "h1");
this._clean(articleContent, "footer");
this._clean(articleContent, "link");
+ this._clean(articleContent, "aside");
// Clean out elements have "share" in their id/class combinations from final top candidates,
// which means we don't remove the top candidates even they have "share".
@@ -579,6 +622,19 @@ Readability.prototype = {
if (next && next.tagName == "P")
br.parentNode.removeChild(br);
});
+
+ // Remove single-cell tables
+ this._forEachNode(this._getAllNodesWithTag(articleContent, ["table"]), function(table) {
+ var tbody = this._hasSingleTagInsideElement(table, "TBODY") ? table.firstElementChild : table;
+ if (this._hasSingleTagInsideElement(tbody, "TR")) {
+ var row = tbody.firstElementChild;
+ if (this._hasSingleTagInsideElement(row, "TD")) {
+ var cell = row.firstElementChild;
+ cell = this._setNodeTag(cell, this._everyNode(cell.childNodes, this._isPhrasingContent) ? "P" : "DIV");
+ table.parentNode.replaceChild(cell, table);
+ }
+ }
+ });
},
/**
@@ -658,37 +714,6 @@ Readability.prototype = {
return node && node.nextElementSibling;
},
- /**
- * Like _getNextNode, but for DOM implementations with no
- * firstElementChild/nextElementSibling functionality...
- */
- _getNextNodeNoElementProperties: function(node, ignoreSelfAndKids) {
- function nextSiblingEl(n) {
- do {
- n = n.nextSibling;
- } while (n && n.nodeType !== n.ELEMENT_NODE);
- return n;
- }
- // First check for kids if those aren't being ignored
- if (!ignoreSelfAndKids && node.children[0]) {
- return node.children[0];
- }
- // Then for siblings...
- var next = nextSiblingEl(node);
- if (next) {
- return next;
- }
- // And finally, move up the parent chain *and* find a sibling
- // (because this is depth-first traversal, we will have already
- // seen the parent nodes themselves).
- do {
- node = node.parentNode;
- if (node)
- next = nextSiblingEl(node);
- } while (node && !next);
- return node && next;
- },
-
_checkByline: function(node, matchString) {
if (this._articleByline) {
return false;
@@ -751,6 +776,12 @@ Readability.prototype = {
while (node) {
var matchString = node.className + " " + node.id;
+ if (!this._isProbablyVisible(node)) {
+ this.log("Removing hidden node - " + matchString);
+ node = this._removeAndGetNext(node);
+ continue;
+ }
+
// Check to see if this node is a byline, and remove it if it is.
if (this._checkByline(node, matchString)) {
node = this._removeAndGetNext(node);
@@ -784,11 +815,31 @@ Readability.prototype = {
// Turn all divs that don't have children block level elements into p's
if (node.tagName === "DIV") {
+ // Put phrasing content into paragraphs.
+ var p = null;
+ var childNode = node.firstChild;
+ while (childNode) {
+ var nextSibling = childNode.nextSibling;
+ if (this._isPhrasingContent(childNode)) {
+ if (p !== null) {
+ p.appendChild(childNode);
+ } else if (!this._isWhitespace(childNode)) {
+ p = doc.createElement('p');
+ node.replaceChild(p, childNode);
+ p.appendChild(childNode);
+ }
+ } else if (p !== null) {
+ while (p.lastChild && this._isWhitespace(p.lastChild)) p.removeChild(p.lastChild);
+ p = null;
+ }
+ childNode = nextSibling;
+ }
+
// Sites like http://mobile.slate.com encloses each paragraph with a DIV
// element. DIVs with only a P element inside and no text content can be
// safely converted into plain P elements to avoid confusing the scoring
// algorithm with DIVs with are, in practice, paragraphs.
- if (this._hasSinglePInsideElement(node)) {
+ if (this._hasSingleTagInsideElement(node, "P") && this._getLinkDensity(node) < 0.25) {
var newNode = node.children[0];
node.parentNode.replaceChild(newNode, node);
node = newNode;
@@ -796,17 +847,6 @@ Readability.prototype = {
} else if (!this._hasChildBlockElement(node)) {
node = this._setNodeTag(node, "P");
elementsToScore.push(node);
- } else {
- // EXPERIMENTAL
- this._forEachNode(node.childNodes, function(childNode) {
- if (childNode.nodeType === Node.TEXT_NODE && childNode.textContent.trim().length > 0) {
- var p = doc.createElement('p');
- p.textContent = childNode.textContent;
- p.style.display = 'inline';
- p.className = 'readability-styled';
- node.replaceChild(p, childNode);
- }
- });
}
}
node = this._getNextNode(node);
@@ -846,7 +886,7 @@ Readability.prototype = {
// Initialize and score ancestors.
this._forEachNode(ancestors, function(ancestor, level) {
- if (!ancestor.tagName)
+ if (!ancestor.tagName || !ancestor.parentNode || typeof(ancestor.parentNode.tagName) === 'undefined')
return;
if (typeof(ancestor.readability) === 'undefined') {
@@ -1085,7 +1125,7 @@ Readability.prototype = {
// finding the content, and the sieve approach gives us a higher likelihood of
// finding the -right- content.
var textLength = this._getInnerText(articleContent, true).length;
- if (textLength < this._wordThreshold) {
+ if (textLength < this._charThreshold) {
parseSuccessful = false;
page.innerHTML = pageCacheHtml;
@@ -1233,27 +1273,28 @@ Readability.prototype = {
},
/**
- * Check if this node has only whitespace and a single P element
+ * Check if this node has only whitespace and a single element with given tag
* Returns false if the DIV node contains non-empty text nodes
- * or if it contains no P or more than 1 element.
+ * or if it contains no element with given tag or more than 1 element.
*
* @param Element
+ * @param string tag of child element
**/
- _hasSinglePInsideElement: function(element) {
- // There should be exactly 1 element child which is a P:
- if (element.children.length != 1 || element.children[0].tagName !== "P") {
+ _hasSingleTagInsideElement: function(element, tag) {
+ // There should be exactly 1 element child with given tag
+ if (element.children.length != 1 || element.children[0].tagName !== tag) {
return false;
}
// And there should be no text nodes with real content
return !this._someNode(element.childNodes, function(node) {
- return node.nodeType === Node.TEXT_NODE &&
+ return node.nodeType === this.TEXT_NODE &&
this.REGEXPS.hasContent.test(node.textContent);
});
},
_isElementWithoutContent: function(node) {
- return node.nodeType === Node.ELEMENT_NODE &&
+ return node.nodeType === this.ELEMENT_NODE &&
node.textContent.trim().length == 0 &&
(node.children.length == 0 ||
node.children.length == node.getElementsByTagName("br").length + node.getElementsByTagName("hr").length);
@@ -1271,6 +1312,21 @@ Readability.prototype = {
});
},
+ /***
+ * Determine if a node qualifies as phrasing content.
+ * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
+ **/
+ _isPhrasingContent: function(node) {
+ return node.nodeType === this.TEXT_NODE || this.PHRASING_ELEMS.indexOf(node.tagName) !== -1 ||
+ ((node.tagName === "A" || node.tagName === "DEL" || node.tagName === "INS") &&
+ this._everyNode(node.childNodes, this._isPhrasingContent));
+ },
+
+ _isWhitespace: function(node) {
+ return (node.nodeType === this.TEXT_NODE && node.textContent.trim().length === 0) ||
+ (node.nodeType === this.ELEMENT_NODE && node.tagName === "BR");
+ },
+
/**
* Get the inner text of a node - cross browser compatibly.
* This also strips out any excess whitespace to be found.
@@ -1312,16 +1368,14 @@ Readability.prototype = {
if (!e || e.tagName.toLowerCase() === 'svg')
return;
- if (e.className !== 'readability-styled') {
- // Remove `style` and deprecated presentational attributes
- for (var i = 0; i < this.PRESENTATIONAL_ATTRIBUTES.length; i++) {
- e.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[i]);
- }
+ // Remove `style` and deprecated presentational attributes
+ for (var i = 0; i < this.PRESENTATIONAL_ATTRIBUTES.length; i++) {
+ e.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[i]);
+ }
- if (this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(e.tagName) !== -1) {
- e.removeAttribute('width');
- e.removeAttribute('height');
- }
+ if (this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(e.tagName) !== -1) {
+ e.removeAttribute('width');
+ e.removeAttribute('height');
}
var cur = e.firstElementChild;
@@ -1639,6 +1693,10 @@ Readability.prototype = {
this._flags = this._flags & ~flag;
},
+ _isProbablyVisible: function(node) {
+ return node.style.display != "none" && !node.hasAttribute("hidden");
+ },
+
/**
* Decides whether or not the document is reader-able without parsing the whole thing.
*
@@ -1663,9 +1721,9 @@ Readability.prototype = {
nodes = [].concat.apply(Array.from(set), nodes);
}
- // FIXME we should have a fallback for helperIsVisible, but this is
- // problematic because of jsdom's elem.style handling - see
- // https://github.com/mozilla/readability/pull/186 for context.
+ if (!helperIsVisible) {
+ helperIsVisible = this._isProbablyVisible;
+ }
var score = 0;
// This is a little cheeky, we use the accumulator 'score' to decide what to return from
@@ -1719,9 +1777,6 @@ Readability.prototype = {
}
}
- if (typeof this._doc.documentElement.firstElementChild === "undefined") {
- this._getNextNode = this._getNextNodeNoElementProperties;
- }
// Remove script tags from the document.
this._removeScripts(this._doc);
@@ -1750,7 +1805,6 @@ Readability.prototype = {
var textContent = articleContent.textContent;
return {
- uri: this._uri,
title: this._articleTitle,
byline: metadata.byline || this._articleByline,
dir: this._articleDir,
diff --git a/toolkit/components/reader/ReaderMode.jsm b/toolkit/components/reader/ReaderMode.jsm
index e9eb83154..218e12d60 100644
--- a/toolkit/components/reader/ReaderMode.jsm
+++ b/toolkit/components/reader/ReaderMode.jsm
@@ -195,7 +195,7 @@ this.ReaderMode = {
// We pass in a helper function to determine if a node is visible, because
// it uses gecko APIs that the engine-agnostic readability code can't rely
// upon.
- return new Readability(uri, doc).isProbablyReaderable(this.isNodeVisible.bind(this, utils));
+ return new Readability(doc).isProbablyReaderable(this.isNodeVisible.bind(this, utils));
},
isNodeVisible(utils, node) {
diff --git a/toolkit/components/reader/ReaderWorker.js b/toolkit/components/reader/ReaderWorker.js
index 69426788b..9cc684e9b 100644
--- a/toolkit/components/reader/ReaderWorker.js
+++ b/toolkit/components/reader/ReaderWorker.js
@@ -48,6 +48,6 @@ var Agent = {
*/
parseDocument(uri, serializedDoc, options) {
let doc = new JSDOMParser().parse(serializedDoc, uri.spec);
- return new Readability(uri, doc, options).parse();
+ return new Readability(doc, options).parse();
},
};
diff --git a/toolkit/components/thumbnails/test/test_thumbnails_interfaces.js b/toolkit/components/thumbnails/test/test_thumbnails_interfaces.js
index 8272b2e06..a8fe51418 100644
--- a/toolkit/components/thumbnails/test/test_thumbnails_interfaces.js
+++ b/toolkit/components/thumbnails/test/test_thumbnails_interfaces.js
@@ -22,10 +22,4 @@ function run_test() {
null, null);
ok(uri instanceof Ci.nsIFileURL, "moz-page-thumb:// is a FileURL");
ok(uri.file, "This moz-page-thumb:// object is backed by a file");
-
- // and check that the error case works as specified
- let bad = Services.io.newURI("moz-page-thumb://wronghost/?url=http%3A%2F%2Fwww.mozilla.org%2F",
- null, null);
- Assert.throws(() => handler.resolveURI(bad), /NS_ERROR_NOT_AVAILABLE/i,
- "moz-page-thumb object with wrong host must not resolve to a file path");
}
diff --git a/toolkit/content/widgets/browser.xml b/toolkit/content/widgets/browser.xml
index e595c847d..a30ff1c43 100644
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -389,10 +389,11 @@
<method name="getTabBrowser">
<body>
<![CDATA[
- var tabBrowser = this.parentNode;
- while (tabBrowser && tabBrowser.localName != "tabbrowser")
- tabBrowser = tabBrowser.parentNode;
- return tabBrowser;
+ for (let node = this.parentNode; node instanceof Element; node = node.parentNode) {
+ if (node.localName == "tabbrowser")
+ return node;
+ }
+ return null;
]]>
</body>
</method>
diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm
index d453a8981..4cd2c3d0a 100644
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -123,13 +123,13 @@ function providerName(aProvider) {
* parent 'addons' level logger accordingly.
*/
var PrefObserver = {
- init: function PrefObserver_init() {
+ init: function() {
Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false);
Services.obs.addObserver(this, "xpcom-shutdown", false);
this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED);
},
- observe: function PrefObserver_observe(aSubject, aTopic, aData) {
+ observe: function(aSubject, aTopic, aData) {
if (aTopic == "xpcom-shutdown") {
Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this);
Services.obs.removeObserver(this, "xpcom-shutdown");
@@ -323,7 +323,7 @@ AsyncObjectCaller.prototype = {
* Passes the next object to the listener or calls noMoreObjects if there
* are none left.
*/
- callNext: function AOC_callNext() {
+ callNext: function() {
if (this.objects.length == 0) {
this.listener.noMoreObjects(this);
return;
@@ -449,7 +449,7 @@ AddonAuthor.prototype = {
url: null,
// Returns the author's name, defaulting to the empty string
- toString: function AddonAuthor_toString() {
+ toString: function() {
return this.name || "";
}
}
@@ -493,7 +493,7 @@ AddonScreenshot.prototype = {
caption: null,
// Returns the screenshot URL, defaulting to the empty string
- toString: function AddonScreenshot_toString() {
+ toString: function() {
return this.url || "";
}
}
@@ -640,11 +640,11 @@ var AddonManagerInternal = {
// Store telemetry details per addon provider
telemetryDetails: {},
- recordTimestamp: function AMI_recordTimestamp(name, value) {
+ recordTimestamp: function(name, value) {
this.TelemetryTimestamps.add(name, value);
},
- validateBlocklist: function AMI_validateBlocklist() {
+ validateBlocklist: function() {
let appBlocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
// If there is no application shipped blocklist then there is nothing to do
@@ -771,7 +771,7 @@ var AddonManagerInternal = {
* Initializes the AddonManager, loading any known providers and initializing
* them.
*/
- startup: function AMI_startup() {
+ startup: function() {
try {
if (gStarted)
return;
@@ -925,7 +925,7 @@ var AddonManagerInternal = {
* @param aTypes
* An optional array of add-on types
*/
- registerProvider: function AMI_registerProvider(aProvider, aTypes) {
+ registerProvider: function(aProvider, aTypes) {
if (!aProvider || typeof aProvider != "object")
throw Components.Exception("aProvider must be specified",
Cr.NS_ERROR_INVALID_ARG);
@@ -977,7 +977,7 @@ var AddonManagerInternal = {
* For providers that have async shutdown methods returning Promises,
* the caller should wait for that Promise to resolve.
*/
- unregisterProvider: function AMI_unregisterProvider(aProvider) {
+ unregisterProvider: function(aProvider) {
if (!aProvider || typeof aProvider != "object")
throw Components.Exception("aProvider must be specified",
Cr.NS_ERROR_INVALID_ARG);
@@ -1032,7 +1032,7 @@ var AddonManagerInternal = {
*
* @param aProvider Provider object to mark safe
*/
- markProviderSafe: function AMI_markProviderSafe(aProvider) {
+ markProviderSafe: function(aProvider) {
if (!gStarted) {
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1062,7 +1062,7 @@ var AddonManagerInternal = {
* The method name to call
* @see callProvider
*/
- callProviders: function AMI_callProviders(aMethod, ...aArgs) {
+ callProviders: function(aMethod, ...aArgs) {
if (!aMethod || typeof aMethod != "string")
throw Components.Exception("aMethod must be a non-empty string",
Cr.NS_ERROR_INVALID_ARG);
@@ -1163,7 +1163,7 @@ var AddonManagerInternal = {
*
* @see nsIObserver
*/
- observe: function AMI_observe(aSubject, aTopic, aData) {
+ observe: function(aSubject, aTopic, aData) {
switch (aData) {
case PREF_EM_CHECK_COMPATIBILITY: {
let oldValue = gCheckCompatibility;
@@ -1247,7 +1247,7 @@ var AddonManagerInternal = {
* The optional application version to use for %APP_VERSION%
* @return The appropriately escaped URI.
*/
- escapeAddonURI: function AMI_escapeAddonURI(aAddon, aUri, aAppVersion)
+ escapeAddonURI: function(aAddon, aUri, aAppVersion)
{
if (!aAddon || typeof aAddon != "object")
throw Components.Exception("aAddon must be an Addon object",
@@ -1318,7 +1318,7 @@ var AddonManagerInternal = {
* @return Promise{null} Resolves when the background update check is complete
* (the resulting addon installations may still be in progress).
*/
- backgroundUpdateCheck: function AMI_backgroundUpdateCheck() {
+ backgroundUpdateCheck: function() {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1347,7 +1347,7 @@ var AddonManagerInternal = {
// be applied
updates.push(new Promise((resolve, reject) => {
addon.findUpdates({
- onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
+ onUpdateAvailable: function(aAddon, aInstall) {
// Start installing updates when the add-on can be updated and
// background updates should be applied.
logger.debug("Found update for add-on ${id}", aAddon);
@@ -1389,7 +1389,7 @@ var AddonManagerInternal = {
* @param aID
* The ID of the add-on
*/
- addStartupChange: function AMI_addStartupChange(aType, aID) {
+ addStartupChange: function(aType, aID) {
if (!aType || typeof aType != "string")
throw Components.Exception("aType must be a non-empty string",
Cr.NS_ERROR_INVALID_ARG);
@@ -1418,7 +1418,7 @@ var AddonManagerInternal = {
* @param aID
* The ID of the add-on
*/
- removeStartupChange: function AMI_removeStartupChange(aType, aID) {
+ removeStartupChange: function(aType, aID) {
if (!aType || typeof aType != "string")
throw Components.Exception("aType must be a non-empty string",
Cr.NS_ERROR_INVALID_ARG);
@@ -1444,7 +1444,7 @@ var AddonManagerInternal = {
* @param aMethod
* The method on the listeners to call
*/
- callManagerListeners: function AMI_callManagerListeners(aMethod, ...aArgs) {
+ callManagerListeners: function(aMethod, ...aArgs) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1475,7 +1475,7 @@ var AddonManagerInternal = {
* An optional array of extra InstallListeners to also call
* @return false if any of the listeners returned false, true otherwise
*/
- callInstallListeners: function AMI_callInstallListeners(aMethod,
+ callInstallListeners: function(aMethod,
aExtraListeners, ...aArgs) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
@@ -1517,7 +1517,7 @@ var AddonManagerInternal = {
* @param aMethod
* The method on the listeners to call
*/
- callAddonListeners: function AMI_callAddonListeners(aMethod, ...aArgs) {
+ callAddonListeners: function(aMethod, ...aArgs) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1551,7 +1551,7 @@ var AddonManagerInternal = {
* A boolean indicating if the change will only take place the next
* time the application is restarted
*/
- notifyAddonChanged: function AMI_notifyAddonChanged(aID, aType, aPendingRestart) {
+ notifyAddonChanged: function(aID, aType, aPendingRestart) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1588,7 +1588,7 @@ var AddonManagerInternal = {
* their add-ons in response to an application change such as a blocklist
* update.
*/
- updateAddonAppDisabledStates: function AMI_updateAddonAppDisabledStates() {
+ updateAddonAppDisabledStates: function() {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1603,7 +1603,7 @@ var AddonManagerInternal = {
* @param aCallback
* Function to call when operation is complete.
*/
- updateAddonRepositoryData: function AMI_updateAddonRepositoryData(aCallback) {
+ updateAddonRepositoryData: function(aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1613,11 +1613,11 @@ var AddonManagerInternal = {
Cr.NS_ERROR_INVALID_ARG);
new AsyncObjectCaller(this.providers, "updateAddonRepositoryData", {
- nextObject: function updateAddonRepositoryData_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "updateAddonRepositoryData",
aCaller.callNext.bind(aCaller));
},
- noMoreObjects: function updateAddonRepositoryData_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback);
// only tests should care about this
Services.obs.notifyObservers(null, "TEST:addon-repository-data-updated", null);
@@ -1646,7 +1646,7 @@ var AddonManagerInternal = {
* An optional nsILoadGroup to associate any network requests with
* @throws if the aUrl, aCallback or aMimetype arguments are not specified
*/
- getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype,
+ getInstallForURL: function(aUrl, aCallback, aMimetype,
aHash, aName, aIcons,
aVersion, aBrowser) {
if (!gStarted)
@@ -1716,7 +1716,7 @@ var AddonManagerInternal = {
* An optional mimetype hint for the add-on
* @throws if the aFile or aCallback arguments are not specified
*/
- getInstallForFile: function AMI_getInstallForFile(aFile, aCallback, aMimetype) {
+ getInstallForFile: function(aFile, aCallback, aMimetype) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1734,7 +1734,7 @@ var AddonManagerInternal = {
Cr.NS_ERROR_INVALID_ARG);
new AsyncObjectCaller(this.providers, "getInstallForFile", {
- nextObject: function getInstallForFile_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getInstallForFile", aFile,
function getInstallForFile_safeCall(aInstall) {
if (aInstall)
@@ -1744,7 +1744,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getInstallForFile_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, null);
}
});
@@ -1760,7 +1760,7 @@ var AddonManagerInternal = {
* A callback which will be passed an array of AddonInstalls
* @throws If the aCallback argument is not specified
*/
- getInstallsByTypes: function AMI_getInstallsByTypes(aTypes, aCallback) {
+ getInstallsByTypes: function(aTypes, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1776,7 +1776,7 @@ var AddonManagerInternal = {
let installs = [];
new AsyncObjectCaller(this.providers, "getInstallsByTypes", {
- nextObject: function getInstallsByTypes_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getInstallsByTypes", aTypes,
function getInstallsByTypes_safeCall(aProviderInstalls) {
if (aProviderInstalls) {
@@ -1786,7 +1786,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getInstallsByTypes_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, installs);
}
});
@@ -1798,7 +1798,7 @@ var AddonManagerInternal = {
* @param aCallback
* A callback which will be passed an array of AddonInstalls
*/
- getAllInstalls: function AMI_getAllInstalls(aCallback) {
+ getAllInstalls: function(aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1818,7 +1818,7 @@ var AddonManagerInternal = {
* @return string containing the Addon ID or null
* @see amIAddonManager.mapURIToAddonID
*/
- mapURIToAddonID: function AMI_mapURIToAddonID(aURI) {
+ mapURIToAddonID: function(aURI) {
if (!(aURI instanceof Ci.nsIURI)) {
throw Components.Exception("aURI is not a nsIURI",
Cr.NS_ERROR_INVALID_ARG);
@@ -1843,7 +1843,7 @@ var AddonManagerInternal = {
* The mimetype to check
* @return true if installation is enabled for the mimetype
*/
- isInstallEnabled: function AMI_isInstallEnabled(aMimetype) {
+ isInstallEnabled: function(aMimetype) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1871,7 +1871,7 @@ var AddonManagerInternal = {
* The nsIPrincipal that initiated the install
* @return true if the source is allowed to install this mimetype
*/
- isInstallAllowed: function AMI_isInstallAllowed(aMimetype, aInstallingPrincipal) {
+ isInstallAllowed: function(aMimetype, aInstallingPrincipal) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -1906,10 +1906,7 @@ var AddonManagerInternal = {
* @param aInstalls
* The array of AddonInstalls to be installed
*/
- installAddonsFromWebpage: function AMI_installAddonsFromWebpage(aMimetype,
- aBrowser,
- aInstallingPrincipal,
- aInstalls) {
+ installAddonsFromWebpage: function(aMimetype, aBrowser, aInstallingPrincipal, aInstalls) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2011,7 +2008,7 @@ var AddonManagerInternal = {
* @param aListener
* The InstallListener to add
*/
- addInstallListener: function AMI_addInstallListener(aListener) {
+ addInstallListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be a InstallListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2027,7 +2024,7 @@ var AddonManagerInternal = {
* @param aListener
* The InstallListener to remove
*/
- removeInstallListener: function AMI_removeInstallListener(aListener) {
+ removeInstallListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be a InstallListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2050,7 +2047,7 @@ var AddonManagerInternal = {
* The callback to pass the retrieved add-on to
* @throws if the aID or aCallback arguments are not specified
*/
- getAddonByID: function AMI_getAddonByID(aID, aCallback) {
+ getAddonByID: function(aID, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2064,7 +2061,7 @@ var AddonManagerInternal = {
Cr.NS_ERROR_INVALID_ARG);
new AsyncObjectCaller(this.providers, "getAddonByID", {
- nextObject: function getAddonByID_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getAddonByID", aID,
function getAddonByID_safeCall(aAddon) {
if (aAddon)
@@ -2074,7 +2071,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getAddonByID_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, null);
}
});
@@ -2089,7 +2086,7 @@ var AddonManagerInternal = {
* The callback to pass the retrieved add-on to.
* @throws if the aGUID or aCallback arguments are not specified
*/
- getAddonBySyncGUID: function AMI_getAddonBySyncGUID(aGUID, aCallback) {
+ getAddonBySyncGUID: function(aGUID, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2103,7 +2100,7 @@ var AddonManagerInternal = {
Cr.NS_ERROR_INVALID_ARG);
new AsyncObjectCaller(this.providers, "getAddonBySyncGUID", {
- nextObject: function getAddonBySyncGUID_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getAddonBySyncGUID", aGUID,
function getAddonBySyncGUID_safeCall(aAddon) {
if (aAddon) {
@@ -2114,7 +2111,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getAddonBySyncGUID_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, null);
}
});
@@ -2129,7 +2126,7 @@ var AddonManagerInternal = {
* The callback to pass an array of Addons to
* @throws if the aID or aCallback arguments are not specified
*/
- getAddonsByIDs: function AMI_getAddonsByIDs(aIDs, aCallback) {
+ getAddonsByIDs: function(aIDs, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2145,7 +2142,7 @@ var AddonManagerInternal = {
let addons = [];
new AsyncObjectCaller(aIDs, null, {
- nextObject: function getAddonsByIDs_nextObject(aCaller, aID) {
+ nextObject: function(aCaller, aID) {
AddonManagerInternal.getAddonByID(aID,
function getAddonsByIDs_getAddonByID(aAddon) {
addons.push(aAddon);
@@ -2153,7 +2150,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getAddonsByIDs_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, addons);
}
});
@@ -2168,7 +2165,7 @@ var AddonManagerInternal = {
* The callback to pass an array of Addons to.
* @throws if the aCallback argument is not specified
*/
- getAddonsByTypes: function AMI_getAddonsByTypes(aTypes, aCallback) {
+ getAddonsByTypes: function(aTypes, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2184,7 +2181,7 @@ var AddonManagerInternal = {
let addons = [];
new AsyncObjectCaller(this.providers, "getAddonsByTypes", {
- nextObject: function getAddonsByTypes_nextObject(aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getAddonsByTypes", aTypes,
function getAddonsByTypes_concatAddons(aProviderAddons) {
if (aProviderAddons) {
@@ -2194,7 +2191,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getAddonsByTypes_noMoreObjects(aCaller) {
+ noMoreObjects: function(aCaller) {
safeCall(aCallback, addons);
}
});
@@ -2206,7 +2203,7 @@ var AddonManagerInternal = {
* @param aCallback
* A callback which will be passed an array of Addons
*/
- getAllAddons: function AMI_getAllAddons(aCallback) {
+ getAllAddons: function(aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2228,8 +2225,7 @@ var AddonManagerInternal = {
* The callback to pass the array of Addons to
* @throws if the aCallback argument is not specified
*/
- getAddonsWithOperationsByTypes:
- function AMI_getAddonsWithOperationsByTypes(aTypes, aCallback) {
+ getAddonsWithOperationsByTypes: function(aTypes, aCallback) {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
@@ -2245,8 +2241,7 @@ var AddonManagerInternal = {
let addons = [];
new AsyncObjectCaller(this.providers, "getAddonsWithOperationsByTypes", {
- nextObject: function getAddonsWithOperationsByTypes_nextObject
- (aCaller, aProvider) {
+ nextObject: function(aCaller, aProvider) {
callProviderAsync(aProvider, "getAddonsWithOperationsByTypes", aTypes,
function getAddonsWithOperationsByTypes_concatAddons
(aProviderAddons) {
@@ -2257,7 +2252,7 @@ var AddonManagerInternal = {
});
},
- noMoreObjects: function getAddonsWithOperationsByTypes_noMoreObjects(caller) {
+ noMoreObjects: function(caller) {
safeCall(aCallback, addons);
}
});
@@ -2269,7 +2264,7 @@ var AddonManagerInternal = {
* @param aListener
* The listener to add
*/
- addManagerListener: function AMI_addManagerListener(aListener) {
+ addManagerListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be an AddonManagerListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2285,7 +2280,7 @@ var AddonManagerInternal = {
* @param aListener
* The listener to remove
*/
- removeManagerListener: function AMI_removeManagerListener(aListener) {
+ removeManagerListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be an AddonManagerListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2305,7 +2300,7 @@ var AddonManagerInternal = {
* @param aListener
* The AddonListener to add
*/
- addAddonListener: function AMI_addAddonListener(aListener) {
+ addAddonListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be an AddonListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2321,7 +2316,7 @@ var AddonManagerInternal = {
* @param aListener
* The AddonListener to remove
*/
- removeAddonListener: function AMI_removeAddonListener(aListener) {
+ removeAddonListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be an AddonListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2341,7 +2336,7 @@ var AddonManagerInternal = {
* @param aListener
* The TypeListener to add
*/
- addTypeListener: function AMI_addTypeListener(aListener) {
+ addTypeListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be a TypeListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2357,7 +2352,7 @@ var AddonManagerInternal = {
* @param aListener
* The TypeListener to remove
*/
- removeTypeListener: function AMI_removeTypeListener(aListener) {
+ removeTypeListener: function(aListener) {
if (!aListener || typeof aListener != "object")
throw Components.Exception("aListener must be a TypeListener object",
Cr.NS_ERROR_INVALID_ARG);
@@ -2496,23 +2491,23 @@ var AddonManagerInternal = {
* subject to change at any time.
*/
this.AddonManagerPrivate = {
- startup: function AMP_startup() {
+ startup: function() {
AddonManagerInternal.startup();
},
- registerProvider: function AMP_registerProvider(aProvider, aTypes) {
+ registerProvider: function(aProvider, aTypes) {
AddonManagerInternal.registerProvider(aProvider, aTypes);
},
- unregisterProvider: function AMP_unregisterProvider(aProvider) {
+ unregisterProvider: function(aProvider) {
AddonManagerInternal.unregisterProvider(aProvider);
},
- markProviderSafe: function AMP_markProviderSafe(aProvider) {
+ markProviderSafe: function(aProvider) {
AddonManagerInternal.markProviderSafe(aProvider);
},
- backgroundUpdateCheck: function AMP_backgroundUpdateCheck() {
+ backgroundUpdateCheck: function() {
return AddonManagerInternal.backgroundUpdateCheck();
},
@@ -2526,32 +2521,32 @@ this.AddonManagerPrivate = {
AddonManagerInternal.backgroundUpdateCheck();
},
- addStartupChange: function AMP_addStartupChange(aType, aID) {
+ addStartupChange: function(aType, aID) {
AddonManagerInternal.addStartupChange(aType, aID);
},
- removeStartupChange: function AMP_removeStartupChange(aType, aID) {
+ removeStartupChange: function(aType, aID) {
AddonManagerInternal.removeStartupChange(aType, aID);
},
- notifyAddonChanged: function AMP_notifyAddonChanged(aID, aType, aPendingRestart) {
+ notifyAddonChanged: function(aID, aType, aPendingRestart) {
AddonManagerInternal.notifyAddonChanged(aID, aType, aPendingRestart);
},
- updateAddonAppDisabledStates: function AMP_updateAddonAppDisabledStates() {
+ updateAddonAppDisabledStates: function() {
AddonManagerInternal.updateAddonAppDisabledStates();
},
- updateAddonRepositoryData: function AMP_updateAddonRepositoryData(aCallback) {
+ updateAddonRepositoryData: function(aCallback) {
AddonManagerInternal.updateAddonRepositoryData(aCallback);
},
- callInstallListeners: function AMP_callInstallListeners(...aArgs) {
+ callInstallListeners: function(...aArgs) {
return AddonManagerInternal.callInstallListeners.apply(AddonManagerInternal,
aArgs);
},
- callAddonListeners: function AMP_callAddonListeners(...aArgs) {
+ callAddonListeners: function(...aArgs) {
AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs);
},
@@ -2563,16 +2558,16 @@ this.AddonManagerPrivate = {
AddonType: AddonType,
- recordTimestamp: function AMP_recordTimestamp(name, value) {
+ recordTimestamp: function(name, value) {
AddonManagerInternal.recordTimestamp(name, value);
},
_simpleMeasures: {},
- recordSimpleMeasure: function AMP_recordSimpleMeasure(name, value) {
+ recordSimpleMeasure: function(name, value) {
this._simpleMeasures[name] = value;
},
- recordException: function AMP_recordException(aModule, aContext, aException) {
+ recordException: function(aModule, aContext, aException) {
let report = {
module: aModule,
context: aContext
@@ -2592,15 +2587,15 @@ this.AddonManagerPrivate = {
this._simpleMeasures.exception = report;
},
- getSimpleMeasures: function AMP_getSimpleMeasures() {
+ getSimpleMeasures: function() {
return this._simpleMeasures;
},
- getTelemetryDetails: function AMP_getTelemetryDetails() {
+ getTelemetryDetails: function() {
return AddonManagerInternal.telemetryDetails;
},
- setTelemetryDetails: function AMP_setTelemetryDetails(aProvider, aDetails) {
+ setTelemetryDetails: function(aProvider, aDetails) {
AddonManagerInternal.telemetryDetails[aProvider] = aDetails;
},
@@ -2619,7 +2614,7 @@ this.AddonManagerPrivate = {
* This can be used as an implementation for Addon.findUpdates() when
* no update mechanism is available.
*/
- callNoUpdateListeners: function (addon, listener, reason, appVersion, platformVersion) {
+ callNoUpdateListeners: function(addon, listener, reason, appVersion, platformVersion) {
if ("onNoCompatibilityUpdateAvailable" in listener) {
safeCall(listener.onNoCompatibilityUpdateAvailable.bind(listener), addon);
}
@@ -2830,14 +2825,13 @@ this.AddonManager = {
return gStartupComplete && !gShutdownInProgress;
},
- getInstallForURL: function AM_getInstallForURL(aUrl, aCallback, aMimetype,
- aHash, aName, aIcons,
- aVersion, aBrowser) {
+ getInstallForURL: function(aUrl, aCallback, aMimetype, aHash, aName, aIcons,
+ aVersion, aBrowser) {
AddonManagerInternal.getInstallForURL(aUrl, aCallback, aMimetype, aHash,
aName, aIcons, aVersion, aBrowser);
},
- getInstallForFile: function AM_getInstallForFile(aFile, aCallback, aMimetype) {
+ getInstallForFile: function(aFile, aCallback, aMimetype) {
AddonManagerInternal.getInstallForFile(aFile, aCallback, aMimetype);
},
@@ -2848,94 +2842,91 @@ this.AddonManager = {
* The type of startup change to get
* @return An array of add-on IDs
*/
- getStartupChanges: function AM_getStartupChanges(aType) {
+ getStartupChanges: function(aType) {
if (!(aType in AddonManagerInternal.startupChanges))
return [];
return AddonManagerInternal.startupChanges[aType].slice(0);
},
- getAddonByID: function AM_getAddonByID(aID, aCallback) {
+ getAddonByID: function(aID, aCallback) {
AddonManagerInternal.getAddonByID(aID, aCallback);
},
- getAddonBySyncGUID: function AM_getAddonBySyncGUID(aGUID, aCallback) {
+ getAddonBySyncGUID: function(aGUID, aCallback) {
AddonManagerInternal.getAddonBySyncGUID(aGUID, aCallback);
},
- getAddonsByIDs: function AM_getAddonsByIDs(aIDs, aCallback) {
+ getAddonsByIDs: function(aIDs, aCallback) {
AddonManagerInternal.getAddonsByIDs(aIDs, aCallback);
},
- getAddonsWithOperationsByTypes:
- function AM_getAddonsWithOperationsByTypes(aTypes, aCallback) {
+ getAddonsWithOperationsByTypes: function(aTypes, aCallback) {
AddonManagerInternal.getAddonsWithOperationsByTypes(aTypes, aCallback);
},
- getAddonsByTypes: function AM_getAddonsByTypes(aTypes, aCallback) {
+ getAddonsByTypes: function(aTypes, aCallback) {
AddonManagerInternal.getAddonsByTypes(aTypes, aCallback);
},
- getAllAddons: function AM_getAllAddons(aCallback) {
+ getAllAddons: function(aCallback) {
AddonManagerInternal.getAllAddons(aCallback);
},
- getInstallsByTypes: function AM_getInstallsByTypes(aTypes, aCallback) {
+ getInstallsByTypes: function(aTypes, aCallback) {
AddonManagerInternal.getInstallsByTypes(aTypes, aCallback);
},
- getAllInstalls: function AM_getAllInstalls(aCallback) {
+ getAllInstalls: function(aCallback) {
AddonManagerInternal.getAllInstalls(aCallback);
},
- mapURIToAddonID: function AM_mapURIToAddonID(aURI) {
+ mapURIToAddonID: function(aURI) {
return AddonManagerInternal.mapURIToAddonID(aURI);
},
- isInstallEnabled: function AM_isInstallEnabled(aType) {
+ isInstallEnabled: function(aType) {
return AddonManagerInternal.isInstallEnabled(aType);
},
- isInstallAllowed: function AM_isInstallAllowed(aType, aInstallingPrincipal) {
+ isInstallAllowed: function(aType, aInstallingPrincipal) {
return AddonManagerInternal.isInstallAllowed(aType, ensurePrincipal(aInstallingPrincipal));
},
- installAddonsFromWebpage: function AM_installAddonsFromWebpage(aType, aBrowser,
- aInstallingPrincipal,
- aInstalls) {
+ installAddonsFromWebpage: function(aType, aBrowser, aInstallingPrincipal, aInstalls) {
AddonManagerInternal.installAddonsFromWebpage(aType, aBrowser,
ensurePrincipal(aInstallingPrincipal),
aInstalls);
},
- addManagerListener: function AM_addManagerListener(aListener) {
+ addManagerListener: function(aListener) {
AddonManagerInternal.addManagerListener(aListener);
},
- removeManagerListener: function AM_removeManagerListener(aListener) {
+ removeManagerListener: function(aListener) {
AddonManagerInternal.removeManagerListener(aListener);
},
- addInstallListener: function AM_addInstallListener(aListener) {
+ addInstallListener: function(aListener) {
AddonManagerInternal.addInstallListener(aListener);
},
- removeInstallListener: function AM_removeInstallListener(aListener) {
+ removeInstallListener: function(aListener) {
AddonManagerInternal.removeInstallListener(aListener);
},
- addAddonListener: function AM_addAddonListener(aListener) {
+ addAddonListener: function(aListener) {
AddonManagerInternal.addAddonListener(aListener);
},
- removeAddonListener: function AM_removeAddonListener(aListener) {
+ removeAddonListener: function(aListener) {
AddonManagerInternal.removeAddonListener(aListener);
},
- addTypeListener: function AM_addTypeListener(aListener) {
+ addTypeListener: function(aListener) {
AddonManagerInternal.addTypeListener(aListener);
},
- removeTypeListener: function AM_removeTypeListener(aListener) {
+ removeTypeListener: function(aListener) {
AddonManagerInternal.removeTypeListener(aListener);
},
@@ -2950,7 +2941,7 @@ this.AddonManager = {
* The Addon representing the add-on
* @return true if the addon should auto-update, false otherwise.
*/
- shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
+ shouldAutoUpdate: function(aAddon) {
if (!aAddon || typeof aAddon != "object")
throw Components.Exception("aAddon must be specified",
Cr.NS_ERROR_INVALID_ARG);
@@ -3008,7 +2999,7 @@ this.AddonManager = {
AddonManagerInternal.autoUpdateDefault = aValue;
},
- escapeAddonURI: function AM_escapeAddonURI(aAddon, aUri, aAppVersion) {
+ escapeAddonURI: function(aAddon, aUri, aAppVersion) {
return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion);
},
diff --git a/toolkit/mozapps/extensions/LightweightThemeManager.jsm b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
index 5856bfa91..372a9f3b8 100644
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -110,11 +110,11 @@ this.LightweightThemeManager = {
return _setCurrentTheme(aData, false);
},
- setLocalTheme: function LightweightThemeManager_setLocalTheme(aData) {
+ setLocalTheme: function(aData) {
_setCurrentTheme(aData, true);
},
- getUsedTheme: function LightweightThemeManager_getUsedTheme(aId) {
+ getUsedTheme: function(aId) {
var usedThemes = this.usedThemes;
for (let usedTheme of usedThemes) {
if (usedTheme.id == aId)
@@ -123,7 +123,7 @@ this.LightweightThemeManager = {
return null;
},
- forgetUsedTheme: function LightweightThemeManager_forgetUsedTheme(aId) {
+ forgetUsedTheme: function(aId) {
let theme = this.getUsedTheme(aId);
if (!theme)
return;
@@ -141,7 +141,7 @@ this.LightweightThemeManager = {
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
},
- previewTheme: function LightweightThemeManager_previewTheme(aData) {
+ previewTheme: function(aData) {
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
Services.obs.notifyObservers(cancel, "lightweight-theme-preview-requested",
@@ -160,7 +160,7 @@ this.LightweightThemeManager = {
_notifyWindows(aData);
},
- resetPreview: function LightweightThemeManager_resetPreview() {
+ resetPreview: function() {
if (_previewTimer) {
_previewTimer.cancel();
_previewTimer = null;
@@ -168,7 +168,7 @@ this.LightweightThemeManager = {
}
},
- parseTheme: function LightweightThemeManager_parseTheme(aString, aBaseURI) {
+ parseTheme: function(aString, aBaseURI) {
try {
return _sanitizeTheme(JSON.parse(aString), aBaseURI, false);
} catch (e) {
@@ -176,7 +176,7 @@ this.LightweightThemeManager = {
}
},
- updateCurrentTheme: function LightweightThemeManager_updateCurrentTheme() {
+ updateCurrentTheme: function() {
try {
if (!_prefs.getBoolPref("update.enabled"))
return;
@@ -224,7 +224,7 @@ this.LightweightThemeManager = {
* @param aData
* The lightweight theme to switch to
*/
- themeChanged: function LightweightThemeManager_themeChanged(aData) {
+ themeChanged: function(aData) {
if (_previewTimer) {
_previewTimer.cancel();
_previewTimer = null;
@@ -251,7 +251,7 @@ this.LightweightThemeManager = {
* Starts the Addons provider and enables the new lightweight theme if
* necessary.
*/
- startup: function LightweightThemeManager_startup() {
+ startup: function() {
if (Services.prefs.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
let id = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
if (id)
@@ -267,7 +267,7 @@ this.LightweightThemeManager = {
/**
* Shuts down the provider.
*/
- shutdown: function LightweightThemeManager_shutdown() {
+ shutdown: function() {
_prefs.removeObserver("", _prefObserver);
},
@@ -283,7 +283,7 @@ this.LightweightThemeManager = {
* true if the newly enabled add-on will only become enabled after a
* restart
*/
- addonChanged: function LightweightThemeManager_addonChanged(aId, aType, aPendingRestart) {
+ addonChanged: function(aId, aType, aPendingRestart) {
if (aType != ADDON_TYPE)
return;
@@ -356,7 +356,7 @@ this.LightweightThemeManager = {
* @param aCallback
* A callback to pass the Addon to
*/
- getAddonByID: function LightweightThemeManager_getAddonByID(aId, aCallback) {
+ getAddonByID: function(aId, aCallback) {
let id = _getInternalID(aId);
if (!id) {
aCallback(null);
@@ -380,7 +380,7 @@ this.LightweightThemeManager = {
* @param aCallback
* A callback to pass an array of Addons to
*/
- getAddonsByTypes: function LightweightThemeManager_getAddonsByTypes(aTypes, aCallback) {
+ getAddonsByTypes: function(aTypes, aCallback) {
if (aTypes && aTypes.indexOf(ADDON_TYPE) == -1) {
aCallback([]);
return;
@@ -541,7 +541,7 @@ AddonWrapper.prototype = {
},
// Lightweight themes are always compatible
- isCompatibleWith: function AddonWrapper_isCompatibleWith(appVersion, platformVersion) {
+ isCompatibleWith: function(appVersion, platformVersion) {
return true;
},
@@ -708,7 +708,7 @@ function _notifyWindows(aThemeData) {
var _previewTimer;
var _previewTimerCallback = {
- notify: function _previewTimerCallback_notify() {
+ notify: function() {
LightweightThemeManager.resetPreview();
}
};
diff --git a/toolkit/mozapps/extensions/addonManager.js b/toolkit/mozapps/extensions/addonManager.js
index 731e70c6c..2628ea87b 100644
--- a/toolkit/mozapps/extensions/addonManager.js
+++ b/toolkit/mozapps/extensions/addonManager.js
@@ -53,7 +53,7 @@ function amManager() {
}
amManager.prototype = {
- observe: function AMC_observe(aSubject, aTopic, aData) {
+ observe: function(aSubject, aTopic, aData) {
if (aTopic == "addons-startup")
AddonManagerPrivate.startup();
},
@@ -61,7 +61,7 @@ amManager.prototype = {
/**
* @see amIAddonManager.idl
*/
- mapURIToAddonID: function AMC_mapURIToAddonID(uri, id) {
+ mapURIToAddonID: function(uri, id) {
id.value = AddonManager.mapURIToAddonID(uri);
return !!id.value;
},
@@ -69,19 +69,15 @@ amManager.prototype = {
/**
* @see amIWebInstaller.idl
*/
- isInstallEnabled: function AMC_isInstallEnabled(aMimetype, aReferer) {
+ isInstallEnabled: function(aMimetype, aReferer) {
return AddonManager.isInstallEnabled(aMimetype);
},
/**
* @see amIWebInstaller.idl
*/
- installAddonsFromWebpage: function AMC_installAddonsFromWebpage(aMimetype,
- aBrowser,
- aInstallingPrincipal,
- aUris, aHashes,
- aNames, aIcons,
- aCallback) {
+ installAddonsFromWebpage: function(aMimetype, aBrowser, aInstallingPrincipal,
+ aUris, aHashes, aNames, aIcons, aCallback) {
if (aUris.length == 0)
return false;
@@ -112,22 +108,22 @@ amManager.prototype = {
installs.push(aInstall);
if (aCallback) {
aInstall.addListener({
- onDownloadCancelled: function buildNextInstall_onDownloadCancelled(aInstall) {
+ onDownloadCancelled: function(aInstall) {
callCallback(uri, USER_CANCELLED);
},
- onDownloadFailed: function buildNextInstall_onDownloadFailed(aInstall) {
+ onDownloadFailed: function(aInstall) {
if (aInstall.error == AddonManager.ERROR_CORRUPT_FILE)
callCallback(uri, CANT_READ_ARCHIVE);
else
callCallback(uri, DOWNLOAD_ERROR);
},
- onInstallFailed: function buildNextInstall_onInstallFailed(aInstall) {
+ onInstallFailed: function(aInstall) {
callCallback(uri, EXECUTION_ERROR);
},
- onInstallEnded: function buildNextInstall_onInstallEnded(aInstall, aStatus) {
+ onInstallEnded: function(aInstall, aStatus) {
callCallback(uri, SUCCESS);
}
});
@@ -144,7 +140,7 @@ amManager.prototype = {
return retval;
},
- notify: function AMC_notify(aTimer) {
+ notify: function(aTimer) {
AddonManagerPrivate.backgroundUpdateTimerHandler();
},
@@ -154,7 +150,7 @@ amManager.prototype = {
* Listens to requests from child processes for InstallTrigger
* activity, and sends back callbacks.
*/
- receiveMessage: function AMC_receiveMessage(aMessage) {
+ receiveMessage: function(aMessage) {
let payload = aMessage.data;
switch (aMessage.name) {
@@ -165,7 +161,7 @@ amManager.prototype = {
let callback = null;
if (payload.callbackID != -1) {
callback = {
- onInstallEnded: function ITP_callback(url, status) {
+ onInstallEnded: function(url, status) {
gParentMM.broadcastAsyncMessage(MSG_INSTALL_CALLBACK, {
callbackID: payload.callbackID,
url: url,
@@ -184,7 +180,7 @@ amManager.prototype = {
classID: Components.ID("{4399533d-08d1-458c-a87a-235f74451cfa}"),
_xpcom_factory: {
- createInstance: function AMC_createInstance(aOuter, aIid) {
+ createInstance: function(aOuter, aIid) {
if (aOuter != null)
throw Components.Exception("Component does not support aggregation",
Cr.NS_ERROR_NO_AGGREGATION);
diff --git a/toolkit/mozapps/extensions/amInstallTrigger.js b/toolkit/mozapps/extensions/amInstallTrigger.js
index a18fe84c4..5fc0e1717 100644
--- a/toolkit/mozapps/extensions/amInstallTrigger.js
+++ b/toolkit/mozapps/extensions/amInstallTrigger.js
@@ -203,7 +203,7 @@ InstallTrigger.prototype = {
return this.startSoftwareUpdate(url);
},
- _resolveURL: function (url) {
+ _resolveURL: function(url) {
return Services.io.newURI(url, null, this._url);
},
diff --git a/toolkit/mozapps/extensions/amWebInstallListener.js b/toolkit/mozapps/extensions/amWebInstallListener.js
index ac6e2495d..088f56640 100644
--- a/toolkit/mozapps/extensions/amWebInstallListener.js
+++ b/toolkit/mozapps/extensions/amWebInstallListener.js
@@ -89,7 +89,7 @@ Installer.prototype = {
/**
* Checks if all downloads are now complete and if so prompts to install.
*/
- checkAllDownloaded: function Installer_checkAllDownloaded() {
+ checkAllDownloaded: function() {
// Prevent re-entrancy caused by the confirmation dialog cancelling unwanted
// installs.
if (!this.isDownloading)
@@ -199,7 +199,7 @@ Installer.prototype = {
/**
* Checks if all installs are now complete and if so notifies observers.
*/
- checkAllInstalled: function Installer_checkAllInstalled() {
+ checkAllInstalled: function() {
var failed = [];
for (let install of this.downloads) {
@@ -225,32 +225,32 @@ Installer.prototype = {
this.installed = null;
},
- onDownloadCancelled: function Installer_onDownloadCancelled(aInstall) {
+ onDownloadCancelled: function(aInstall) {
aInstall.removeListener(this);
this.checkAllDownloaded();
},
- onDownloadFailed: function Installer_onDownloadFailed(aInstall) {
+ onDownloadFailed: function(aInstall) {
aInstall.removeListener(this);
this.checkAllDownloaded();
},
- onDownloadEnded: function Installer_onDownloadEnded(aInstall) {
+ onDownloadEnded: function(aInstall) {
this.checkAllDownloaded();
return false;
},
- onInstallCancelled: function Installer_onInstallCancelled(aInstall) {
+ onInstallCancelled: function(aInstall) {
aInstall.removeListener(this);
this.checkAllInstalled();
},
- onInstallFailed: function Installer_onInstallFailed(aInstall) {
+ onInstallFailed: function(aInstall) {
aInstall.removeListener(this);
this.checkAllInstalled();
},
- onInstallEnded: function Installer_onInstallEnded(aInstall) {
+ onInstallEnded: function(aInstall) {
aInstall.removeListener(this);
this.installed.push(aInstall);
@@ -272,7 +272,7 @@ extWebInstallListener.prototype = {
/**
* @see amIWebInstallListener.idl
*/
- onWebInstallDisabled: function extWebInstallListener_onWebInstallDisabled(aBrowser, aUri, aInstalls) {
+ onWebInstallDisabled: function(aBrowser, aUri, aInstalls) {
let info = {
browser: aBrowser,
originatingURI: aUri,
@@ -286,13 +286,13 @@ extWebInstallListener.prototype = {
/**
* @see amIWebInstallListener.idl
*/
- onWebInstallOriginBlocked: function extWebInstallListener_onWebInstallOriginBlocked(aBrowser, aUri, aInstalls) {
+ onWebInstallOriginBlocked: function(aBrowser, aUri, aInstalls) {
let info = {
browser: aBrowser,
originatingURI: aUri,
installs: aInstalls,
- install: function onWebInstallBlocked_install() {
+ install: function() {
},
QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallInfo])
@@ -305,13 +305,13 @@ extWebInstallListener.prototype = {
/**
* @see amIWebInstallListener.idl
*/
- onWebInstallBlocked: function extWebInstallListener_onWebInstallBlocked(aBrowser, aUri, aInstalls) {
+ onWebInstallBlocked: function(aBrowser, aUri, aInstalls) {
let info = {
browser: aBrowser,
originatingURI: aUri,
installs: aInstalls,
- install: function onWebInstallBlocked_install() {
+ install: function() {
new Installer(this.browser, this.originatingURI, this.installs);
},
@@ -325,7 +325,7 @@ extWebInstallListener.prototype = {
/**
* @see amIWebInstallListener.idl
*/
- onWebInstallRequested: function extWebInstallListener_onWebInstallRequested(aBrowser, aUri, aInstalls) {
+ onWebInstallRequested: function(aBrowser, aUri, aInstalls) {
new Installer(aBrowser, aUri, aInstalls);
// We start the installs ourself
diff --git a/toolkit/themes/osx/global/notification.css b/toolkit/themes/osx/global/notification.css
index 24b3d3920..6d22cf9c8 100644
--- a/toolkit/themes/osx/global/notification.css
+++ b/toolkit/themes/osx/global/notification.css
@@ -81,12 +81,12 @@ notificationbox[notificationside="bottom"] > notification {
Invert the close icon for @type=info since both are normally dark. It's unclear
why !important is necessary here so remove it if it's no longer needed.
*/
-notification[type="info"]:not([value="translation"]) .close-icon:not(:hover) {
+notification[type="info"] .close-icon:not(:hover) {
-moz-image-region: rect(0, 64px, 16px, 48px) !important;
}
@media (min-resolution: 2dppx) {
- notification[type="info"]:not([value="translation"]) .close-icon:not(:hover) {
+ notification[type="info"] .close-icon:not(:hover) {
-moz-image-region: rect(0, 128px, 32px, 96px) !important;
}
}
diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json
index 5fb645762..767b43db0 100644
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -224,7 +224,6 @@
"tokenserverclient.js": ["TokenServerClient", "TokenServerClientError", "TokenServerClientNetworkError", "TokenServerClientServerError"],
"ToolboxProcess.jsm": ["BrowserToolboxProcess"],
"tps.jsm": ["ACTIONS", "TPS"],
- "Translation.jsm": ["Translation", "TranslationTelemetry"],
"Traversal.jsm": ["TraversalRules", "TraversalHelper"],
"UpdateTelemetry.jsm": ["AUSTLMY"],
"userapi.js": ["UserAPI10Client"],