mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1015527 - Back/Forward navigation shouldn't break the Translation UI, r=felipe.
This commit is contained in:
parent
ea84d98c38
commit
c54bd196cb
@ -5311,8 +5311,8 @@ function setStyleDisabled(disabled) {
|
||||
|
||||
var LanguageDetectionListener = {
|
||||
init: function() {
|
||||
window.messageManager.addMessageListener("LanguageDetection:Result", msg => {
|
||||
Translation.languageDetected(msg.target, msg.data);
|
||||
window.messageManager.addMessageListener("Translation:DocumentState", msg => {
|
||||
Translation.documentStateReceived(msg.target, msg.data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -24,6 +24,11 @@ const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC
|
||||
|
||||
|
||||
this.Translation = {
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
|
||||
supportedTargetLanguages: ["en", "pl", "tr", "vi"],
|
||||
|
||||
@ -38,21 +43,33 @@ this.Translation = {
|
||||
return this._defaultTargetLanguage;
|
||||
},
|
||||
|
||||
languageDetected: function(aBrowser, aDetectedLanguage) {
|
||||
if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) == -1 ||
|
||||
aDetectedLanguage == this.defaultTargetLanguage)
|
||||
return;
|
||||
documentStateReceived: function(aBrowser, aData) {
|
||||
if (aData.state == this.STATE_OFFER) {
|
||||
if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1 ||
|
||||
aData.detectedLanguage == this.defaultTargetLanguage)
|
||||
return;
|
||||
|
||||
TranslationHealthReport.recordTranslationOpportunity(aDetectedLanguage);
|
||||
TranslationHealthReport.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 = aData.state;
|
||||
trUI.detectedLanguage = aData.detectedLanguage;
|
||||
trUI.translatedFrom = aData.translatedFrom;
|
||||
trUI.translatedTo = aData.translatedTo;
|
||||
trUI.originalShown = aData.originalShown;
|
||||
|
||||
aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
|
||||
trUI.showURLBarIcon();
|
||||
|
||||
if (trUI.shouldShowInfoBar(aBrowser.currentURI))
|
||||
trUI.showTranslationInfoBar();
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,7 +79,6 @@ this.Translation = {
|
||||
* the infobar are:
|
||||
* - detectedLanguage, code of the language detected on the web page.
|
||||
* - state, the state in which the infobar should be displayed
|
||||
* - STATE_{OFFER,TRANSLATING,TRANSLATED,ERROR} constants.
|
||||
* - translatedFrom, if already translated, source language code.
|
||||
* - translatedTo, if already translated, target language code.
|
||||
* - translate, method starting the translation of the current page.
|
||||
@ -78,20 +94,15 @@ function TranslationUI(aBrowser) {
|
||||
}
|
||||
|
||||
TranslationUI.prototype = {
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
translate: function(aFrom, aTo) {
|
||||
if (aFrom == aTo ||
|
||||
(this.state == this.STATE_TRANSLATED &&
|
||||
(this.state == Translation.STATE_TRANSLATED &&
|
||||
this.translatedFrom == aFrom && this.translatedTo == aTo)) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.state = Translation.STATE_TRANSLATING;
|
||||
this.translatedFrom = aFrom;
|
||||
this.translatedTo = aTo;
|
||||
|
||||
@ -101,10 +112,10 @@ TranslationUI.prototype = {
|
||||
);
|
||||
},
|
||||
|
||||
showURLBarIcon: function(aTranslated) {
|
||||
showURLBarIcon: function() {
|
||||
let chromeWin = this.browser.ownerGlobal;
|
||||
let PopupNotifications = chromeWin.PopupNotifications;
|
||||
let removeId = aTranslated ? "translate" : "translated";
|
||||
let removeId = this.originalShown ? "translated" : "translate";
|
||||
let notification =
|
||||
PopupNotifications.getNotification(removeId, this.browser);
|
||||
if (notification)
|
||||
@ -121,7 +132,7 @@ TranslationUI.prototype = {
|
||||
return true;
|
||||
};
|
||||
|
||||
let addId = aTranslated ? "translated" : "translate";
|
||||
let addId = this.originalShown ? "translate" : "translated";
|
||||
PopupNotifications.show(this.browser, addId, null,
|
||||
addId + "-notification-icon", null, null,
|
||||
{dismissed: true, eventCallback: callback});
|
||||
@ -138,14 +149,14 @@ TranslationUI.prototype = {
|
||||
|
||||
originalShown: true,
|
||||
showOriginalContent: function() {
|
||||
this.showURLBarIcon();
|
||||
this.originalShown = true;
|
||||
this.showURLBarIcon();
|
||||
this.browser.messageManager.sendAsyncMessage("Translation:ShowOriginal");
|
||||
},
|
||||
|
||||
showTranslatedContent: function() {
|
||||
this.showURLBarIcon(true);
|
||||
this.originalShown = false;
|
||||
this.showURLBarIcon();
|
||||
this.browser.messageManager.sendAsyncMessage("Translation:ShowTranslation");
|
||||
},
|
||||
|
||||
@ -159,11 +170,11 @@ TranslationUI.prototype = {
|
||||
return notif;
|
||||
},
|
||||
|
||||
shouldShowInfoBar: function(aURI, aDetectedLanguage) {
|
||||
shouldShowInfoBar: function(aURI) {
|
||||
// Check if we should never show the infobar for this language.
|
||||
let neverForLangs =
|
||||
Services.prefs.getCharPref("browser.translation.neverForLanguages");
|
||||
if (neverForLangs.split(",").indexOf(aDetectedLanguage) != -1)
|
||||
if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1)
|
||||
return false;
|
||||
|
||||
// or if we should never show the infobar for this domain.
|
||||
@ -182,7 +193,7 @@ TranslationUI.prototype = {
|
||||
|
||||
this.showURLBarIcon();
|
||||
|
||||
if (!this.shouldShowInfoBar(this.browser.currentURI, aDetectedLanguage))
|
||||
if (!this.shouldShowInfoBar(this.browser.currentURI))
|
||||
return null;
|
||||
|
||||
return this.showTranslationInfoBar();
|
||||
@ -192,11 +203,11 @@ TranslationUI.prototype = {
|
||||
switch (msg.name) {
|
||||
case "Translation:Finished":
|
||||
if (msg.data.success) {
|
||||
this.state = this.STATE_TRANSLATED;
|
||||
this.showURLBarIcon(true);
|
||||
this.state = Translation.STATE_TRANSLATED;
|
||||
this.originalShown = false;
|
||||
this.showURLBarIcon();
|
||||
} else {
|
||||
this.state = this.STATE_ERROR;
|
||||
this.state = Translation.STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -12,11 +12,17 @@ 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);
|
||||
@ -24,6 +30,35 @@ this.TranslationContentHandler = function(global, docShell) {
|
||||
}
|
||||
|
||||
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 ||
|
||||
@ -35,10 +70,14 @@ TranslationContentHandler.prototype = {
|
||||
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(this.global.content.document, "text/plain", encoder.SkipInvisibleContent);
|
||||
encoder.init(content.document, "text/plain", encoder.SkipInvisibleContent);
|
||||
let string = encoder.encodeToStringWithMaxLength(60 * 1024);
|
||||
|
||||
// Language detection isn't reliable on very short strings.
|
||||
@ -46,8 +85,17 @@ TranslationContentHandler.prototype = {
|
||||
return;
|
||||
|
||||
LanguageDetector.detectLanguage(string).then(result => {
|
||||
if (result.confident)
|
||||
this.global.sendAsyncMessage("LanguageDetection:Result", result.language);
|
||||
if (!result.confident)
|
||||
return;
|
||||
|
||||
content.detectedLanguage = result.language;
|
||||
|
||||
let data = {
|
||||
state: STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: result.language
|
||||
};
|
||||
this.global.sendAsyncMessage("Translation:DocumentState", data);
|
||||
});
|
||||
},
|
||||
|
||||
@ -78,12 +126,17 @@ TranslationContentHandler.prototype = {
|
||||
msg.data.to);
|
||||
|
||||
this.global.content.translationDocument = translationDocument;
|
||||
translationDocument.translatedFrom = msg.data.from;
|
||||
translationDocument.translatedTo = msg.data.to;
|
||||
translationDocument.translationError = false;
|
||||
|
||||
bingTranslation.translate().then(
|
||||
success => {
|
||||
this.global.sendAsyncMessage("Translation:Finished", {success: true});
|
||||
translationDocument.showTranslation();
|
||||
},
|
||||
error => {
|
||||
translationDocument.translationError = true;
|
||||
this.global.sendAsyncMessage("Translation:Finished", {success: false});
|
||||
}
|
||||
);
|
||||
|
@ -31,6 +31,11 @@ this.TranslationDocument = function(document) {
|
||||
};
|
||||
|
||||
this.TranslationDocument.prototype = {
|
||||
translatedFrom: "",
|
||||
translatedTo: "",
|
||||
translationError: false,
|
||||
originalShown: true,
|
||||
|
||||
/**
|
||||
* Initializes the object and populates
|
||||
* the roots lists.
|
||||
@ -185,6 +190,7 @@ this.TranslationDocument.prototype = {
|
||||
* content.
|
||||
*/
|
||||
showTranslation: function() {
|
||||
this.originalShown = false;
|
||||
this._swapDocumentContent("translation");
|
||||
},
|
||||
|
||||
@ -193,6 +199,7 @@ this.TranslationDocument.prototype = {
|
||||
* content.
|
||||
*/
|
||||
showOriginal: function() {
|
||||
this.originalShown = true;
|
||||
this._swapDocumentContent("original");
|
||||
},
|
||||
|
||||
|
@ -104,7 +104,10 @@ let gTests = [
|
||||
desc: "never for language",
|
||||
run: function* checkNeverForLanguage() {
|
||||
// Show the infobar for example.com and fr.
|
||||
Translation.languageDetected(gBrowser.selectedBrowser, "fr");
|
||||
Translation.documentStateReceived(gBrowser.selectedBrowser,
|
||||
{state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: "fr"});
|
||||
let notif = getInfoBar();
|
||||
ok(notif, "the infobar is visible");
|
||||
let ui = gBrowser.selectedBrowser.translationUI;
|
||||
@ -150,7 +153,10 @@ let gTests = [
|
||||
desc: "never for site",
|
||||
run: function* checkNeverForSite() {
|
||||
// Show the infobar for example.com and fr.
|
||||
Translation.languageDetected(gBrowser.selectedBrowser, "fr");
|
||||
Translation.documentStateReceived(gBrowser.selectedBrowser,
|
||||
{state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: "fr"});
|
||||
let notif = getInfoBar();
|
||||
ok(notif, "the infobar is visible");
|
||||
let ui = gBrowser.selectedBrowser.translationUI;
|
||||
|
@ -34,7 +34,7 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
|
||||
var TranslationStub = {
|
||||
translate: function(aFrom, aTo) {
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.state = Translation.STATE_TRANSLATING;
|
||||
this.translatedFrom = aFrom;
|
||||
this.translatedTo = aTo;
|
||||
},
|
||||
@ -45,20 +45,22 @@ var TranslationStub = {
|
||||
},
|
||||
|
||||
failTranslation: function() {
|
||||
this.state = this.STATE_ERROR;
|
||||
this.state = Translation.STATE_ERROR;
|
||||
this._reset();
|
||||
},
|
||||
|
||||
finishTranslation: function() {
|
||||
this.showTranslatedContent();
|
||||
this.state = this.STATE_TRANSLATED;
|
||||
this.state = Translation.STATE_TRANSLATED;
|
||||
this._reset();
|
||||
}
|
||||
};
|
||||
|
||||
function showTranslationUI(aDetectedLanguage) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
Translation.languageDetected(browser, aDetectedLanguage);
|
||||
Translation.documentStateReceived(browser, {state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: aDetectedLanguage});
|
||||
let ui = browser.translationUI;
|
||||
for (let name of ["translate", "_reset", "failTranslation", "finishTranslation"])
|
||||
ui[name] = TranslationStub[name];
|
||||
@ -100,13 +102,13 @@ function checkURLBarIcon(aExpectTranslated = false) {
|
||||
function run_tests(aFinishCallback) {
|
||||
info("Show an info bar saying the current page is in French");
|
||||
let notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif.state, Translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the 'Translate' button");
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "fr", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
|
||||
@ -114,12 +116,12 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Make the translation fail and check we are in the error state.");
|
||||
notif.translation.failTranslation();
|
||||
is(notif.state, notif.translation.STATE_ERROR, "infobar in the error state");
|
||||
is(notif.state, Translation.STATE_ERROR, "infobar in the error state");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the try again button");
|
||||
notif._getAnonElt("tryAgain").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "fr", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
|
||||
@ -127,7 +129,7 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Make the translation succeed and check we are in the 'translated' state.");
|
||||
notif.translation.finishTranslation();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATED, "infobar in the translated state");
|
||||
is(notif.state, Translation.STATE_TRANSLATED, "infobar in the translated state");
|
||||
checkURLBarIcon(true);
|
||||
|
||||
info("Test 'Show original' / 'Show Translation' buttons.");
|
||||
@ -153,7 +155,7 @@ function run_tests(aFinishCallback) {
|
||||
let from = notif._getAnonElt("fromLanguage");
|
||||
from.value = "es";
|
||||
from.doCommand();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "es", "from language correct");
|
||||
is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "to language correct");
|
||||
@ -167,7 +169,7 @@ function run_tests(aFinishCallback) {
|
||||
let to = notif._getAnonElt("toLanguage");
|
||||
to.value = "pl";
|
||||
to.doCommand();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "es", "from language correct");
|
||||
is(notif.translation.translatedTo, "pl", "to language correct");
|
||||
@ -180,12 +182,12 @@ function run_tests(aFinishCallback) {
|
||||
|
||||
info("Reopen the info bar to check that it's possible to override the detected language.");
|
||||
notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif.state, Translation.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
// Change the language and click 'Translate'
|
||||
notif._getAnonElt("detectedLanguage").value = "ja";
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
is(notif.state, Translation.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
|
||||
is(notif.translation.translatedFrom, "ja", "from language correct");
|
||||
notif.close();
|
||||
|
@ -127,7 +127,7 @@
|
||||
|
||||
let stateName;
|
||||
for (let name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
|
||||
if (this.translation["STATE_" + name] == val) {
|
||||
if (Translation["STATE_" + name] == val) {
|
||||
stateName = name.toLowerCase();
|
||||
break;
|
||||
}
|
||||
@ -188,7 +188,7 @@
|
||||
<method name="translate">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.state == this.translation.STATE_OFFER) {
|
||||
if (this.state == Translation.STATE_OFFER) {
|
||||
this._getAnonElt("fromLanguage").value =
|
||||
this._getAnonElt("detectedLanguage").value;
|
||||
this._getAnonElt("toLanguage").value =
|
||||
@ -235,7 +235,7 @@
|
||||
<![CDATA[
|
||||
// Get the source language name.
|
||||
let lang;
|
||||
if (this.state == this.translation.STATE_OFFER)
|
||||
if (this.state == Translation.STATE_OFFER)
|
||||
lang = this._getAnonElt("detectedLanguage").value;
|
||||
else
|
||||
lang = this._getAnonElt("fromLanguage").value;
|
||||
|
Loading…
Reference in New Issue
Block a user