mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to mozilla-inbound
This commit is contained in:
commit
3a7fcff936
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
|
||||
@ -131,6 +131,6 @@
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f8e49f3837230cfbb2d6fbcf239d1f25b57b39a7"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="72e3a520e3c700839f07ba0113fd527b923c3330"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="3b002889eca9e47f77ef10af44619c8c56df069b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="6a7ada569fd37c09ed4bbee6eb78cea5b467b229"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||
</manifest>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="52c909ccead537f8f9dbf634f3e6639078a8b0bd">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "e1fc74c2ae523e7cce5be01e1a29b43defaec124",
|
||||
"revision": "35bd8bfb0ee9dce0eb9dcfdbb43587517b655121",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
|
||||
@ -127,7 +127,7 @@
|
||||
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="3b002889eca9e47f77ef10af44619c8c56df069b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="6a7ada569fd37c09ed4bbee6eb78cea5b467b229"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7591e9dc782ac2e97d63a96f9deb71c7b3588328"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dadf0e60a6421f5b57ee9fc536c6617212805c19"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
@ -1425,6 +1425,8 @@ pref("browser.cache.auto_delete_cache_version", 1);
|
||||
// -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);
|
||||
|
||||
// Telemetry experiments settings.
|
||||
pref("experiments.enabled", false);
|
||||
pref("experiments.manifest.fetchIntervalSeconds", 86400);
|
||||
|
@ -147,6 +147,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "gCustomizationTabPreloader",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Translation",
|
||||
"resource:///modules/translation/Translation.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SitePermissions",
|
||||
"resource:///modules/SitePermissions.jsm");
|
||||
|
||||
@ -1033,6 +1036,7 @@ var gBrowserInit = {
|
||||
gFormSubmitObserver.init();
|
||||
gRemoteTabsUI.init();
|
||||
gPageStyleMenu.init();
|
||||
LanguageDetectionListener.init();
|
||||
|
||||
// Initialize the full zoom setting.
|
||||
// We do this before the session restore service gets initialized so we can
|
||||
@ -4464,9 +4468,6 @@ var TabsInTitlebar = {
|
||||
let titlebar = $("titlebar");
|
||||
let titlebarContent = $("titlebar-content");
|
||||
let menubar = $("toolbar-menubar");
|
||||
#ifdef XP_MACOSX
|
||||
let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
|
||||
#endif
|
||||
|
||||
if (allowed) {
|
||||
// We set the tabsintitlebar attribute first so that our CSS for
|
||||
@ -4484,6 +4485,7 @@ var TabsInTitlebar = {
|
||||
let captionButtonsBoxWidth = rect($("titlebar-buttonbox-container")).width;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
|
||||
// No need to look up the menubar stuff on OS X:
|
||||
let menuHeight = 0;
|
||||
let fullMenuHeight = 0;
|
||||
@ -4558,6 +4560,9 @@ var TabsInTitlebar = {
|
||||
|
||||
|
||||
// Finally, size the placeholders:
|
||||
#ifdef XP_MACOSX
|
||||
this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
|
||||
#endif
|
||||
this._sizePlaceholder("caption-buttons", captionButtonsBoxWidth);
|
||||
|
||||
if (!this._draghandles) {
|
||||
@ -4579,16 +4584,16 @@ var TabsInTitlebar = {
|
||||
document.documentElement.removeAttribute("tabsintitlebar");
|
||||
updateTitlebarDisplay();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
|
||||
this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
|
||||
#endif
|
||||
// Reset the margins and padding that might have been modified:
|
||||
titlebarContent.style.marginTop = "";
|
||||
titlebarContent.style.marginBottom = "";
|
||||
titlebar.style.marginBottom = "";
|
||||
menubar.style.paddingBottom = "";
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
|
||||
#endif
|
||||
},
|
||||
|
||||
_sizePlaceholder: function (type, width) {
|
||||
@ -5342,6 +5347,15 @@ function setStyleDisabled(disabled) {
|
||||
}
|
||||
|
||||
|
||||
var LanguageDetectionListener = {
|
||||
init: function() {
|
||||
window.messageManager.addMessageListener("LanguageDetection:Result", msg => {
|
||||
Translation.languageDetected(msg.target, msg.data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var BrowserOffline = {
|
||||
_inited: false,
|
||||
|
||||
|
@ -12,6 +12,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
|
||||
"resource:///modules/ContentLinkHandler.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
|
||||
"resource:///modules/translation/LanguageDetector.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
|
||||
"resource://gre/modules/LoginManagerContent.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
|
||||
@ -387,3 +389,49 @@ let PageStyleHandler = {
|
||||
},
|
||||
};
|
||||
PageStyleHandler.init();
|
||||
|
||||
let TranslationHandler = {
|
||||
init: function() {
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
},
|
||||
|
||||
/* nsIWebProgressListener implementation */
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (!aWebProgress.isTopLevel ||
|
||||
!(aStateFlags & Ci.nsIWebProgressListener.STATE_STOP))
|
||||
return;
|
||||
|
||||
let url = aRequest.name;
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://"))
|
||||
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 => {
|
||||
if (result.confident)
|
||||
sendAsyncMessage("LanguageDetection:Result", result.language);
|
||||
});
|
||||
},
|
||||
|
||||
// Unused methods.
|
||||
onProgressChange: function() {},
|
||||
onLocationChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.translation.detectLanguage"))
|
||||
TranslationHandler.init();
|
||||
|
@ -11,42 +11,11 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
|
||||
"resource:///modules/translation/LanguageDetector.jsm");
|
||||
|
||||
/* Create an object keeping 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:
|
||||
* - supportedSourceLanguages, array of supported source language codes
|
||||
* - supportedTargetLanguages, array of supported target language codes
|
||||
* - detectedLanguage, code of the language detected on the web page.
|
||||
* - defaultTargetLanguage, code of the language to use by default for
|
||||
* translation.
|
||||
* - 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.
|
||||
* - 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.
|
||||
*/
|
||||
this.Translation = function(aBrowser) {
|
||||
this.browser = aBrowser;
|
||||
};
|
||||
|
||||
this.Translation.prototype = {
|
||||
this.Translation = {
|
||||
supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
|
||||
supportedTargetLanguages: ["en", "pl", "tr", "vi"],
|
||||
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
_defaultTargetLanguage: "",
|
||||
get defaultTargetLanguage() {
|
||||
if (!this._defaultTargetLanguage) {
|
||||
@ -58,6 +27,43 @@ this.Translation.prototype = {
|
||||
return this._defaultTargetLanguage;
|
||||
},
|
||||
|
||||
languageDetected: function(aBrowser, aDetectedLanguage) {
|
||||
if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) != -1 &&
|
||||
aDetectedLanguage != this.defaultTargetLanguage) {
|
||||
if (!aBrowser.translationUI)
|
||||
aBrowser.translationUI = new TranslationUI(aBrowser);
|
||||
|
||||
aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* 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
|
||||
* - 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.
|
||||
* - 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 = {
|
||||
STATE_OFFER: 0,
|
||||
STATE_TRANSLATING: 1,
|
||||
STATE_TRANSLATED: 2,
|
||||
STATE_ERROR: 3,
|
||||
|
||||
get doc() this.browser.contentDocument,
|
||||
|
||||
translate: function(aFrom, aTo) {
|
||||
|
@ -29,8 +29,6 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
}
|
||||
|
||||
var TranslationStub = {
|
||||
__proto__: Translation.prototype,
|
||||
|
||||
translate: function(aFrom, aTo) {
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.translatedFrom = aFrom;
|
||||
@ -54,6 +52,14 @@ var TranslationStub = {
|
||||
}
|
||||
};
|
||||
|
||||
function showTranslationUI(aDetectedLanguage) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
Translation.languageDetected(browser, aDetectedLanguage);
|
||||
let ui = browser.translationUI;
|
||||
for (let name of ["translate", "_reset", "failTranslation", "finishTranslation"])
|
||||
ui[name] = TranslationStub[name];
|
||||
return ui.notificationBox.getNotificationWithValue("translation");
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -83,35 +89,35 @@ function checkURLBarIcon(aExpectTranslated = false) {
|
||||
|
||||
function run_tests(aFinishCallback) {
|
||||
info("Show an info bar saying the current page is in French");
|
||||
let notif = TranslationStub.showTranslationUI("fr");
|
||||
is(notif.state, TranslationStub.STATE_OFFER, "the infobar is offering translation");
|
||||
let notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.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, TranslationStub.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
|
||||
is(TranslationStub.translatedFrom, "fr", "from language correct");
|
||||
is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "from language correct");
|
||||
is(notif.state, notif.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");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Make the translation fail and check we are in the error state.");
|
||||
TranslationStub.failTranslation();
|
||||
is(notif.state, TranslationStub.STATE_ERROR, "infobar in the error state");
|
||||
notif.translation.failTranslation();
|
||||
is(notif.state, notif.translation.STATE_ERROR, "infobar in the error state");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the try again button");
|
||||
notif._getAnonElt("tryAgain").click();
|
||||
is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
|
||||
is(TranslationStub.translatedFrom, "fr", "from language correct");
|
||||
is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "from language correct");
|
||||
is(notif.state, notif.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");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Make the translation succeed and check we are in the 'translated' state.");
|
||||
TranslationStub.finishTranslation();
|
||||
is(notif.state, TranslationStub.STATE_TRANSLATED, "infobar in the translated state");
|
||||
notif.translation.finishTranslation();
|
||||
is(notif.state, notif.translation.STATE_TRANSLATED, "infobar in the translated state");
|
||||
checkURLBarIcon(true);
|
||||
|
||||
info("Test 'Show original' / 'Show Translation' buttons.");
|
||||
@ -137,45 +143,45 @@ function run_tests(aFinishCallback) {
|
||||
let from = notif._getAnonElt("fromLanguage");
|
||||
from.value = "es";
|
||||
from.doCommand();
|
||||
is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
|
||||
is(TranslationStub.translatedFrom, "es", "from language correct");
|
||||
is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "to language correct");
|
||||
is(notif.state, notif.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");
|
||||
// We want to show the 'translated' icon while re-translating,
|
||||
// because we are still displaying the previous translation.
|
||||
checkURLBarIcon(true);
|
||||
TranslationStub.finishTranslation();
|
||||
notif.translation.finishTranslation();
|
||||
checkURLBarIcon(true);
|
||||
|
||||
info("Check that changing the target language causes a re-translation");
|
||||
let to = notif._getAnonElt("toLanguage");
|
||||
to.value = "pl";
|
||||
to.doCommand();
|
||||
is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
|
||||
is(TranslationStub.translatedFrom, "es", "from language correct");
|
||||
is(TranslationStub.translatedTo, "pl", "to language correct");
|
||||
is(notif.state, notif.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");
|
||||
checkURLBarIcon(true);
|
||||
TranslationStub.finishTranslation();
|
||||
notif.translation.finishTranslation();
|
||||
checkURLBarIcon(true);
|
||||
|
||||
// Cleanup.
|
||||
notif.close();
|
||||
|
||||
info("Reopen the info bar to check that it's possible to override the detected language.");
|
||||
notif = TranslationStub.showTranslationUI("fr");
|
||||
is(notif.state, TranslationStub.STATE_OFFER, "the infobar is offering translation");
|
||||
notif = showTranslationUI("fr");
|
||||
is(notif.state, notif.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, TranslationStub.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
|
||||
is(TranslationStub.translatedFrom, "ja", "from language correct");
|
||||
is(notif.state, notif.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();
|
||||
|
||||
info("Reopen to check the 'Not Now' button closes the notification.");
|
||||
notif = TranslationStub.showTranslationUI("fr");
|
||||
notif = showTranslationUI("fr");
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
ok(!!notificationBox.getNotificationWithValue("translation"), "there's a 'translate' notification");
|
||||
notif._getAnonElt("notNow").click();
|
||||
|
@ -102,7 +102,7 @@
|
||||
// Fill the lists of supported source languages.
|
||||
let detectedLanguage = this._getAnonElt("detectedLanguage");
|
||||
let fromLanguage = this._getAnonElt("fromLanguage");
|
||||
for (let code of this.translation.supportedSourceLanguages) {
|
||||
for (let code of Translation.supportedSourceLanguages) {
|
||||
let name = bundle.GetStringFromName(code);
|
||||
detectedLanguage.appendItem(name, code);
|
||||
fromLanguage.appendItem(name, code);
|
||||
@ -115,7 +115,7 @@
|
||||
|
||||
// Fill the list of supporter target languages.
|
||||
let toLanguage = this._getAnonElt("toLanguage");
|
||||
for (let code of this.translation.supportedTargetLanguages)
|
||||
for (let code of Translation.supportedTargetLanguages)
|
||||
toLanguage.appendItem(bundle.GetStringFromName(code), code);
|
||||
|
||||
if (aTranslation.translatedTo)
|
||||
@ -143,7 +143,7 @@
|
||||
this._getAnonElt("fromLanguage").value =
|
||||
this._getAnonElt("detectedLanguage").value;
|
||||
this._getAnonElt("toLanguage").value =
|
||||
this.translation.defaultTargetLanguage;
|
||||
Translation.defaultTargetLanguage;
|
||||
}
|
||||
|
||||
this._handleButtonHiding(false);
|
||||
|
@ -252,6 +252,10 @@ Experiments.Policy = function () {
|
||||
this._log = Log.repository.getLoggerWithMessagePrefix(
|
||||
"Browser.Experiments.Policy",
|
||||
"Policy #" + gPolicyCounter++ + "::");
|
||||
|
||||
// Set to true to ignore hash verification on downloaded XPIs. This should
|
||||
// not be used outside of testing.
|
||||
this.ignoreHashes = false;
|
||||
};
|
||||
|
||||
Experiments.Policy.prototype = {
|
||||
@ -372,19 +376,24 @@ Experiments.Experiments.prototype = {
|
||||
AsyncShutdown.profileBeforeChange.addBlocker("Experiments.jsm shutdown",
|
||||
this.uninit.bind(this));
|
||||
|
||||
this._startWatchingAddons();
|
||||
this._registerWithAddonManager();
|
||||
|
||||
this._loadTask = Task.spawn(this._loadFromCache.bind(this));
|
||||
let deferred = Promise.defer();
|
||||
|
||||
this._loadTask = this._loadFromCache();
|
||||
this._loadTask.then(
|
||||
() => {
|
||||
this._log.trace("_loadTask finished ok");
|
||||
this._loadTask = null;
|
||||
this._run();
|
||||
this._run().then(deferred.resolve, deferred.reject);
|
||||
},
|
||||
(e) => {
|
||||
this._log.error("_loadFromCache caught error: " + e);
|
||||
deferred.reject(e);
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -402,7 +411,7 @@ Experiments.Experiments.prototype = {
|
||||
yield this._loadTask;
|
||||
|
||||
if (!this._shutdown) {
|
||||
this._stopWatchingAddons();
|
||||
this._unregisterWithAddonManager();
|
||||
|
||||
gPrefs.ignore(PREF_LOGGING, configureLogging);
|
||||
gPrefs.ignore(PREF_MANIFEST_URI, this.updateManifest, this);
|
||||
@ -423,12 +432,14 @@ Experiments.Experiments.prototype = {
|
||||
this._log.info("Completed uninitialization.");
|
||||
}),
|
||||
|
||||
_startWatchingAddons: function () {
|
||||
_registerWithAddonManager: function () {
|
||||
this._log.trace("Registering instance with Addon Manager.");
|
||||
|
||||
AddonManager.addAddonListener(this);
|
||||
AddonManager.addInstallListener(this);
|
||||
},
|
||||
|
||||
_stopWatchingAddons: function () {
|
||||
_unregisterWithAddonManager: function () {
|
||||
AddonManager.removeInstallListener(this);
|
||||
AddonManager.removeAddonListener(this);
|
||||
},
|
||||
@ -812,7 +823,7 @@ Experiments.Experiments.prototype = {
|
||||
/*
|
||||
* Task function, load the cached experiments manifest file from disk.
|
||||
*/
|
||||
_loadFromCache: function*() {
|
||||
_loadFromCache: Task.async(function* () {
|
||||
this._log.trace("_loadFromCache");
|
||||
let path = this._cacheFilePath;
|
||||
try {
|
||||
@ -822,7 +833,7 @@ Experiments.Experiments.prototype = {
|
||||
// No cached manifest yet.
|
||||
this._experiments = new Map();
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
_populateFromCache: function (data) {
|
||||
this._log.trace("populateFromCache() - data: " + JSON.stringify(data));
|
||||
@ -1498,8 +1509,9 @@ Experiments.ExperimentEntry.prototype = {
|
||||
_installAddon: function* () {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let install = yield addonInstallForURL(this._manifestData.xpiURL,
|
||||
this._manifestData.xpiHash);
|
||||
let hash = this._policy.ignoreHashes ? null : this._manifestData.xpiHash;
|
||||
|
||||
let install = yield addonInstallForURL(this._manifestData.xpiURL, hash);
|
||||
gActiveInstallURLs.add(install.sourceURI.spec);
|
||||
|
||||
let failureHandler = (install, handler) => {
|
||||
|
@ -140,4 +140,23 @@ add_task(function* test_startStop() {
|
||||
Assert.equal(experiment.enabled, false, "Experiment should be disabled.");
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 0, "Experiment add-on is uninstalled.");
|
||||
|
||||
// Ensure hash validation works.
|
||||
// We set an incorrect hash and expect the install to fail.
|
||||
experiment._manifestData.xpiHash = "sha1:41014dcc66b4dcedcd973491a1530a32f0517d8a";
|
||||
let errored = false;
|
||||
try {
|
||||
yield experiment.start();
|
||||
} catch (ex) {
|
||||
errored = true;
|
||||
}
|
||||
Assert.ok(experiment._failedStart, "Experiment failed to start.");
|
||||
Assert.ok(errored, "start() threw an exception.");
|
||||
|
||||
// Make sure "ignore hashes" mode works.
|
||||
gPolicy.ignoreHashes = true;
|
||||
let changes = yield experiment.start();
|
||||
Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL);
|
||||
yield experiment.stop();
|
||||
gPolicy.ignoreHashes = false;
|
||||
});
|
||||
|
@ -1366,9 +1366,9 @@ add_task(function* testUnknownExperimentsUninstalled() {
|
||||
Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are present.");
|
||||
|
||||
// Simulate us not listening.
|
||||
experiments._stopWatchingAddons();
|
||||
experiments._unregisterWithAddonManager();
|
||||
yield AddonTestUtils.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1);
|
||||
experiments._startWatchingAddons();
|
||||
experiments._registerWithAddonManager();
|
||||
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 1, "Experiment 1 installed via AddonManager");
|
||||
@ -1452,9 +1452,9 @@ add_task(function* testEnabledAfterRestart() {
|
||||
Assert.ok(addons[0].isActive, "That experiment is active.");
|
||||
|
||||
dump("Restarting Addon Manager\n");
|
||||
experiments._stopWatchingAddons();
|
||||
experiments._unregisterWithAddonManager();
|
||||
restartManager();
|
||||
experiments._startWatchingAddons();
|
||||
experiments._registerWithAddonManager();
|
||||
|
||||
addons = yield getExperimentAddons();
|
||||
Assert.equal(addons.length, 1, "The experiment is still there after restart.");
|
||||
|
@ -55,7 +55,7 @@
|
||||
}
|
||||
@keyframes moveY {
|
||||
/* These values are adjusted for the padding and height of the panel. */
|
||||
from { margin-top: -6px; } to { margin-top: 58px; }
|
||||
from { margin-top: -.5em; } to { margin-top: calc(64px - .5em); }
|
||||
}
|
||||
|
||||
#PanelUI-button {
|
||||
|
@ -35,7 +35,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports
|
||||
nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids);
|
||||
};
|
||||
|
||||
[scriptable, uuid(7222bdf1-c2b9-41f1-a40a-a3d65283a95b)]
|
||||
[scriptable, uuid(1158bd7e-a08b-4ff6-9417-6f99144cfccc)]
|
||||
interface nsIDocumentEncoder : nsISupports
|
||||
{
|
||||
// Output methods flag bits. There are a frightening number of these,
|
||||
@ -329,6 +329,21 @@ interface nsIDocumentEncoder : nsISupports
|
||||
AString encodeToStringWithContext( out AString aContextString,
|
||||
out AString aInfoString);
|
||||
|
||||
/**
|
||||
* Encode the document into a string of limited size.
|
||||
* @param aMaxLength After aMaxLength characters, the encoder will stop
|
||||
* encoding new data.
|
||||
* Only values > 0 will be considered.
|
||||
* The returned string may be slightly larger than
|
||||
* aMaxLength because some serializers (eg. HTML)
|
||||
* may need to close some tags after they stop
|
||||
* encoding new data, or finish a line (72 columns
|
||||
* by default for the plain text serializer).
|
||||
*
|
||||
* @return The document encoded into a string.
|
||||
*/
|
||||
AString encodeToStringWithMaxLength(in unsigned long aMaxLength);
|
||||
|
||||
/**
|
||||
* Set the fixup object associated with node persistence.
|
||||
* @param aFixup The fixup object.
|
||||
|
@ -81,7 +81,8 @@ protected:
|
||||
nsINode* aOriginalNode = nullptr);
|
||||
nsresult SerializeToStringRecursive(nsINode* aNode,
|
||||
nsAString& aStr,
|
||||
bool aDontSerializeRoot);
|
||||
bool aDontSerializeRoot,
|
||||
uint32_t aMaxLength = 0);
|
||||
nsresult SerializeNodeEnd(nsINode* aNode, nsAString& aStr);
|
||||
// This serializes the content of aNode.
|
||||
nsresult SerializeToStringIterative(nsINode* aNode,
|
||||
@ -450,8 +451,13 @@ nsDocumentEncoder::SerializeNodeEnd(nsINode* aNode,
|
||||
nsresult
|
||||
nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
||||
nsAString& aStr,
|
||||
bool aDontSerializeRoot)
|
||||
bool aDontSerializeRoot,
|
||||
uint32_t aMaxLength)
|
||||
{
|
||||
if (aMaxLength > 0 && aStr.Length() >= aMaxLength) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!IsVisibleNode(aNode))
|
||||
return NS_OK;
|
||||
|
||||
@ -487,7 +493,12 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
||||
}
|
||||
|
||||
if (!aDontSerializeRoot) {
|
||||
rv = SerializeNodeStart(maybeFixedNode, 0, -1, aStr, aNode);
|
||||
int32_t endOffset = -1;
|
||||
if (aMaxLength > 0) {
|
||||
MOZ_ASSERT(aMaxLength >= aStr.Length());
|
||||
endOffset = aMaxLength - aStr.Length();
|
||||
}
|
||||
rv = SerializeNodeStart(maybeFixedNode, 0, endOffset, aStr, aNode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -496,7 +507,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
||||
for (nsINode* child = nsNodeUtils::GetFirstChildOfTemplateOrNode(node);
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
rv = SerializeToStringRecursive(child, aStr, false);
|
||||
rv = SerializeToStringRecursive(child, aStr, false, aMaxLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1016,6 +1027,13 @@ nsDocumentEncoder::SerializeRangeToString(nsRange *aRange,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
|
||||
{
|
||||
return EncodeToStringWithMaxLength(0, aOutputString);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
|
||||
nsAString& aOutputString)
|
||||
{
|
||||
if (!mDocument)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -1146,7 +1164,7 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
|
||||
rv = mSerializer->AppendDocumentStart(mDocument, output);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = SerializeToStringRecursive(mDocument, output, false);
|
||||
rv = SerializeToStringRecursive(mDocument, output, false, aMaxLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,8 @@ nsPlainTextSerializer::AppendText(nsIContent* aText,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int32_t endoffset = (aEndOffset == -1) ? frag->GetLength() : aEndOffset;
|
||||
int32_t fragLength = frag->GetLength();
|
||||
int32_t endoffset = (aEndOffset == -1) ? fragLength : std::min(aEndOffset, fragLength);
|
||||
NS_ASSERTION(aStartOffset <= endoffset, "A start offset is beyond the end of the text fragment!");
|
||||
|
||||
int32_t length = endoffset - aStartOffset;
|
||||
|
@ -138,7 +138,8 @@ nsXMLContentSerializer::AppendTextData(nsIContent* aNode,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int32_t endoffset = (aEndOffset == -1) ? frag->GetLength() : aEndOffset;
|
||||
int32_t fragLength = frag->GetLength();
|
||||
int32_t endoffset = (aEndOffset == -1) ? fragLength : std::min(aEndOffset, fragLength);
|
||||
int32_t length = endoffset - aStartOffset;
|
||||
|
||||
NS_ASSERTION(aStartOffset >= 0, "Negative start offset for text fragment!");
|
||||
@ -300,12 +301,16 @@ nsXMLContentSerializer::AppendComment(nsIContent* aComment,
|
||||
rv = comment->GetData(data);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
if (aStartOffset || (aEndOffset != -1)) {
|
||||
int32_t length = (aEndOffset == -1) ? data.Length() : aEndOffset;
|
||||
int32_t dataLength = data.Length();
|
||||
if (aStartOffset || (aEndOffset != -1 && aEndOffset < dataLength)) {
|
||||
int32_t length =
|
||||
(aEndOffset == -1) ? dataLength : std::min(aEndOffset, dataLength);
|
||||
length -= aStartOffset;
|
||||
|
||||
nsAutoString frag;
|
||||
data.Mid(frag, aStartOffset, length);
|
||||
if (length > 0) {
|
||||
data.Mid(frag, aStartOffset, length);
|
||||
}
|
||||
data.Assign(frag);
|
||||
}
|
||||
|
||||
|
@ -559,6 +559,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183
|
||||
[test_domparser_null_char.html]
|
||||
[test_domparsing.html]
|
||||
[test_elementTraversal.html]
|
||||
[test_encodeToStringWithMaxLength.html]
|
||||
[test_fileapi.html]
|
||||
skip-if = e10s
|
||||
[test_fileapi_slice.html]
|
||||
|
64
content/base/test/test_encodeToStringWithMaxLength.html
Normal file
64
content/base/test/test_encodeToStringWithMaxLength.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=995321
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 995321 - encodeToStringWithMaxLength</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
function getEncoder() {
|
||||
const de = SpecialPowers.Ci.nsIDocumentEncoder;
|
||||
const Cc = SpecialPowers.Cc;
|
||||
|
||||
// Create a plaintext encoder without flags.
|
||||
var encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
|
||||
.createInstance(de);
|
||||
encoder.init(document, "text/plain", 0);
|
||||
return encoder;
|
||||
}
|
||||
|
||||
function testPlaintextSerializerWithMaxLength() {
|
||||
var string = getEncoder().encodeToString();
|
||||
|
||||
var shorterString = getEncoder().encodeToStringWithMaxLength(1);
|
||||
ok(shorterString.length < 1 + 72,
|
||||
"test length is in the expected range after limiting the length to 1");
|
||||
ok(string.startsWith(shorterString.trimRight()),
|
||||
"the shorter string has the expected content");
|
||||
|
||||
shorterString = getEncoder().encodeToStringWithMaxLength(300);
|
||||
ok(shorterString.length < 300 + 72,
|
||||
"test length is in the expected range after limiting the length to 300");
|
||||
ok(string.startsWith(shorterString.trimRight()),
|
||||
"the shorter string has the expected content");
|
||||
|
||||
is(getEncoder().encodeToStringWithMaxLength(0), string,
|
||||
"limiting the length to 0 should be ignored");
|
||||
|
||||
is(getEncoder().encodeToStringWithMaxLength(10000), string,
|
||||
"limiting the length to a huge value should return the whole page");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addLoadEvent(testPlaintextSerializerWithMaxLength);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=995321">Mozilla Bug 995321</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
The <em>Mozilla</em> project is a global community of <strong>people</strong> who believe that openness, innovation, and opportunity are key to the continued health of the Internet. We have worked together since 1998 to ensure that the Internet is developed in a way that benefits everyone. We are best known for creating the Mozilla Firefox web browser.
|
||||
|
||||
The Mozilla project uses a community-based approach to create world-class open source software and to develop new types of collaborative activities. We create communities of people involved in making the Internet experience better for all of us.
|
||||
|
||||
As a result of these efforts, we have distilled a set of principles that we believe are critical for the Internet to continue to benefit the public good as well as commercial aspects of life. We set out these principles below.
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -819,6 +819,8 @@ InterAppCommService.prototype = {
|
||||
// To prevent the hacked child process from sending commands to parent
|
||||
// to do illegal connections, we need to check its manifest URL.
|
||||
if (aMessage.name !== "child-process-shutdown" &&
|
||||
// TODO: fix bug 988142 to re-enable "InterAppMessagePort:Unregister".
|
||||
aMessage.name !== "InterAppMessagePort:Unregister" &&
|
||||
kMessages.indexOf(aMessage.name) != -1) {
|
||||
if (!target.assertContainApp(message.manifestURL)) {
|
||||
if (DEBUG) {
|
||||
|
@ -1392,6 +1392,13 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
return;
|
||||
}
|
||||
|
||||
// aCallIndex can be UINT32_MAX for the pending outgoing call state update.
|
||||
// aCallIndex will be updated again after real call state changes. See Bug
|
||||
// 990467.
|
||||
if (aCallIndex == UINT32_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (aCallIndex >= mCurrentCallArray.Length()) {
|
||||
Call call;
|
||||
mCurrentCallArray.AppendElement(call);
|
||||
|
@ -139,6 +139,8 @@ nsGonkCameraControl::Initialize()
|
||||
|
||||
// Set preferred preview frame format.
|
||||
mParams.Set(CAMERA_PARAM_PREVIEWFORMAT, NS_LITERAL_STRING("yuv420sp"));
|
||||
// Turn off any normal pictures returned by the HDR scene mode
|
||||
mParams.Set(CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE, false);
|
||||
PushParametersImpl();
|
||||
|
||||
// Grab any other settings we'll need later.
|
||||
|
@ -147,7 +147,6 @@ protected:
|
||||
bool mFlashSupported;
|
||||
bool mLuminanceSupported;
|
||||
bool mAutoFlashModeOverridden;
|
||||
|
||||
Atomic<uint32_t> mDeferConfigUpdate;
|
||||
GonkCameraParameters mParams;
|
||||
|
||||
|
@ -81,6 +81,10 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
|
||||
return "iso";
|
||||
case CAMERA_PARAM_LUMINANCE:
|
||||
return "luminance-condition";
|
||||
case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
|
||||
// Not every platform defines KEY_QC_HDR_NEED_1X;
|
||||
// for those that don't, we use the raw string key.
|
||||
return "hdr-need-1x";
|
||||
|
||||
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
|
||||
return KEY_SUPPORTED_PREVIEW_SIZES;
|
||||
@ -685,6 +689,19 @@ GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Handle bools
|
||||
nsresult
|
||||
GonkCameraParameters::SetTranslated(uint32_t aKey, const bool& aValue)
|
||||
{
|
||||
return SetImpl(aKey, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraParameters::GetTranslated(uint32_t aKey, bool& aValue)
|
||||
{
|
||||
return GetImpl(aKey, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
|
||||
{
|
||||
|
@ -103,13 +103,18 @@ protected:
|
||||
{
|
||||
public:
|
||||
using android::CameraParameters::set;
|
||||
using android::CameraParameters::get;
|
||||
using android::CameraParameters::TRUE;
|
||||
using android::CameraParameters::FALSE;
|
||||
|
||||
void set(const char* aKey, float aValue) { setFloat(aKey, aValue); }
|
||||
void set(const char* aKey, double aValue) { setFloat(aKey, aValue); }
|
||||
void set(const char* aKey, bool aValue) { set(aKey, aValue ? TRUE : FALSE); }
|
||||
void get(const char* aKey, float& aRet) { aRet = getFloat(aKey); }
|
||||
void get(const char* aKey, double& aRet) { aRet = getFloat(aKey); }
|
||||
void get(const char* aKey, const char*& aRet) { aRet = android::CameraParameters::get(aKey); }
|
||||
void get(const char* aKey, const char*& aRet) { aRet = get(aKey); }
|
||||
void get(const char* aKey, int& aRet) { aRet = getInt(aKey); }
|
||||
void get(const char* aKey, bool& aRet) { aRet = strcmp(get(aKey), FALSE); }
|
||||
|
||||
static const char* GetTextKey(uint32_t aKey);
|
||||
};
|
||||
@ -173,6 +178,8 @@ protected:
|
||||
nsresult GetTranslated(uint32_t aKey, int& aValue);
|
||||
nsresult SetTranslated(uint32_t aKey, const uint32_t& aValue);
|
||||
nsresult GetTranslated(uint32_t aKey, uint32_t& aValue);
|
||||
nsresult SetTranslated(uint32_t aKey, const bool& aValue);
|
||||
nsresult GetTranslated(uint32_t aKey, bool& aValue);
|
||||
nsresult GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues);
|
||||
nsresult GetTranslated(uint32_t aKey, nsTArray<double>& aValues);
|
||||
|
||||
|
@ -51,6 +51,7 @@ enum {
|
||||
CAMERA_PARAM_SENSORANGLE,
|
||||
CAMERA_PARAM_ISOMODE,
|
||||
CAMERA_PARAM_LUMINANCE,
|
||||
CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE,
|
||||
|
||||
// supported features
|
||||
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
|
||||
|
@ -94,12 +94,15 @@ var findResult1;
|
||||
function verifyBlob(blob1, blob2, isLast)
|
||||
{
|
||||
is(blob1 instanceof SpecialPowers.Ci.nsIDOMBlob, true,
|
||||
"Instance of nsIDOMBlob");
|
||||
is(blob1 instanceof SpecialPowers.Ci.nsIDOMFile,
|
||||
blob2 instanceof SpecialPowers.Ci.nsIDOMFile,
|
||||
"Instance of nsIDOMFile");
|
||||
is(blob1.size, blob2.size, "Correct size");
|
||||
is(blob1.type, blob2.type, "Correct type");
|
||||
"blob1 is an instance of nsIDOMBlob");
|
||||
is(blob2 instanceof SpecialPowers.Ci.nsIDOMBlob, true,
|
||||
"blob2 is an instance of nsIDOMBlob");
|
||||
isnot(blob1 instanceof SpecialPowers.Ci.nsIDOMFile, true,
|
||||
"blob1 is an instance of nsIDOMFile");
|
||||
isnot(blob2 instanceof SpecialPowers.Ci.nsIDOMFile, true,
|
||||
"blob2 is an instance of nsIDOMFile");
|
||||
ise(blob1.size, blob2.size, "Same size");
|
||||
ise(blob1.type, blob2.type, "Same type");
|
||||
|
||||
var buffer1;
|
||||
var buffer2;
|
||||
@ -125,16 +128,18 @@ function verifyBlob(blob1, blob2, isLast)
|
||||
|
||||
function verifyBlobArray(blobs1, blobs2)
|
||||
{
|
||||
is(blobs1 instanceof Array, true, "Got an array object");
|
||||
is(blobs1.length, blobs2.length, "Correct length");
|
||||
is(blobs1 instanceof Array, true, "blobs1 is an array object");
|
||||
is(blobs2 instanceof Array, true, "blobs2 is an array object");
|
||||
ise(blobs1.length, blobs2.length, "Same length");
|
||||
|
||||
if (!blobs1.length) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < blobs1.length; i++)
|
||||
for (var i = 0; i < blobs1.length; i++) {
|
||||
verifyBlob(blobs1[i], blobs2[i], i == blobs1.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
var req;
|
||||
@ -170,7 +175,7 @@ var steps = [
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
verifyBlobArray(createResult1.photo, properties1.photo);
|
||||
verifyBlobArray(findResult1.photo, properties1.photo);
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
@ -195,7 +200,7 @@ var steps = [
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
verifyBlobArray(createResult1.photo, properties2.photo);
|
||||
verifyBlobArray(findResult1.photo, properties2.photo);
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
@ -74,6 +74,8 @@ function wrapDomRequestAsPromise(aRequest) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
let workingFrame;
|
||||
|
||||
/**
|
||||
* Get mozSettings value specified by @aKey.
|
||||
*
|
||||
@ -93,7 +95,8 @@ function wrapDomRequestAsPromise(aRequest) {
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function getSettings(aKey, aAllowError) {
|
||||
let request = navigator.mozSettings.createLock().get(aKey);
|
||||
let request =
|
||||
workingFrame.contentWindow.navigator.mozSettings.createLock().get(aKey);
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(function resolve(aEvent) {
|
||||
ok(true, "getSettings(" + aKey + ") - success");
|
||||
@ -120,7 +123,8 @@ function getSettings(aKey, aAllowError) {
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setSettings(aSettings, aAllowError) {
|
||||
let request = navigator.mozSettings.createLock().set(aSettings);
|
||||
let request =
|
||||
workingFrame.contentWindow.navigator.mozSettings.createLock().set(aSettings);
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(function resolve() {
|
||||
ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
|
||||
@ -195,7 +199,6 @@ function setDataApnSettings(aApnSettings, aAllowError) {
|
||||
return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError);
|
||||
}
|
||||
|
||||
let workingFrame;
|
||||
let mobileConnection;
|
||||
|
||||
/**
|
||||
@ -282,7 +285,8 @@ function waitForManagerEvent(aEventName, aServiceId) {
|
||||
|
||||
let mobileConn = mobileConnection;
|
||||
if (aServiceId !== undefined) {
|
||||
mobileConn = navigator.mozMobileConnections[aServiceId];
|
||||
mobileConn =
|
||||
workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
|
||||
}
|
||||
|
||||
mobileConn.addEventListener(aEventName, function onevent(aEvent) {
|
||||
@ -407,7 +411,8 @@ function setDataEnabledAndWait(aEnabled, aServiceId) {
|
||||
Promise.all(promises).then(function keepWaiting() {
|
||||
let mobileConn = mobileConnection;
|
||||
if (aServiceId !== undefined) {
|
||||
mobileConn = navigator.mozMobileConnections[aServiceId];
|
||||
mobileConn =
|
||||
workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
|
||||
}
|
||||
// To ignore some transient states, we only resolve that deferred promise
|
||||
// when the |connected| state equals to the expected one and never rejects.
|
||||
@ -467,7 +472,8 @@ function setEmulatorRoamingAndWait(aRoaming, aServiceId) {
|
||||
.then(() => {
|
||||
let mobileConn = mobileConnection;
|
||||
if (aServiceId !== undefined) {
|
||||
mobileConn = navigator.mozMobileConnections[aServiceId];
|
||||
mobileConn =
|
||||
workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId];
|
||||
}
|
||||
is(mobileConn[aWhich].roaming, aRoaming,
|
||||
aWhich + ".roaming")
|
||||
|
@ -6,8 +6,8 @@ MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const SETTINGS_KEY_DATA_DEFAULT_ID = "ril.data.defaultServiceId";
|
||||
|
||||
let connections = window.navigator.mozMobileConnections;
|
||||
let numOfRadioInterfaces = getNumOfRadioInterfaces();
|
||||
let connections;
|
||||
let numOfRadioInterfaces;
|
||||
let currentDataDefaultId = 0;
|
||||
|
||||
function muxModem(id) {
|
||||
@ -142,6 +142,9 @@ function testDisableData() {
|
||||
}
|
||||
|
||||
startDSDSTestCommon(function() {
|
||||
connections = workingFrame.contentWindow.navigator.mozMobileConnections;
|
||||
numOfRadioInterfaces = getNumOfRadioInterfaces();
|
||||
|
||||
return testEnableData()
|
||||
.then(testSwitchDefaultDataToSimTwo)
|
||||
.then(testDisableDataRoamingWhileRoaming)
|
||||
|
@ -8,6 +8,6 @@ startTestCommon(function() {
|
||||
let connections =
|
||||
workingFrame.contentWindow.navigator.mozMobileConnections;
|
||||
|
||||
let num = SpecialPowers.getIntPref("ril.numRadioInterfaces");
|
||||
let num = getNumOfRadioInterfaces();
|
||||
is(connections.length, num, "ril.numRadioInterfaces");
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ public class testPictureLinkContextMenu extends ContentContextMenuTest {
|
||||
private static final String tabs [] = { "Image", "Link" };
|
||||
private static final String photoMenuItems [] = { "Copy Image Location", "Share Image", "Set Image As", "Save Image" };
|
||||
private static final String linkMenuItems [] = { "Open Link in New Tab", "Open Link in Private Tab", "Copy Link", "Share Link", "Bookmark Link"};
|
||||
private static final String linkTitle = "^Link$";
|
||||
private static final String imageTitle = "^Image$";
|
||||
|
||||
public void testPictureLinkContextMenu() {
|
||||
blockForGeckoReady();
|
||||
@ -20,21 +20,19 @@ public class testPictureLinkContextMenu extends ContentContextMenuTest {
|
||||
loadAndPaint(PICTURE_PAGE_URL);
|
||||
verifyPageTitle(PICTURE_PAGE_TITLE);
|
||||
|
||||
switchTabs(imageTitle);
|
||||
verifyContextMenuItems(photoMenuItems);
|
||||
verifyTabs(tabs);
|
||||
switchTabs(imageTitle);
|
||||
verifyCopyOption(photoMenuItems[0], "Firefox.jpg"); // Test the "Copy Image Location" option
|
||||
switchTabs(imageTitle);
|
||||
verifyShareOption(photoMenuItems[1], PICTURE_PAGE_TITLE); // Test the "Share Image" option
|
||||
|
||||
switchTabs(linkTitle);
|
||||
verifyContextMenuItems(linkMenuItems);
|
||||
openTabFromContextMenu(linkMenuItems[0],2); // Test the "Open in New Tab" option - expecting 2 tabs: the original and the new one
|
||||
switchTabs(linkTitle);
|
||||
openTabFromContextMenu(linkMenuItems[1],2); // Test the "Open in Private Tab" option - expecting only 2 tabs in normal mode
|
||||
switchTabs(linkTitle);
|
||||
verifyCopyOption(linkMenuItems[2], BLANK_PAGE_URL); // Test the "Copy Link" option
|
||||
switchTabs(linkTitle);
|
||||
verifyShareOption(linkMenuItems[3], PICTURE_PAGE_TITLE); // Test the "Share Link" option
|
||||
switchTabs(linkTitle);
|
||||
verifyBookmarkLinkOption(linkMenuItems[4],BLANK_PAGE_URL); // Test the "Bookmark Link" option
|
||||
}
|
||||
|
||||
|
@ -2102,6 +2102,11 @@ var NativeWindow = {
|
||||
else this._targetRef = null;
|
||||
},
|
||||
|
||||
get defaultContext() {
|
||||
delete this.defaultContext;
|
||||
return this.defaultContext = Strings.browser.GetStringFromName("browser.menu.context.default");
|
||||
},
|
||||
|
||||
/* Gets menuitems for an arbitrary node
|
||||
* Parameters:
|
||||
* element - The element to look at. If this element has a contextmenu attribute, the
|
||||
@ -2183,7 +2188,7 @@ var NativeWindow = {
|
||||
} catch(ex) { }
|
||||
|
||||
// Fallback to the default
|
||||
return Strings.browser.GetStringFromName("browser.menu.context.default");
|
||||
return this.defaultContext;
|
||||
},
|
||||
|
||||
// Adds context menu items added through the add-on api
|
||||
@ -2338,7 +2343,8 @@ var NativeWindow = {
|
||||
*/
|
||||
_reformatList: function(target) {
|
||||
let contexts = Object.keys(this.menus);
|
||||
if (contexts.length == 1) {
|
||||
|
||||
if (contexts.length === 1) {
|
||||
// If there's only one context, we'll only show a single flat single select list
|
||||
return this._reformatMenuItems(target, this.menus[contexts[0]]);
|
||||
}
|
||||
@ -2357,12 +2363,24 @@ var NativeWindow = {
|
||||
*/
|
||||
_reformatListAsTabs: function(target, menus) {
|
||||
let itemArray = [];
|
||||
for (let context in menus) {
|
||||
|
||||
// Sort the keys so that "link" is always first
|
||||
let contexts = Object.keys(this.menus);
|
||||
contexts.sort((context1, context2) => {
|
||||
if (context1 === this.defaultContext) {
|
||||
return -1;
|
||||
} else if (context2 === this.defaultContext) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
contexts.forEach(context => {
|
||||
itemArray.push({
|
||||
label: context,
|
||||
items: this._reformatMenuItems(target, menus[context])
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return itemArray;
|
||||
},
|
||||
@ -8386,8 +8404,10 @@ HTMLContextMenuItem.prototype = Object.create(ContextMenuItem.prototype, {
|
||||
}
|
||||
|
||||
var items = NativeWindow.contextmenus._getHTMLContextMenuItemsForMenu(elt, target);
|
||||
// This menu will always only have one context, but we still make sure its the "right" one.
|
||||
var context = NativeWindow.contextmenus._getContextType(target);
|
||||
if (items.length > 0) {
|
||||
NativeWindow.contextmenus._addMenuItems(items, "link");
|
||||
NativeWindow.contextmenus._addMenuItems(items, context);
|
||||
}
|
||||
|
||||
} catch(ex) {
|
||||
|
Binary file not shown.
@ -242,10 +242,16 @@ int APIENTRY WinMain(
|
||||
|
||||
/* BEGIN Mozilla customizations */
|
||||
bool showProgress = true;
|
||||
bool extractOnly = false;
|
||||
if (switches.Left(3).CompareNoCase(UString(L"-ms")) == 0 ||
|
||||
switches.Left(4).CompareNoCase(UString(L"/INI")) == 0 ||
|
||||
switches.Left(2).CompareNoCase(UString(L"/S")) == 0)
|
||||
switches.Left(4).CompareNoCase(UString(L"/ini")) == 0 ||
|
||||
switches.Left(2).CompareNoCase(UString(L"/s")) == 0) {
|
||||
showProgress = false;
|
||||
} else if (switches.Left(12).CompareNoCase(UString(L"/extractdir=")) == 0) {
|
||||
assumeYes = true;
|
||||
showProgress = false;
|
||||
extractOnly = true;
|
||||
}
|
||||
/* END Mozilla customizations */
|
||||
|
||||
AString config;
|
||||
@ -290,16 +296,20 @@ int APIENTRY WinMain(
|
||||
}
|
||||
|
||||
NFile::NDirectory::CTempDirectory tempDir;
|
||||
if (!tempDir.Create(kTempDirPrefix))
|
||||
/* Mozilla customizations - Added !extractOnly */
|
||||
if (!extractOnly && !tempDir.Create(kTempDirPrefix))
|
||||
{
|
||||
if (!assumeYes)
|
||||
MyMessageBox(L"Can not create temp folder archive");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* BEGIN Mozilla customizations */
|
||||
UString tempDirPath = (extractOnly ? switches.Mid(12) : GetUnicodeString(tempDir.GetPath()));
|
||||
/* END Mozilla customizations */
|
||||
|
||||
COpenCallbackGUI openCallback;
|
||||
|
||||
UString tempDirPath = GetUnicodeString(tempDir.GetPath());
|
||||
bool isCorrupt = false;
|
||||
UString errorMessage;
|
||||
HRESULT result = ExtractArchive(fullPath, tempDirPath, &openCallback, showProgress,
|
||||
@ -320,6 +330,13 @@ int APIENTRY WinMain(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* BEGIN Mozilla customizations */
|
||||
// The code immediately above handles the error case for extraction.
|
||||
if (extractOnly) {
|
||||
return 0;
|
||||
}
|
||||
/* END Mozilla customizations */
|
||||
|
||||
CCurrentDirRestorer currentDirRestorer;
|
||||
|
||||
if (!SetCurrentDirectory(tempDir.GetPath()))
|
||||
|
@ -164,9 +164,9 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
|
||||
ProgressSynch.SetPaused(true);
|
||||
int res = ::MessageBoxW(HWND(*this),
|
||||
L"Are you sure you want to cancel?",
|
||||
_title, MB_YESNOCANCEL);
|
||||
_title, MB_YESNO);
|
||||
ProgressSynch.SetPaused(paused);
|
||||
if (res == IDCANCEL || res == IDNO)
|
||||
if (res == IDNO)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
@ -502,6 +502,13 @@ ErrorHandler.prototype = {
|
||||
*/
|
||||
dontIgnoreErrors: false,
|
||||
|
||||
/**
|
||||
* Flag that indicates if we have already reported a prolonged failure.
|
||||
* Once set, we don't report it again, meaning this error is only reported
|
||||
* one per run.
|
||||
*/
|
||||
didReportProlongedError: false,
|
||||
|
||||
init: function init() {
|
||||
Svc.Obs.add("weave:engine:sync:applied", this);
|
||||
Svc.Obs.add("weave:engine:sync:error", this);
|
||||
@ -772,7 +779,13 @@ ErrorHandler.prototype = {
|
||||
if (lastSync && ((Date.now() - Date.parse(lastSync)) >
|
||||
Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 1000)) {
|
||||
Status.sync = PROLONGED_SYNC_FAILURE;
|
||||
this._log.trace("shouldReportError: true (prolonged sync failure).");
|
||||
if (this.didReportProlongedError) {
|
||||
this._log.trace("shouldReportError: false (prolonged sync failure, but" +
|
||||
" we've already reported it).");
|
||||
return false;
|
||||
}
|
||||
this._log.trace("shouldReportError: true (first prolonged sync failure).");
|
||||
this.didReportProlongedError = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,7 @@ function clean() {
|
||||
Service.startOver();
|
||||
Status.resetSync();
|
||||
Status.resetBackoff();
|
||||
errorHandler.didReportProlongedError = false;
|
||||
}
|
||||
|
||||
add_identity_test(this, function test_401_logout() {
|
||||
@ -297,18 +298,32 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, prolonged, login error reported
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
// Second time with prolonged error and without resetting
|
||||
// didReportProlongedError, sync error should not be reported.
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_false(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test non-network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
errorHandler.didReportProlongedError = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
@ -316,6 +331,8 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
@ -323,6 +340,8 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test non-network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
@ -330,6 +349,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test non-network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
@ -337,6 +357,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
@ -344,6 +365,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_false(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
@ -351,6 +373,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
do_check_false(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test server maintenance, sync errors are not reported
|
||||
Status.resetSync();
|
||||
@ -358,6 +381,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_false(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test server maintenance, login errors are not reported
|
||||
Status.resetSync();
|
||||
@ -365,6 +389,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
do_check_false(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test prolonged, server maintenance, sync errors are reported
|
||||
Status.resetSync();
|
||||
@ -372,6 +397,8 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test prolonged, server maintenance, login errors are reported
|
||||
Status.resetSync();
|
||||
@ -379,6 +406,8 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test dontIgnoreErrors, server maintenance, sync errors are reported
|
||||
Status.resetSync();
|
||||
@ -386,6 +415,8 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
// dontIgnoreErrors means we don't set didReportProlongedError
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, server maintenance, login errors are reported
|
||||
Status.resetSync();
|
||||
@ -393,6 +424,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, prolonged, server maintenance,
|
||||
// sync errors are reported
|
||||
@ -401,6 +433,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, prolonged, server maintenance,
|
||||
// login errors are reported
|
||||
@ -409,7 +442,7 @@ add_identity_test(this, function test_shouldReportError() {
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
do_check_true(errorHandler.shouldReportError());
|
||||
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
});
|
||||
|
||||
add_identity_test(this, function test_shouldReportError_master_password() {
|
||||
@ -625,6 +658,7 @@ add_task(function test_login_prolonged_non_network_error() {
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -651,6 +685,7 @@ add_task(function test_sync_prolonged_non_network_error() {
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -671,6 +706,7 @@ add_identity_test(this, function test_login_prolonged_network_error() {
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
deferred.resolve();
|
||||
@ -688,6 +724,7 @@ add_test(function test_sync_prolonged_network_error() {
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
clean();
|
||||
@ -708,6 +745,7 @@ add_task(function test_login_non_network_error() {
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -734,6 +772,7 @@ add_task(function test_sync_non_network_error() {
|
||||
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -755,6 +794,7 @@ add_identity_test(this, function test_login_network_error() {
|
||||
Svc.Obs.remove("weave:ui:clear-error", onClearError);
|
||||
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
clean();
|
||||
@ -773,6 +813,7 @@ add_test(function test_sync_network_error() {
|
||||
Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
|
||||
Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
|
||||
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
clean();
|
||||
@ -807,6 +848,7 @@ add_identity_test(this, function test_sync_server_maintenance_error() {
|
||||
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
|
||||
clean();
|
||||
@ -850,6 +892,7 @@ add_identity_test(this, function test_info_collections_login_server_maintenance_
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
clean();
|
||||
@ -892,6 +935,7 @@ add_identity_test(this, function test_meta_global_login_server_maintenance_error
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
clean();
|
||||
@ -937,6 +981,7 @@ add_identity_test(this, function test_crypto_keys_login_server_maintenance_error
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
clean();
|
||||
@ -964,6 +1009,7 @@ add_task(function test_sync_prolonged_server_maintenance_error() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -998,6 +1044,7 @@ add_identity_test(this, function test_info_collections_login_prolonged_server_ma
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1033,6 +1080,7 @@ add_identity_test(this, function test_meta_global_login_prolonged_server_mainten
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1070,6 +1118,7 @@ add_identity_test(this, function test_download_crypto_keys_login_prolonged_serve
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1105,6 +1154,7 @@ add_identity_test(this, function test_upload_crypto_keys_login_prolonged_server_
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1141,6 +1191,7 @@ add_identity_test(this, function test_wipeServer_login_prolonged_server_maintena
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1183,6 +1234,7 @@ add_identity_test(this, function test_wipeRemote_prolonged_server_maintenance_er
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
|
||||
do_check_true(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1214,6 +1266,7 @@ add_task(function test_sync_syncAndReportErrors_server_maintenance_error() {
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1249,6 +1302,7 @@ add_identity_test(this, function test_info_collections_login_syncAndReportErrors
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1285,6 +1339,7 @@ add_identity_test(this, function test_meta_global_login_syncAndReportErrors_serv
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1323,6 +1378,7 @@ add_identity_test(this, function test_download_crypto_keys_login_syncAndReportEr
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1359,6 +1415,7 @@ add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErro
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1395,6 +1452,7 @@ add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_serve
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1436,6 +1494,7 @@ add_identity_test(this, function test_wipeRemote_syncAndReportErrors_server_main
|
||||
do_check_eq(Status.service, SYNC_FAILED);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1467,6 +1526,9 @@ add_task(function test_sync_syncAndReportErrors_prolonged_server_maintenance_err
|
||||
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
|
||||
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
|
||||
do_check_eq(Status.sync, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1502,6 +1564,9 @@ add_identity_test(this, function test_info_collections_login_syncAndReportErrors
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1538,6 +1603,9 @@ add_identity_test(this, function test_meta_global_login_syncAndReportErrors_prol
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1576,6 +1644,9 @@ add_identity_test(this, function test_download_crypto_keys_login_syncAndReportEr
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1612,6 +1683,9 @@ add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErro
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
@ -1648,6 +1722,9 @@ add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_prolo
|
||||
do_check_eq(backoffInterval, 42);
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
do_check_false(errorHandler.didReportProlongedError);
|
||||
|
||||
clean();
|
||||
server.stop(deferred.resolve);
|
||||
|
@ -79,9 +79,18 @@ var Authentication = {
|
||||
});
|
||||
|
||||
try {
|
||||
return cb.wait();
|
||||
cb.wait();
|
||||
|
||||
if (Weave.Status.login !== Weave.LOGIN_SUCCEEDED) {
|
||||
Logger.logInfo("Logging into Weave.");
|
||||
Weave.Service.login();
|
||||
Logger.AssertEqual(Weave.Status.login, Weave.LOGIN_SUCCEEDED,
|
||||
"Weave logged in");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
throw new Error("signIn() failed with: " + JSON.stringify(error));
|
||||
throw new Error("signIn() failed with: " + error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -68,9 +68,16 @@ var Authentication = {
|
||||
Weave.Service.identity.basicPassword = account["password"];
|
||||
Weave.Service.identity.syncKey = account["passphrase"];
|
||||
|
||||
// Fake the login
|
||||
Weave.Service.login();
|
||||
Weave.Svc.Obs.notify("weave:service:setup-complete");
|
||||
if (Weave.Status.login !== Weave.LOGIN_SUCCEEDED) {
|
||||
Logger.logInfo("Logging into Weave.");
|
||||
Weave.Service.login();
|
||||
Logger.AssertEqual(Weave.Status.login, Weave.LOGIN_SUCCEEDED,
|
||||
"Weave logged in");
|
||||
|
||||
// Bug 997279: Temporary workaround until we can ensure that Sync itself
|
||||
// sends this notification for the first login attempt by TPS
|
||||
Weave.Svc.Obs.notify("weave:service:setup-complete");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -837,7 +837,6 @@ let TPS = {
|
||||
let account = this.fxaccounts_enabled ? this.config.fx_account
|
||||
: this.config.sync_account;
|
||||
Authentication.signIn(account);
|
||||
|
||||
this.waitForSetupComplete();
|
||||
Logger.AssertEqual(Weave.Status.service, Weave.STATUS_OK, "Weave status OK");
|
||||
this.waitForTracking();
|
||||
|
@ -7,169 +7,150 @@ let gCategoryUtilities;
|
||||
let gInstalledAddons = [];
|
||||
let gContext = this;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
add_task(function* initializeState() {
|
||||
gManagerWindow = yield open_manager();
|
||||
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
|
||||
|
||||
open_manager(null, (win) => {
|
||||
gManagerWindow = win;
|
||||
gCategoryUtilities = new CategoryUtilities(win);
|
||||
// The Experiments Manager will interfere with us by preventing installs
|
||||
// of experiments it doesn't know about. We remove it from the equation
|
||||
// because here we are only concerned with core Addon Manager operation,
|
||||
// not the superset Experiments Manager has imposed.
|
||||
if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
|
||||
Components.utils.import("resource:///modules/experiments/Experiments.jsm", gContext);
|
||||
|
||||
// The Experiments Manager will interfere with us by preventing installs
|
||||
// of experiments it doesn't know about. We remove it from the equation
|
||||
// because here we are only concerned with core Addon Manager operation,
|
||||
// not the superset Experiments Manager has imposed.
|
||||
if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
|
||||
Components.utils.import("resource:///modules/experiments/Experiments.jsm", gContext);
|
||||
|
||||
// There is a race condition between XPCOM service initialization and
|
||||
// this test running. We have to initialize the instance first, then
|
||||
// uninitialize it to prevent this.
|
||||
let instance = gContext.Experiments.instance();
|
||||
instance.uninit().then(run_next_test);
|
||||
} else {
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
for (let addon of gInstalledAddons) {
|
||||
addon.uninstall();
|
||||
// There is a race condition between XPCOM service initialization and
|
||||
// this test running. We have to initialize the instance first, then
|
||||
// uninitialize it to prevent this.
|
||||
let instance = gContext.Experiments.instance();
|
||||
yield instance.uninit();
|
||||
}
|
||||
|
||||
close_manager(gManagerWindow, () => {
|
||||
if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
|
||||
gContext.Experiments.instance().init();
|
||||
finish();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// On an empty profile with no experiments, the experiment category
|
||||
// should be hidden.
|
||||
add_test(function testInitialState() {
|
||||
add_task(function* testInitialState() {
|
||||
Assert.ok(gCategoryUtilities.get("experiment", false), "Experiment tab is defined.");
|
||||
|
||||
Assert.ok(!gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab hidden by default.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function testExperimentInfoNotVisible() {
|
||||
gCategoryUtilities.openType("extension", () => {
|
||||
let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
|
||||
is_element_hidden(el, "Experiment info not visible on other types.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
add_task(function* testExperimentInfoNotVisible() {
|
||||
yield gCategoryUtilities.openType("extension");
|
||||
let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
|
||||
is_element_hidden(el, "Experiment info not visible on other types.");
|
||||
});
|
||||
|
||||
// If we have an active experiment, we should see the experiments tab
|
||||
// and that tab should have some messages.
|
||||
add_test(function testActiveExperiment() {
|
||||
install_addon("addons/browser_experiment1.xpi", (addon) => {
|
||||
gInstalledAddons.push(addon);
|
||||
add_task(function* testActiveExperiment() {
|
||||
let addon = yield install_addon("addons/browser_experiment1.xpi");
|
||||
gInstalledAddons.push(addon);
|
||||
|
||||
Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install.");
|
||||
Assert.equal(addon.isActive, false, "Add-on is not active.");
|
||||
Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install.");
|
||||
Assert.equal(addon.isActive, false, "Add-on is not active.");
|
||||
|
||||
Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
|
||||
Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
|
||||
|
||||
gCategoryUtilities.openType("experiment", (win) => {
|
||||
let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
|
||||
is_element_visible(el, "Experiment info is visible on experiment tab.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
yield gCategoryUtilities.openType("experiment");
|
||||
let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
|
||||
is_element_visible(el, "Experiment info is visible on experiment tab.");
|
||||
});
|
||||
|
||||
add_test(function testExperimentLearnMore() {
|
||||
add_task(function* testExperimentLearnMore() {
|
||||
// Actual URL is irrelevant.
|
||||
Services.prefs.setCharPref("toolkit.telemetry.infoURL",
|
||||
"http://mochi.test:8888/server.js");
|
||||
|
||||
gCategoryUtilities.openType("experiment", (win) => {
|
||||
let btn = gManagerWindow.document.getElementById("experiments-learn-more");
|
||||
yield gCategoryUtilities.openType("experiment");
|
||||
let btn = gManagerWindow.document.getElementById("experiments-learn-more");
|
||||
|
||||
if (!gUseInContentUI) {
|
||||
is_element_hidden(btn, "Learn more button hidden if not using in-content UI.");
|
||||
Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
|
||||
if (!gUseInContentUI) {
|
||||
is_element_hidden(btn, "Learn more button hidden if not using in-content UI.");
|
||||
Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
|
||||
|
||||
run_next_test();
|
||||
return;
|
||||
} else {
|
||||
is_element_visible(btn, "Learn more button visible.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("DOMContentLoaded", function onLoad(event) {
|
||||
info("Telemetry privacy policy window opened.");
|
||||
window.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
is_element_visible(btn, "Learn more button visible.");
|
||||
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL");
|
||||
Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy.");
|
||||
browser.contentWindow.close();
|
||||
let deferred = Promise.defer();
|
||||
window.addEventListener("DOMContentLoaded", function onLoad(event) {
|
||||
info("Telemetry privacy policy window opened.");
|
||||
window.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL");
|
||||
Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy.");
|
||||
browser.contentWindow.close();
|
||||
|
||||
run_next_test();
|
||||
}, false);
|
||||
Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
|
||||
|
||||
info("Opening telemetry privacy policy.");
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
|
||||
});
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
|
||||
info("Opening telemetry privacy policy.");
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
|
||||
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
||||
add_test(function testOpenPreferences() {
|
||||
gCategoryUtilities.openType("experiment", (win) => {
|
||||
let btn = gManagerWindow.document.getElementById("experiments-change-telemetry");
|
||||
if (!gUseInContentUI) {
|
||||
is_element_hidden(btn, "Change telemetry button not enabled in out of window UI.");
|
||||
info("Skipping preferences open test because not using in-content UI.");
|
||||
run_next_test();
|
||||
return;
|
||||
}
|
||||
add_task(function* testOpenPreferences() {
|
||||
yield gCategoryUtilities.openType("experiment");
|
||||
let btn = gManagerWindow.document.getElementById("experiments-change-telemetry");
|
||||
if (!gUseInContentUI) {
|
||||
is_element_hidden(btn, "Change telemetry button not enabled in out of window UI.");
|
||||
info("Skipping preferences open test because not using in-content UI.");
|
||||
return;
|
||||
}
|
||||
|
||||
is_element_visible(btn, "Change telemetry button visible in in-content UI.");
|
||||
is_element_visible(btn, "Change telemetry button visible in in-content UI.");
|
||||
|
||||
Services.obs.addObserver(function observer(prefWin, topic, data) {
|
||||
Services.obs.removeObserver(observer, "advanced-pane-loaded");
|
||||
let deferred = Promise.defer();
|
||||
Services.obs.addObserver(function observer(prefWin, topic, data) {
|
||||
Services.obs.removeObserver(observer, "advanced-pane-loaded");
|
||||
|
||||
info("Advanced preference pane opened.");
|
||||
info("Advanced preference pane opened.");
|
||||
|
||||
// We want this test to fail if the preferences pane changes.
|
||||
let el = prefWin.document.getElementById("dataChoicesPanel");
|
||||
is_element_visible(el);
|
||||
// We want this test to fail if the preferences pane changes.
|
||||
let el = prefWin.document.getElementById("dataChoicesPanel");
|
||||
is_element_visible(el);
|
||||
|
||||
prefWin.close();
|
||||
info("Closed preferences pane.");
|
||||
prefWin.close();
|
||||
info("Closed preferences pane.");
|
||||
|
||||
run_next_test();
|
||||
}, "advanced-pane-loaded", false);
|
||||
deferred.resolve();
|
||||
}, "advanced-pane-loaded", false);
|
||||
|
||||
info("Loading preferences pane.");
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
|
||||
});
|
||||
info("Loading preferences pane.");
|
||||
EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
|
||||
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
||||
add_test(function testButtonPresence() {
|
||||
gCategoryUtilities.openType("experiment", (win) => {
|
||||
let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
|
||||
Assert.ok(item, "Got add-on element.");
|
||||
add_task(function* testButtonPresence() {
|
||||
yield gCategoryUtilities.openType("experiment");
|
||||
let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
|
||||
Assert.ok(item, "Got add-on element.");
|
||||
|
||||
let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
|
||||
// Corresponds to the uninstall permission.
|
||||
is_element_visible(el, "Remove button is visible.");
|
||||
// Corresponds to lack of disable permission.
|
||||
el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
|
||||
is_element_hidden(el, "Disable button not visible.");
|
||||
// Corresponds to lack of enable permission.
|
||||
el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn");
|
||||
is_element_hidden(el, "Enable button not visible.");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
|
||||
// Corresponds to the uninstall permission.
|
||||
is_element_visible(el, "Remove button is visible.");
|
||||
// Corresponds to lack of disable permission.
|
||||
el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
|
||||
is_element_hidden(el, "Disable button not visible.");
|
||||
// Corresponds to lack of enable permission.
|
||||
el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn");
|
||||
is_element_hidden(el, "Enable button not visible.");
|
||||
});
|
||||
|
||||
add_task(function* testCleanup() {
|
||||
for (let addon of gInstalledAddons) {
|
||||
addon.uninstall();
|
||||
}
|
||||
|
||||
yield close_manager(gManagerWindow);
|
||||
|
||||
if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
|
||||
yield gContext.Experiments.instance().init();
|
||||
}
|
||||
});
|
||||
|
@ -283,6 +283,8 @@ function wait_for_manager_load(aManagerWindow, aCallback) {
|
||||
}
|
||||
|
||||
function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
function setup_manager(aManagerWindow) {
|
||||
if (aLoadCallback)
|
||||
log_exceptions(aLoadCallback, aManagerWindow);
|
||||
@ -299,7 +301,10 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
// Some functions like synthesizeMouse don't like to be called during
|
||||
// the load event so ensure that has completed
|
||||
executeSoon(function() {
|
||||
log_exceptions(aCallback, aManagerWindow);
|
||||
if (aCallback) {
|
||||
log_exceptions(aCallback, aManagerWindow);
|
||||
}
|
||||
deferred.resolve(aManagerWindow);
|
||||
});
|
||||
}, null, aLongerTimeout);
|
||||
});
|
||||
@ -309,7 +314,7 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
if (gUseInContentUI) {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
switchToTabHavingURI(MANAGER_URI, true);
|
||||
|
||||
|
||||
// This must be a new load, else the ping/pong would have
|
||||
// found the window above.
|
||||
Services.obs.addObserver(function (aSubject, aTopic, aData) {
|
||||
@ -318,7 +323,7 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
return;
|
||||
setup_manager(aSubject);
|
||||
}, "EM-loaded", false);
|
||||
return;
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
openDialog(MANAGER_URI);
|
||||
@ -326,9 +331,12 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
setup_manager(aSubject);
|
||||
}, "EM-loaded", false);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function close_manager(aManagerWindow, aCallback, aLongerTimeout) {
|
||||
let deferred = Promise.defer();
|
||||
requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2);
|
||||
|
||||
ok(aManagerWindow != null, "Should have an add-ons manager window to close");
|
||||
@ -336,10 +344,15 @@ function close_manager(aManagerWindow, aCallback, aLongerTimeout) {
|
||||
|
||||
aManagerWindow.addEventListener("unload", function() {
|
||||
this.removeEventListener("unload", arguments.callee, false);
|
||||
log_exceptions(aCallback);
|
||||
if (aCallback) {
|
||||
log_exceptions(aCallback);
|
||||
}
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
|
||||
aManagerWindow.close();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function restart_manager(aManagerWindow, aView, aCallback, aLoadCallback) {
|
||||
@ -424,17 +437,25 @@ function is_element_hidden(aElement, aMsg) {
|
||||
* The callback will receive the Addon for the installed add-on.
|
||||
*/
|
||||
function install_addon(path, cb, pathPrefix=TESTROOT) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
AddonManager.getInstallForURL(pathPrefix + path, (install) => {
|
||||
install.addListener({
|
||||
onInstallEnded: () => {
|
||||
executeSoon(() => {
|
||||
cb(install.addon);
|
||||
if (cb) {
|
||||
cb(install.addon);
|
||||
}
|
||||
|
||||
deferred.resolve(install.addon);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
install.install();
|
||||
}, "application/x-xpinstall");
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function CategoryUtilities(aManagerWindow) {
|
||||
@ -496,17 +517,26 @@ CategoryUtilities.prototype = {
|
||||
},
|
||||
|
||||
open: function(aCategory, aCallback) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
isnot(this.window, null, "Should not open category when manager window is not loaded");
|
||||
ok(this.isVisible(aCategory), "Category should be visible if attempting to open it");
|
||||
|
||||
EventUtils.synthesizeMouse(aCategory, 2, 2, { }, this.window);
|
||||
|
||||
if (aCallback)
|
||||
wait_for_view_load(this.window, aCallback);
|
||||
wait_for_view_load(this.window, (win) => {
|
||||
if (aCallback) {
|
||||
log_exceptions(aCallback, win);
|
||||
}
|
||||
|
||||
deferred.resolve(win);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
openType: function(aCategoryType, aCallback) {
|
||||
this.open(this.get(aCategoryType), aCallback);
|
||||
return this.open(this.get(aCategoryType), aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user