Merge m-c to inbound
|
@ -793,6 +793,12 @@ panelview > .social-panel-frame {
|
|||
height: auto;
|
||||
}
|
||||
|
||||
/* Translation */
|
||||
notification[value="translation"] {
|
||||
-moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
|
||||
}
|
||||
|
||||
/* Social */
|
||||
/* Note the chatbox 'width' values are duplicated in socialchat.xml */
|
||||
chatbox {
|
||||
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbox");
|
||||
|
|
|
@ -1181,6 +1181,33 @@ var gBrowserInit = {
|
|||
WindowsPrefSync.init();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (window.matchMedia("(-moz-os-version: windows-win8)").matches &&
|
||||
window.matchMedia("(-moz-windows-default-theme)").matches) {
|
||||
let windows8WindowFrameColor = Cu.import("resource:///modules/Windows8WindowFrameColor.jsm", {}).Windows8WindowFrameColor;
|
||||
let windowFrameColor = windows8WindowFrameColor.get();
|
||||
|
||||
// Formula from W3C Techniques For Accessibility Evaluation And
|
||||
// Repair Tools, Section 2.2 http://www.w3.org/TR/AERT#color
|
||||
let brightnessThreshold = 125;
|
||||
let colorThreshold = 500;
|
||||
let bY = windowFrameColor[0] * .299 +
|
||||
windowFrameColor[1] * .587 +
|
||||
windowFrameColor[2] * .114;
|
||||
let fY = 0; // Default to black for foreground text.
|
||||
let brightnessDifference = Math.abs(bY - fY);
|
||||
// Color difference calculation is simplified because black is 0 for R,G,B.
|
||||
let colorDifference = windowFrameColor[0] + windowFrameColor[1] + windowFrameColor[2];
|
||||
|
||||
// Brightness is defined within {0, 255}. Set an attribute
|
||||
// if the window frame color doesn't reach these thresholds
|
||||
// so the theme can be adjusted for readability.
|
||||
if (brightnessDifference < brightnessThreshold && colorDifference < colorThreshold) {
|
||||
document.documentElement.setAttribute("darkwindowframe", "true");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SessionStore.promiseInitialized.then(() => {
|
||||
// Bail out if the window has been closed in the meantime.
|
||||
if (window.closed) {
|
||||
|
|
|
@ -300,6 +300,11 @@ const CustomizableWidgets = [{
|
|||
|
||||
let item;
|
||||
if (node.localName == "menuseparator") {
|
||||
// Don't insert duplicate or leading separators. This can happen if there are
|
||||
// menus (which we don't copy) above the separator.
|
||||
if (!fragment.lastChild || fragment.lastChild.localName == "menuseparator") {
|
||||
continue;
|
||||
}
|
||||
item = doc.createElementNS(kNSXUL, "menuseparator");
|
||||
} else if (node.localName == "menuitem") {
|
||||
item = doc.createElementNS(kNSXUL, "toolbarbutton");
|
||||
|
|
|
@ -81,4 +81,5 @@ skip-if = os == "linux"
|
|||
[browser_978084_dragEnd_after_move.js]
|
||||
[browser_980155_add_overflow_toolbar.js]
|
||||
[browser_981418-widget-onbeforecreated-handler.js]
|
||||
[browser_981305_separator_insertion.js]
|
||||
[browser_panel_toggle.js]
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let tempElements = [];
|
||||
// Shouldn't insert multiple separators into the developer tools subview
|
||||
add_task(function testMultipleDevtoolsSeparators() {
|
||||
let devtoolsSubMenu = document.getElementById("menuWebDeveloperPopup");
|
||||
// Last element is null to insert at the end:
|
||||
let beforeEls = [devtoolsSubMenu.firstChild, devtoolsSubMenu.lastChild, null];
|
||||
for (let i = 0; i < beforeEls.length; i++) {
|
||||
let sep = document.createElement("menuseparator");
|
||||
tempElements.push(sep);
|
||||
devtoolsSubMenu.insertBefore(sep, beforeEls[i]);
|
||||
let menu = document.createElement("menu");
|
||||
tempElements.push(menu);
|
||||
devtoolsSubMenu.insertBefore(menu, beforeEls[i]);
|
||||
// And another separator for good measure:
|
||||
sep = document.createElement("menuseparator");
|
||||
tempElements.push(sep);
|
||||
devtoolsSubMenu.insertBefore(sep, beforeEls[i]);
|
||||
}
|
||||
yield PanelUI.show();
|
||||
|
||||
let devtoolsButton = document.getElementById("developer-button");
|
||||
devtoolsButton.click();
|
||||
yield waitForCondition(() => !PanelUI.multiView.hasAttribute("transitioning"));
|
||||
let subview = document.getElementById("PanelUI-developerItems");
|
||||
ok(subview.firstChild, "Subview should have a kid");
|
||||
is(subview.firstChild.localName, "toolbarbutton", "There should be no separators to start with");
|
||||
|
||||
for (let kid of subview.children) {
|
||||
if (kid.localName == "menuseparator") {
|
||||
ok(kid.previousSibling && kid.previousSibling.localName != "menuseparator",
|
||||
"Separators should never have another separator next to them, and should never be the first node.");
|
||||
}
|
||||
}
|
||||
|
||||
let panelHiddenPromise = promisePanelHidden(window);
|
||||
PanelUI.hide();
|
||||
yield panelHiddenPromise;
|
||||
});
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
for (let el of tempElements) {
|
||||
el.remove();
|
||||
}
|
||||
tempElements = null;
|
||||
});
|
|
@ -10,7 +10,6 @@ const Cu = Components.utils;
|
|||
const Cr = Components.results;
|
||||
|
||||
const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
|
||||
const kRegMultiSz = 7;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -21,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
|
||||
"resource://gre/modules/ctypes.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
|
||||
"resource://gre/modules/WindowsRegistry.jsm");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Helpers.
|
||||
|
@ -126,45 +127,6 @@ function hostIsIPAddress(aHost) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely reads a value from the registry.
|
||||
*
|
||||
* @param aRoot
|
||||
* The root registry to use.
|
||||
* @param aPath
|
||||
* The registry path to the key.
|
||||
* @param aKey
|
||||
* The key name.
|
||||
* @return The key value or undefined if it doesn't exist. If the key is
|
||||
* a REG_MULTI_SZ, an array is returned.
|
||||
*/
|
||||
function readRegKey(aRoot, aPath, aKey) {
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
registry.open(aRoot, aPath, Ci.nsIWindowsRegKey.ACCESS_READ);
|
||||
if (registry.hasValue(aKey)) {
|
||||
let type = registry.getValueType(aKey);
|
||||
switch (type) {
|
||||
case kRegMultiSz:
|
||||
// nsIWindowsRegKey doesn't support REG_MULTI_SZ type out of the box.
|
||||
let str = registry.readStringValue(aKey);
|
||||
return [v for each (v in str.split("\0")) if (v)];
|
||||
case Ci.nsIWindowsRegKey.TYPE_STRING:
|
||||
return registry.readStringValue(aKey);
|
||||
case Ci.nsIWindowsRegKey.TYPE_INT:
|
||||
return registry.readIntValue(aKey);
|
||||
default:
|
||||
throw new Error("Unsupported registry value.");
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Resources
|
||||
|
||||
|
@ -192,9 +154,9 @@ Bookmarks.prototype = {
|
|||
// Retrieve the name of IE's favorites subfolder that holds the bookmarks
|
||||
// in the toolbar. This was previously stored in the registry and changed
|
||||
// in IE7 to always be called "Links".
|
||||
let folderName = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Internet Explorer\\Toolbar",
|
||||
"LinksFolderName");
|
||||
let folderName = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Internet Explorer\\Toolbar",
|
||||
"LinksFolderName");
|
||||
this.__toolbarFolderName = folderName || "Links";
|
||||
}
|
||||
return this.__toolbarFolderName;
|
||||
|
@ -605,8 +567,8 @@ Settings.prototype = {
|
|||
* Conversion function from the Registry format to the pref format.
|
||||
*/
|
||||
_set: function S__set(aPath, aKey, aPref, aTransformFn) {
|
||||
let value = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
aPath, aKey);
|
||||
let value = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
aPath, aKey);
|
||||
// Don't import settings that have never been flipped.
|
||||
if (value === undefined)
|
||||
return;
|
||||
|
@ -651,10 +613,10 @@ IEProfileMigrator.prototype.getResources = function IE_getResources() {
|
|||
|
||||
Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", {
|
||||
get: function IE_get_sourceHomePageURL() {
|
||||
let defaultStartPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
kMainKey, "Default_Page_URL");
|
||||
let startPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
kMainKey, "Start Page");
|
||||
let defaultStartPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
|
||||
kMainKey, "Default_Page_URL");
|
||||
let startPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
kMainKey, "Start Page");
|
||||
// If the user didn't customize the Start Page, he is still on the default
|
||||
// page, that may be considered the equivalent of our about:home. There's
|
||||
// no reason to retain it, since it is heavily targeted to IE.
|
||||
|
@ -664,8 +626,8 @@ Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", {
|
|||
// are in addition to the Start Page, and no empty entries are possible,
|
||||
// thus a Start Page is always defined if any of these exists, though it
|
||||
// may be the default one.
|
||||
let secondaryPages = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
kMainKey, "Secondary Start Pages");
|
||||
let secondaryPages = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
kMainKey, "Secondary Start Pages");
|
||||
if (secondaryPages) {
|
||||
if (homepage)
|
||||
secondaryPages.unshift(homepage);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
browser.jar:
|
||||
content/browser/translation-infobar.xml
|
|
@ -10,6 +10,12 @@ EXTRA_JS_MODULES = [
|
|||
'LanguageDetector.jsm'
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/browser.ini'
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'test/xpcshell.ini'
|
||||
]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[DEFAULT]
|
||||
|
||||
[browser_translation_infobar.js]
|
|
@ -0,0 +1,155 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// tests the translation infobar, using a fake 'Translation' implementation.
|
||||
|
||||
var Translation = {
|
||||
supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
|
||||
supportedTargetLanguages: ["en", "pl", "tr", "vi"],
|
||||
defaultTargetLanguage: "en",
|
||||
|
||||
_translateFrom: "",
|
||||
_translateTo: "",
|
||||
_deferred: null,
|
||||
translate: function(aFrom, aTo) {
|
||||
this._translateFrom = aFrom;
|
||||
this._translateTo = aTo;
|
||||
this._deferred = Promise.defer();
|
||||
return this._deferred.promise;
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
this._translateFrom = "";
|
||||
this._translateTo = "";
|
||||
this._deferred = null;
|
||||
},
|
||||
|
||||
failTranslation: function() {
|
||||
this._deferred.reject();
|
||||
this._reset();
|
||||
},
|
||||
|
||||
finishTranslation: function() {
|
||||
this._deferred.resolve();
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_showOriginalCalled: false,
|
||||
showOriginalContent: function() {
|
||||
this._showOriginalCalled = true;
|
||||
},
|
||||
|
||||
_showTranslationCalled: false,
|
||||
showTranslatedContent: function() {
|
||||
this._showTranslationCalled = true;
|
||||
},
|
||||
|
||||
showTranslationUI: function(aLanguage) {
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
let notif = notificationBox.appendNotification("", "translation", null,
|
||||
notificationBox.PRIORITY_INFO_HIGH);
|
||||
notif.init(this);
|
||||
notif.detectedLanguage = aLanguage;
|
||||
return notif;
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Show an info bar saying the current page is in French
|
||||
let notif = Translation.showTranslationUI("fr");
|
||||
is(notif.state, notif.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
|
||||
// Click the "Translate" button
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!Translation._deferred, "Translation.translate has been called");
|
||||
is(Translation._translateFrom, "fr", "from language correct");
|
||||
is(Translation._translateTo, Translation.defaultTargetLanguage, "from language correct");
|
||||
|
||||
// Make the translation fail and check we are in the error state.
|
||||
Translation.failTranslation();
|
||||
is(notif.state, notif.STATE_ERROR, "infobar in the error state");
|
||||
|
||||
// Click the try again button
|
||||
notif._getAnonElt("tryAgain").click();
|
||||
is(notif.state, notif.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!Translation._deferred, "Translation.translate has been called");
|
||||
is(Translation._translateFrom, "fr", "from language correct");
|
||||
is(Translation._translateTo, Translation.defaultTargetLanguage, "to language correct");
|
||||
|
||||
// Make the translation succeed and check we are in the 'translated' state.
|
||||
Translation.finishTranslation();
|
||||
is(notif.state, notif.STATE_TRANSLATED, "infobar in the translated state");
|
||||
|
||||
// Test 'Show Original' / 'Show Translation' buttons.
|
||||
// First check 'Show Original' is visible and 'Show Translation' is hidden.
|
||||
ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible");
|
||||
ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden");
|
||||
// Click the button.
|
||||
notif._getAnonElt("showOriginal").click();
|
||||
// Check the correct function has been called.
|
||||
ok(Translation._showOriginalCalled, "'Translation.showOriginalContent' called")
|
||||
ok(!Translation._showTranslationCalled, "'Translation.showTranslatedContent' not called")
|
||||
Translation._showOriginalCalled = false;
|
||||
// And the 'Show Translation' button is now visible.
|
||||
ok(notif._getAnonElt("showOriginal").hidden, "'Show Original' button hidden");
|
||||
ok(!notif._getAnonElt("showTranslation").hidden, "'Show Translation' button visible");
|
||||
// Click the 'Show Translation' button
|
||||
notif._getAnonElt("showTranslation").click();
|
||||
// Check the correct function has been called.
|
||||
ok(!Translation._showOriginalCalled, "'Translation.showOriginalContent' not called")
|
||||
ok(Translation._showTranslationCalled, "'Translation.showTranslatedContent' called")
|
||||
Translation._showTranslationCalled = false;
|
||||
// Check that the 'Show Original' button is visible again.
|
||||
ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible");
|
||||
ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden");
|
||||
|
||||
// Check that changing the source language causes a re-translation
|
||||
let from = notif._getAnonElt("fromLanguage");
|
||||
from.value = "es";
|
||||
from.doCommand();
|
||||
is(notif.state, notif.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!Translation._deferred, "Translation.translate has been called");
|
||||
is(Translation._translateFrom, "es", "from language correct");
|
||||
is(Translation._translateTo, Translation.defaultTargetLanguage, "to language correct");
|
||||
Translation.finishTranslation();
|
||||
|
||||
// Check that changing the target language causes a re-translation
|
||||
let to = notif._getAnonElt("toLanguage");
|
||||
to.value = "pl";
|
||||
to.doCommand();
|
||||
is(notif.state, notif.STATE_TRANSLATING, "infobar in the translating state");
|
||||
ok(!!Translation._deferred, "Translation.translate has been called");
|
||||
is(Translation._translateFrom, "es", "from language correct");
|
||||
is(Translation._translateTo, "pl", "to language correct");
|
||||
Translation.finishTranslation();
|
||||
|
||||
// Cleanup.
|
||||
notif.close();
|
||||
|
||||
// Reopen the info bar to check that it's possible to override the detected language.
|
||||
notif = Translation.showTranslationUI("fr");
|
||||
is(notif.state, notif.STATE_OFFER, "the infobar is offering translation");
|
||||
is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
|
||||
// Change the language and click 'Translate'
|
||||
notif._getAnonElt("detectedLanguage").value = "ja";
|
||||
notif._getAnonElt("translate").click();
|
||||
is(notif.state, notif.STATE_TRANSLATING, "the infobar is in the translating state");
|
||||
ok(!!Translation._deferred, "Translation.translate has been called");
|
||||
is(Translation._translateFrom, "ja", "from language correct");
|
||||
notif.close();
|
||||
|
||||
// Reopen one last time to check the 'Not Now' button closes the notification.
|
||||
notif = Translation.showTranslationUI("fr");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
ok(!!notificationBox.getNotificationWithValue("translation"), "there's a 'translate' notification");
|
||||
notif._getAnonElt("notNow").click();
|
||||
ok(!notificationBox.getNotificationWithValue("translation"), "no 'translate' notification after clicking 'not now'");
|
||||
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
|
||||
%notificationDTD;
|
||||
<!ENTITY % translationDTD SYSTEM "chrome://browser/locale/translation.dtd" >
|
||||
%translationDTD;
|
||||
]>
|
||||
|
||||
<bindings id="translationBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
<binding id="translationbar" extends="chrome://global/content/bindings/notification.xml#notification" role="xul:alert">
|
||||
<resources>
|
||||
<stylesheet src="chrome://global/skin/notification.css"/>
|
||||
</resources>
|
||||
<content>
|
||||
<xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
|
||||
<xul:hbox anonid="details" align="center" flex="1">
|
||||
<xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image,type,value"/>
|
||||
<xul:deck anonid="translationStates" selectedIndex="0">
|
||||
|
||||
<!-- offer to translate -->
|
||||
<xul:hbox class="translate-offer-box" align="baseline">
|
||||
<xul:label value="&translation.thisPageIsIn.label;"/>
|
||||
<xul:menulist anonid="detectedLanguage">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:label value="&translation.translateThisPage.label;"/>
|
||||
<xul:button label="&translation.translate.button;" anonid="translate"
|
||||
oncommand="document.getBindingParent(this).translate();"/>
|
||||
<xul:button label="&translation.notNow.button;" anonid="notNow"
|
||||
oncommand="document.getBindingParent(this).close();"/>
|
||||
</xul:hbox>
|
||||
|
||||
<!-- translating -->
|
||||
<xul:vbox class="translating-box" pack="center">
|
||||
<xul:label value="&translation.translatingContent.label;"/>
|
||||
</xul:vbox>
|
||||
|
||||
<!-- translated -->
|
||||
<xul:hbox class="translated-box" align="baseline">
|
||||
<xul:label value="&translation.translatedFrom.label;"/>
|
||||
<xul:menulist anonid="fromLanguage"
|
||||
oncommand="document.getBindingParent(this).translate()">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:label value="&translation.translatedTo.label;"/>
|
||||
<xul:menulist anonid="toLanguage"
|
||||
oncommand="document.getBindingParent(this).translate()">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
<xul:button anonid="showOriginal"
|
||||
label="&translation.showOriginal.button;"
|
||||
oncommand="document.getBindingParent(this).showOriginal();"/>
|
||||
<xul:button anonid="showTranslation"
|
||||
label="&translation.showTranslation.button;"
|
||||
oncommand="document.getBindingParent(this).showTranslation();"/>
|
||||
</xul:hbox>
|
||||
|
||||
<!-- error -->
|
||||
<xul:hbox class="translation-error" align="baseline">
|
||||
<xul:label value="&translation.errorTranslating.label;"/>
|
||||
<xul:button label="&translation.tryAgain.button;" anonid="tryAgain"
|
||||
oncommand="document.getBindingParent(this).translate();"/>
|
||||
</xul:hbox>
|
||||
|
||||
</xul:deck>
|
||||
<xul:spacer flex="1"/>
|
||||
|
||||
<xul:button type="menu" label="&translation.options.menu;">
|
||||
<xul:menupopup/>
|
||||
</xul:button>
|
||||
|
||||
</xul:hbox>
|
||||
<xul:toolbarbutton ondblclick="event.stopPropagation();"
|
||||
class="messageCloseButton close-icon tabbable"
|
||||
xbl:inherits="hidden=hideclose"
|
||||
tooltiptext="&closeNotification.tooltip;"
|
||||
oncommand="document.getBindingParent(this).close();"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="STATE_OFFER" readonly="true">0</field>
|
||||
<field name="STATE_TRANSLATING" readonly="true">1</field>
|
||||
<field name="STATE_TRANSLATED" readonly="true">2</field>
|
||||
<field name="STATE_ERROR" readonly="true">3</field>
|
||||
|
||||
<property name="state"
|
||||
onget="return this._getAnonElt('translationStates').selectedIndex;"
|
||||
onset="this._getAnonElt('translationStates').selectedIndex = val;"/>
|
||||
|
||||
<!-- Initialize the infobar with a translation object exposing these
|
||||
properties:
|
||||
- supportedSourceLanguages, array of supported source language codes
|
||||
- supportedTargetLanguages, array of supported target language codes
|
||||
- defaultTargetLanguage, code of the language to use by default for
|
||||
translation.
|
||||
- translate, method starting the translation of the current page.
|
||||
Returns a promise.
|
||||
- showOriginalContent, method showing the original page content.
|
||||
- showTranslatedContent, method showing the translation for an
|
||||
already translated page whose original content is shown.
|
||||
-->
|
||||
<method name="init">
|
||||
<parameter name="aTranslation"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.translation = aTranslation;
|
||||
let bundle = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://global/locale/languageNames.properties");
|
||||
|
||||
let detectedLanguage = this._getAnonElt("detectedLanguage");
|
||||
let fromLanguage = this._getAnonElt("fromLanguage");
|
||||
for (let code of this.translation.supportedSourceLanguages) {
|
||||
let name = bundle.GetStringFromName(code);
|
||||
detectedLanguage.appendItem(name, code);
|
||||
fromLanguage.appendItem(name, code);
|
||||
}
|
||||
|
||||
let toLanguage = this._getAnonElt("toLanguage");
|
||||
for (let code of this.translation.supportedTargetLanguages)
|
||||
toLanguage.appendItem(bundle.GetStringFromName(code), code);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_getAnonElt">
|
||||
<parameter name="aAnonId"/>
|
||||
<body>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", aAnonId);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<field name="_detectedLanguage">""</field>
|
||||
<property name="detectedLanguage" onget="return this._detectedLanguage;">
|
||||
<setter><![CDATA[
|
||||
this._getAnonElt("detectedLanguage").value = val;
|
||||
this._detectedLanguage = val;
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="translate">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.state == this.STATE_OFFER) {
|
||||
this._getAnonElt("fromLanguage").value =
|
||||
this._getAnonElt("detectedLanguage").value;
|
||||
this._getAnonElt("toLanguage").value =
|
||||
this.translation.defaultTargetLanguage;
|
||||
}
|
||||
|
||||
this._getAnonElt("showOriginal").hidden = false;
|
||||
this._getAnonElt("showTranslation").hidden = true;
|
||||
|
||||
this.state = this.STATE_TRANSLATING;
|
||||
this.translation.translate(this._getAnonElt("fromLanguage").value,
|
||||
this._getAnonElt("toLanguage").value)
|
||||
.then(() => { this.state = this.STATE_TRANSLATED; },
|
||||
() => { this.state = this.STATE_ERROR; });
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showOriginal">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._getAnonElt("showOriginal").hidden = true;
|
||||
this._getAnonElt("showTranslation").hidden = false;
|
||||
|
||||
this.translation.showOriginalContent();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showTranslation">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._getAnonElt("showOriginal").hidden = false;
|
||||
this._getAnonElt("showTranslation").hidden = true;
|
||||
|
||||
this.translation.showTranslatedContent();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -0,0 +1,20 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!ENTITY translation.thisPageIsIn.label "This page is in">
|
||||
<!ENTITY translation.translateThisPage.label "Translate this page?">
|
||||
<!ENTITY translation.translate.button "Translate">
|
||||
<!ENTITY translation.notNow.button "Not Now">
|
||||
|
||||
<!ENTITY translation.translatingContent.label "Translating page content…">
|
||||
|
||||
<!ENTITY translation.translatedFrom.label "This page has been translated from">
|
||||
<!ENTITY translation.translatedTo.label "to">
|
||||
<!ENTITY translation.showOriginal.button "Show Original">
|
||||
<!ENTITY translation.showTranslation.button "Show Translation">
|
||||
|
||||
<!ENTITY translation.errorTranslating.label "There has been an error translating this page.">
|
||||
<!ENTITY translation.tryAgain.button "Try Again">
|
||||
|
||||
<!ENTITY translation.options.menu "Options">
|
|
@ -76,6 +76,7 @@
|
|||
locale/browser/tabbrowser.properties (%chrome/browser/tabbrowser.properties)
|
||||
locale/browser/tabview.properties (%chrome/browser/tabview.properties)
|
||||
locale/browser/taskbar.properties (%chrome/browser/taskbar.properties)
|
||||
locale/browser/translation.dtd (%chrome/browser/translation.dtd)
|
||||
locale/browser/downloads/downloads.dtd (%chrome/browser/downloads/downloads.dtd)
|
||||
locale/browser/downloads/downloads.properties (%chrome/browser/downloads/downloads.properties)
|
||||
locale/browser/places/places.dtd (%chrome/browser/places/places.dtd)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Windows8WindowFrameColor"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/WindowsRegistry.jsm");
|
||||
|
||||
const Windows8WindowFrameColor = {
|
||||
_windowFrameColor: null,
|
||||
|
||||
get: function() {
|
||||
if (this._windowFrameColor)
|
||||
return this._windowFrameColor;
|
||||
|
||||
let windowFrameColor = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Windows\\DWM",
|
||||
"ColorizationColor");
|
||||
// The color returned from the Registry is in decimal form.
|
||||
let windowFrameColorHex = windowFrameColor.toString(16);
|
||||
// Zero-pad the number just to make sure that it is 8 digits.
|
||||
windowFrameColorHex = ("00000000" + windowFrameColorHex).substr(-8);
|
||||
let windowFrameColorArray = windowFrameColorHex.match(/../g);
|
||||
let [pixelA, pixelR, pixelG, pixelB] = windowFrameColorArray.map(function(val) parseInt(val, 16));
|
||||
|
||||
return this._windowFrameColor = [pixelR, pixelG, pixelB];
|
||||
},
|
||||
};
|
|
@ -26,6 +26,7 @@ EXTRA_JS_MODULES += [
|
|||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXTRA_JS_MODULES += [
|
||||
'Windows8WindowFrameColor.jsm',
|
||||
'WindowsJumpLists.jsm',
|
||||
'WindowsPreviewPerTab.jsm',
|
||||
]
|
||||
|
|
|
@ -292,6 +292,7 @@ browser.jar:
|
|||
skin/classic/browser/sync-notification-24.png
|
||||
skin/classic/browser/syncProgress-menuPanel.png
|
||||
skin/classic/browser/syncProgress-toolbar.png
|
||||
skin/classic/browser/syncProgress-toolbar-inverted.png
|
||||
skin/classic/browser/syncSetup.css
|
||||
skin/classic/browser/syncCommon.css
|
||||
skin/classic/browser/syncQuota.css
|
||||
|
|
Двоичные данные
browser/themes/linux/syncProgress-horizontalbar.png
До Ширина: | Высота: | Размер: 535 B После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
browser/themes/linux/syncProgress-menuPanel.png
До Ширина: | Высота: | Размер: 1.1 KiB После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 14 KiB |
Двоичные данные
browser/themes/linux/syncProgress-toolbar.png
До Ширина: | Высота: | Размер: 623 B После Ширина: | Высота: | Размер: 13 KiB |
|
@ -841,6 +841,17 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||
-moz-image-region: rect(36px, 540px, 72px, 504px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="toolbar"][status="active"],
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:hover:active:not([disabled="true"]) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar@2x.png");
|
||||
-moz-image-region: rect(0, 36px, 36px, 0px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:-moz-lwtheme-brighttext,
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:-moz-lwtheme-brighttext:hover:active:not([disabled="true"]) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted@2x.png");
|
||||
}
|
||||
|
||||
#feed-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 576px, 36px, 540px);
|
||||
}
|
||||
|
@ -1092,6 +1103,11 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||
-moz-image-region: rect(0px, 768px, 64px, 704px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="menu-panel"][status="active"] {
|
||||
list-style-image: url(chrome://browser/skin/syncProgress-menuPanel@2x.png);
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#feed-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #feed-button {
|
||||
-moz-image-region: rect(0px, 832px, 64px, 768px);
|
||||
|
@ -1593,13 +1609,6 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
margin: 2px;
|
||||
}
|
||||
|
||||
/* sync button */
|
||||
|
||||
#sync-button[status="active"] {
|
||||
list-style-image: url("chrome://browser/skin/sync-throbber.png");
|
||||
-moz-image-region: rect(0, 20px, 20px, 0px);
|
||||
}
|
||||
|
||||
/* ----- FULLSCREEN WINDOW CONTROLS ----- */
|
||||
|
||||
#minimize-button,
|
||||
|
|
|
@ -401,7 +401,6 @@ browser.jar:
|
|||
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
skin/classic/browser/sync-bg.png
|
||||
|
@ -417,6 +416,12 @@ browser.jar:
|
|||
skin/classic/browser/syncProgress.css
|
||||
skin/classic/browser/syncProgress-horizontalbar.png
|
||||
skin/classic/browser/syncProgress-horizontalbar@2x.png
|
||||
skin/classic/browser/syncProgress-menuPanel.png
|
||||
skin/classic/browser/syncProgress-menuPanel@2x.png
|
||||
skin/classic/browser/syncProgress-toolbar.png
|
||||
skin/classic/browser/syncProgress-toolbar@2x.png
|
||||
skin/classic/browser/syncProgress-toolbar-inverted.png
|
||||
skin/classic/browser/syncProgress-toolbar-inverted@2x.png
|
||||
#endif
|
||||
skin/classic/browser/Toolbar-background-noise.png (Toolbar-background-noise.png)
|
||||
skin/classic/browser/lion/toolbarbutton-dropmarker.png (toolbarbutton-dropmarker-lion.png)
|
||||
|
|
Двоичные данные
browser/themes/osx/sync-throbber.png
До Ширина: | Высота: | Размер: 7.7 KiB |
Двоичные данные
browser/themes/osx/syncProgress-horizontalbar.png
До Ширина: | Высота: | Размер: 537 B После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
browser/themes/osx/syncProgress-horizontalbar@2x.png
До Ширина: | Высота: | Размер: 1.0 KiB После Ширина: | Высота: | Размер: 27 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 55 KiB |
После Ширина: | Высота: | Размер: 14 KiB |
После Ширина: | Высота: | Размер: 31 KiB |
После Ширина: | Высота: | Размер: 13 KiB |
После Ширина: | Высота: | Размер: 33 KiB |
|
@ -54,6 +54,11 @@ toolbarpaletteitem[place="palette"] > #sync-button {
|
|||
-moz-image-region: rect(0px, 384px, 32px, 352px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="menu-panel"][status="active"] {
|
||||
list-style-image: url(chrome://browser/skin/syncProgress-menuPanel.png);
|
||||
-moz-image-region: rect(0px, 32px, 32px, 0px);
|
||||
}
|
||||
|
||||
#feed-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #feed-button {
|
||||
-moz-image-region: rect(0px, 416px, 32px, 384px);
|
||||
|
|
|
@ -56,6 +56,17 @@
|
|||
-moz-image-region: rect(0, 270px, 18px, 252px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="toolbar"][status="active"],
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:hover:active:not([disabled="true"]) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar.png");
|
||||
-moz-image-region: rect(0, 18px, 18px, 0px);
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:-moz-lwtheme-brighttext,
|
||||
#sync-button[cui-areatype="toolbar"][status="active"]:-moz-lwtheme-brighttext:hover:active:not([disabled="true"]) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
|
||||
}
|
||||
|
||||
#feed-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 288px, 18px, 270px);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,39 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) {
|
||||
.sidebar-header,
|
||||
#sidebar-header {
|
||||
-moz-appearance: none;
|
||||
color: black;
|
||||
background-color: #EEF3FA;
|
||||
border-bottom: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.sidebar-title,
|
||||
#sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sidebar-splitter {
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid #A9B7C9;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#appcontent ~ .sidebar-splitter {
|
||||
-moz-border-start: 1px solid #A9B7C9;
|
||||
-moz-border-end: none;
|
||||
-moz-margin-start: 0;
|
||||
-moz-margin-end: -3px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) and (-moz-os-version: windows-vista),
|
||||
(-moz-windows-default-theme) and (-moz-os-version: windows-win7) {
|
||||
#navigator-toolbox > toolbar:not(:-moz-lwtheme),
|
||||
|
@ -52,37 +85,6 @@
|
|||
border-color: hsla(206,100%,60%,.65) hsla(206,100%,55%,.65) hsla(206,100%,50%,.65);
|
||||
}
|
||||
|
||||
.sidebar-header,
|
||||
#sidebar-header {
|
||||
-moz-appearance: none;
|
||||
color: black;
|
||||
background-color: #EEF3FA;
|
||||
border-bottom: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.sidebar-title,
|
||||
#sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sidebar-splitter {
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid #A9B7C9;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#appcontent ~ .sidebar-splitter {
|
||||
-moz-border-start: 1px solid #A9B7C9;
|
||||
-moz-border-end: none;
|
||||
-moz-margin-start: 0;
|
||||
-moz-margin-end: -3px;
|
||||
}
|
||||
|
||||
.menu-accel,
|
||||
.menu-iconic-accel {
|
||||
color: graytext;
|
||||
|
@ -136,6 +138,32 @@
|
|||
border-right-style: none !important;
|
||||
}
|
||||
|
||||
#main-window[darkwindowframe="true"] #toolbar-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive),
|
||||
#main-window[darkwindowframe="true"] #TabsToolbar:not(:-moz-lwtheme):not(:-moz-window-inactive) {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) :-moz-any(@primaryToolbarButtons@):not(:-moz-lwtheme):not(:-moz-window-inactive),
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) #bookmarks-menu-button:not(:-moz-lwtheme) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:not(:-moz-window-inactive) {
|
||||
list-style-image: url(chrome://browser/skin/Toolbar-inverted.png);
|
||||
}
|
||||
|
||||
#main-window[darkwindowframe="true"] .tabs-newtab-button:not(:-moz-lwtheme):not(:-moz-window-inactive),
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > #new-tab-button:not(:-moz-lwtheme):not(:-moz-window-inactive),
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > toolbarpaletteitem > #new-tab-button:not(:-moz-lwtheme):not(:-moz-window-inactive) {
|
||||
list-style-image: url(chrome://browser/skin/tabbrowser/newtab-inverted.png);
|
||||
}
|
||||
|
||||
#main-window[darkwindowframe="true"] .tab-close-button:not(:-moz-any(:hover, [selected="true"], :-moz-lwtheme, :-moz-window-inactive)) {
|
||||
-moz-image-region: rect(0, 64px, 16px, 48px);
|
||||
}
|
||||
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > #sync-button[status="active"]:not(:-moz-lwtheme),
|
||||
#main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > toolbarpaletteitem > #sync-button[status="active"]:not(:-moz-lwtheme) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
|
||||
}
|
||||
|
||||
|
||||
#toolbar-menubar:not(:-moz-lwtheme) {
|
||||
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
|
||||
}
|
||||
|
@ -195,6 +223,7 @@
|
|||
|
||||
#main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) {
|
||||
background-color: rgba(255,255,255,.5);
|
||||
color: black;
|
||||
}
|
||||
|
||||
@media (-moz-os-version: windows-vista),
|
||||
|
@ -242,6 +271,11 @@
|
|||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
|
||||
#toolbar-menubar > #sync-button[status="active"]:not(:-moz-lwtheme),
|
||||
#toolbar-menubar > toolbarpaletteitem > #sync-button[status="active"]:not(:-moz-lwtheme) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
|
||||
}
|
||||
|
||||
/* Glass Fog */
|
||||
|
||||
#TabsToolbar:not(:-moz-lwtheme) {
|
||||
|
@ -341,8 +375,6 @@
|
|||
/* Introducing an additional hover state for the Bookmark button */
|
||||
#nav-bar .toolbarbutton-1[buttonover] > .toolbarbutton-menubutton-button:hover > .toolbarbutton-icon {
|
||||
background-color: hsla(210,4%,10%,.08);
|
||||
-moz-border-end: 1px solid;
|
||||
-moz-padding-end: 5px;
|
||||
border-color: hsla(210,4%,10%,.1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,8 @@
|
|||
%endif
|
||||
|
||||
/* Make the menu inherit the toolbar's color. On non-compositor (Aero Basic, XP modern, classic)
|
||||
* this is defined above. Otherwise (Aero Glass, Windows 8), this is hardcoded to black in
|
||||
* browser-aero.css. */
|
||||
* this is defined above. Otherwise (Aero Glass, Windows 8 inactive windows), this is hardcoded
|
||||
* to black in browser-aero.css. */
|
||||
#main-menubar > menu:not(:-moz-lwtheme) {
|
||||
color: inherit;
|
||||
}
|
||||
|
@ -157,6 +157,11 @@
|
|||
box-shadow: 0 0 50px 8px InactiveCaption;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar]:not([sizemode=fullscreen]) toolbar[customindex]:not(:-moz-lwtheme),
|
||||
#main-window[tabsintitlebar]:not([sizemode=fullscreen]) #PersonalToolbar:not(:-moz-lwtheme) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Need to constrain the box shadow fade to avoid overlapping layers, see bug 886281. */
|
||||
#main-window[tabsintitlebar]:not([sizemode=fullscreen]) #navigator-toolbox:not(:-moz-lwtheme) {
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
|
@ -671,7 +676,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-text,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-badge-container,
|
||||
|
@ -969,12 +974,9 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
|
||||
#sync-button[cui-areatype="toolbar"][status="active"] {
|
||||
/* !important because we need to override the glass selectors that trigger
|
||||
* use of the Toolbar-inverted image. Those use a list of all primary toolbar
|
||||
* buttons, so we can't easily fix those selectors. */
|
||||
list-style-image: url("chrome://browser/skin/sync-throbber.png") !important;
|
||||
-moz-image-region: rect(0, 18px, 18px, 0);
|
||||
#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > #sync-button[status="active"]:-moz-system-metric(windows-classic):not(:-moz-lwtheme),
|
||||
#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > #sync-button[status="active"]:-moz-system-metric(windows-classic):not(:-moz-lwtheme) {
|
||||
list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
|
||||
}
|
||||
|
||||
/* tabview button & menu item */
|
||||
|
|
|
@ -312,7 +312,6 @@ browser.jar:
|
|||
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
skin/classic/browser/sync-128.png
|
||||
|
@ -328,6 +327,10 @@ browser.jar:
|
|||
skin/classic/browser/syncProgress.css
|
||||
skin/classic/browser/syncProgress-horizontalbar.png
|
||||
skin/classic/browser/syncProgress-horizontalbar-XPVista7.png
|
||||
skin/classic/browser/syncProgress-menuPanel.png
|
||||
skin/classic/browser/syncProgress-toolbar.png
|
||||
skin/classic/browser/syncProgress-toolbar-inverted.png
|
||||
skin/classic/browser/syncProgress-toolbar-XPVista7.png
|
||||
#endif
|
||||
skin/classic/browser/devtools/tooltip/arrow-horizontal-dark.png (../shared/devtools/tooltip/arrow-horizontal-dark.png)
|
||||
skin/classic/browser/devtools/tooltip/arrow-horizontal-dark@2x.png (../shared/devtools/tooltip/arrow-horizontal-dark@2x.png)
|
||||
|
@ -648,7 +651,6 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/aero/browser/sync-throbber.png
|
||||
skin/classic/aero/browser/sync-16.png
|
||||
skin/classic/aero/browser/sync-32.png
|
||||
skin/classic/aero/browser/sync-128.png
|
||||
|
@ -664,6 +666,10 @@ browser.jar:
|
|||
skin/classic/aero/browser/syncProgress.css
|
||||
skin/classic/aero/browser/syncProgress-horizontalbar.png
|
||||
skin/classic/aero/browser/syncProgress-horizontalbar-XPVista7.png
|
||||
skin/classic/aero/browser/syncProgress-menuPanel.png
|
||||
skin/classic/aero/browser/syncProgress-toolbar.png
|
||||
skin/classic/aero/browser/syncProgress-toolbar-inverted.png
|
||||
skin/classic/aero/browser/syncProgress-toolbar-XPVista7.png
|
||||
#endif
|
||||
#endif
|
||||
skin/classic/aero/browser/devtools/tooltip/arrow-horizontal-dark.png (../shared/devtools/tooltip/arrow-horizontal-dark.png)
|
||||
|
|
|
@ -36,6 +36,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) {
|
||||
#placesView > splitter {
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid #A9B7C9;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) and (-moz-os-version: windows-vista),
|
||||
(-moz-windows-default-theme) and (-moz-os-version: windows-win7) {
|
||||
#placesView,
|
||||
|
@ -50,16 +62,6 @@
|
|||
color: black;
|
||||
}
|
||||
|
||||
#placesView > splitter {
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid #A9B7C9;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#detailsDeck {
|
||||
border-top-color: #A9B7C9;
|
||||
}
|
||||
|
|
Двоичные данные
browser/themes/windows/sync-throbber.png
До Ширина: | Высота: | Размер: 10 KiB |
Двоичные данные
browser/themes/windows/syncProgress-horizontalbar-XPVista7.png
До Ширина: | Высота: | Размер: 535 B После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
browser/themes/windows/syncProgress-horizontalbar.png
До Ширина: | Высота: | Размер: 370 B После Ширина: | Высота: | Размер: 5.3 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 13 KiB |
После Ширина: | Высота: | Размер: 14 KiB |
После Ширина: | Высота: | Размер: 5.4 KiB |
|
@ -7463,7 +7463,7 @@ fi
|
|||
AC_SUBST(MOZ_AUDIO_CHANNEL_MANAGER)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable Support for Firefox Accounts in B2G
|
||||
dnl = Enable Support for Firefox Accounts (services/fxaccounts)
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_SERVICES_FXACCOUNTS"; then
|
||||
AC_DEFINE(MOZ_SERVICES_FXACCOUNTS)
|
||||
|
|
|
@ -53,8 +53,8 @@ interface GeckoEditableListener {
|
|||
final int NOTIFY_IME_REPLY_EVENT = -1;
|
||||
final int NOTIFY_IME_OF_FOCUS = 1;
|
||||
final int NOTIFY_IME_OF_BLUR = 2;
|
||||
final int NOTIFY_IME_TO_COMMIT_COMPOSITION = 4;
|
||||
final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 5;
|
||||
final int NOTIFY_IME_TO_COMMIT_COMPOSITION = 7;
|
||||
final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 8;
|
||||
// IME enabled state for notifyIMEContext()
|
||||
final int IME_STATE_DISABLED = 0;
|
||||
final int IME_STATE_ENABLED = 1;
|
||||
|
|
|
@ -4742,8 +4742,8 @@ var BrowserEventHandler = {
|
|||
let rect = rects[0];
|
||||
// if either width or height is zero, we don't want to move the click to the edge of the element. See bug 757208
|
||||
if (rect.width != 0 && rect.height != 0) {
|
||||
aX = Math.min(Math.floor(rect.left + rect.width), Math.max(Math.ceil(rect.left), aX));
|
||||
aY = Math.min(Math.floor(rect.top + rect.height), Math.max(Math.ceil(rect.top), aY));
|
||||
aX = Math.min(Math.ceil(rect.left + rect.width) - 1, Math.max(Math.ceil(rect.left), aX));
|
||||
aY = Math.min(Math.ceil(rect.top + rect.height) - 1, Math.max(Math.ceil(rect.top), aY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,6 +135,47 @@ for (let [constProp, dirKey] of [
|
|||
*/
|
||||
let clone = SharedAll.clone;
|
||||
|
||||
/**
|
||||
* Extract a shortened version of an object, fit for logging.
|
||||
*
|
||||
* This function returns a copy of the original object in which all
|
||||
* long strings, Arrays, TypedArrays, ArrayBuffers are removed and
|
||||
* replaced with placeholders. Use this function to sanitize objects
|
||||
* if you wish to log them or to keep them in memory.
|
||||
*
|
||||
* @param {*} obj The obj to shorten.
|
||||
* @return {*} array A shorter object, fit for logging.
|
||||
*/
|
||||
function summarizeObject(obj) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
}
|
||||
if (typeof obj == "string") {
|
||||
if (obj.length > 1024) {
|
||||
return {"Long string": obj.length};
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (typeof obj == "object") {
|
||||
if (Array.isArray(obj)) {
|
||||
if (obj.length > 32) {
|
||||
return {"Long array": obj.length};
|
||||
}
|
||||
return [summarizeObject(k) for (k of obj)];
|
||||
}
|
||||
if ("byteLength" in obj) {
|
||||
// Assume TypedArray or ArrayBuffer
|
||||
return {"Binary Data": obj.byteLength};
|
||||
}
|
||||
let result = {};
|
||||
for (let k of Object.keys(obj)) {
|
||||
result[k] = summarizeObject(obj[k]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
let worker = null;
|
||||
let Scheduler = {
|
||||
/**
|
||||
|
@ -157,19 +198,36 @@ let Scheduler = {
|
|||
queue: Promise.resolve(),
|
||||
|
||||
/**
|
||||
* The latest message sent and still waiting for a reply. In DEBUG
|
||||
* builds, the entire message is stored, which may be memory-consuming.
|
||||
* In non-DEBUG builds, only the method name is stored.
|
||||
* Miscellaneous debugging information
|
||||
*/
|
||||
latestSent: undefined,
|
||||
Debugging: {
|
||||
/**
|
||||
* The latest message sent and still waiting for a reply.
|
||||
*/
|
||||
latestSent: undefined,
|
||||
|
||||
/**
|
||||
* The latest reply received, or null if we are waiting for a reply.
|
||||
* In DEBUG builds, the entire response is stored, which may be
|
||||
* memory-consuming. In non-DEBUG builds, only exceptions and
|
||||
* method names are stored.
|
||||
*/
|
||||
latestReceived: undefined,
|
||||
/**
|
||||
* The latest reply received, or null if we are waiting for a reply.
|
||||
*/
|
||||
latestReceived: undefined,
|
||||
|
||||
/**
|
||||
* Number of messages sent to the worker. This includes the
|
||||
* initial SET_DEBUG, if applicable.
|
||||
*/
|
||||
messagesSent: 0,
|
||||
|
||||
/**
|
||||
* Total number of messages ever queued, including the messages
|
||||
* sent.
|
||||
*/
|
||||
messagesQueued: 0,
|
||||
|
||||
/**
|
||||
* Number of messages received from the worker.
|
||||
*/
|
||||
messagesReceived: 0,
|
||||
},
|
||||
|
||||
/**
|
||||
* A timer used to automatically shut down the worker after some time.
|
||||
|
@ -234,6 +292,7 @@ let Scheduler = {
|
|||
if (firstLaunch && SharedAll.Config.DEBUG) {
|
||||
// If we have delayed sending SET_DEBUG, do it now.
|
||||
worker.post("SET_DEBUG", [true]);
|
||||
Scheduler.Debugging.messagesSent++;
|
||||
}
|
||||
|
||||
// By convention, the last argument of any message may be an |options| object.
|
||||
|
@ -242,41 +301,43 @@ let Scheduler = {
|
|||
if (methodArgs) {
|
||||
options = methodArgs[methodArgs.length - 1];
|
||||
}
|
||||
Scheduler.Debugging.messagesQueued++;
|
||||
return this.push(() => Task.spawn(function*() {
|
||||
Scheduler.latestReceived = null;
|
||||
if (OS.Constants.Sys.DEBUG) {
|
||||
// Update possibly memory-expensive debugging information
|
||||
Scheduler.latestSent = [Date.now(), method, ...args];
|
||||
} else {
|
||||
Scheduler.latestSent = [Date.now(), method];
|
||||
}
|
||||
// Update debugging information. As |args| may be quite
|
||||
// expensive, we only keep a shortened version of it.
|
||||
Scheduler.Debugging.latestReceived = null;
|
||||
Scheduler.Debugging.latestSent = [Date.now(), method, summarizeObject(methodArgs)];
|
||||
let data;
|
||||
let reply;
|
||||
let isError = false;
|
||||
try {
|
||||
data = yield worker.post(method, ...args);
|
||||
reply = data;
|
||||
} catch (error if error instanceof PromiseWorker.WorkerError) {
|
||||
reply = error;
|
||||
isError = true;
|
||||
throw EXCEPTION_CONSTRUCTORS[error.data.exn || "OSError"](error.data);
|
||||
} catch (error if error instanceof ErrorEvent) {
|
||||
reply = error;
|
||||
let message = error.message;
|
||||
if (message == "uncaught exception: [object StopIteration]") {
|
||||
throw StopIteration;
|
||||
try {
|
||||
data = yield worker.post(method, ...args);
|
||||
} finally {
|
||||
Scheduler.Debugging.messagesReceived++;
|
||||
}
|
||||
reply = data;
|
||||
} catch (error) {
|
||||
reply = error;
|
||||
isError = true;
|
||||
throw new Error(message, error.filename, error.lineno);
|
||||
if (error instanceof PromiseWorker.WorkerError) {
|
||||
throw EXCEPTION_CONSTRUCTORS[error.data.exn || "OSError"](error.data);
|
||||
}
|
||||
if (error instanceof ErrorEvent) {
|
||||
let message = error.message;
|
||||
if (message == "uncaught exception: [object StopIteration]") {
|
||||
isError = false;
|
||||
throw StopIteration;
|
||||
}
|
||||
throw new Error(message, error.filename, error.lineno);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
Scheduler.latestSent = Scheduler.latestSent.slice(0, 2);
|
||||
if (OS.Constants.Sys.DEBUG) {
|
||||
// Update possibly memory-expensive debugging information
|
||||
Scheduler.latestReceived = [Date.now(), reply];
|
||||
} else if (isError) {
|
||||
Scheduler.latestReceived = [Date.now(), reply.message, reply.fileName, reply.lineNumber];
|
||||
Scheduler.Debugging.latestSent = Scheduler.Debugging.latestSent.slice(0, 2);
|
||||
if (isError) {
|
||||
Scheduler.Debugging.latestReceived = [Date.now(), reply.message, reply.fileName, reply.lineNumber];
|
||||
} else {
|
||||
Scheduler.latestReceived = [Date.now()];
|
||||
Scheduler.Debugging.latestReceived = [Date.now(), summarizeObject(reply)];
|
||||
}
|
||||
if (firstLaunch) {
|
||||
Scheduler._updateTelemetry();
|
||||
|
@ -1381,8 +1442,12 @@ AsyncShutdown.profileBeforeChange.addBlocker(
|
|||
shutdown: Scheduler.shutdown,
|
||||
worker: !!worker,
|
||||
pendingReset: !!Scheduler.resetTimer,
|
||||
latestSent: Scheduler.latestSent,
|
||||
latestReceived: Scheduler.latestReceived
|
||||
latestSent: Scheduler.Debugging.latestSent,
|
||||
latestReceived: Scheduler.Debugging.latestReceived,
|
||||
messagesSent: Scheduler.Debugging.messagesSent,
|
||||
messagesReceived: Scheduler.Debugging.messagesReceived,
|
||||
messagesQueued: Scheduler.Debugging.messagesQueued,
|
||||
DEBUG: SharedAll.Config.DEBUG
|
||||
};
|
||||
// Convert dates to strings for better readability
|
||||
for (let key of ["latestSent", "latestReceived"]) {
|
||||
|
|
|
@ -108,7 +108,7 @@ exports.defineLazyGetter = defineLazyGetter;
|
|||
* The choice of logger can be overridden with Config.TEST.
|
||||
*/
|
||||
let gLogger;
|
||||
if (typeof console != "undefined" && console.log) {
|
||||
if (typeof window != "undefined" && window.console && console.log) {
|
||||
gLogger = console.log.bind(console, "OS");
|
||||
} else {
|
||||
gLogger = function(...args) {
|
||||
|
|
|
@ -802,7 +802,8 @@ ActorPool.prototype = {
|
|||
if (!aActor.actorID) {
|
||||
let prefix = aActor.actorPrefix;
|
||||
if (typeof aActor == "function") {
|
||||
prefix = aActor.prototype.actorPrefix;
|
||||
// typeName is a convention used with protocol.js-based actors
|
||||
prefix = aActor.prototype.actorPrefix || aActor.prototype.typeName;
|
||||
}
|
||||
aActor.actorID = this.conn.allocID(prefix || undefined);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["WindowsRegistry"];
|
||||
|
||||
const WindowsRegistry = {
|
||||
/**
|
||||
* Safely reads a value from the registry.
|
||||
*
|
||||
* @param aRoot
|
||||
* The root registry to use.
|
||||
* @param aPath
|
||||
* The registry path to the key.
|
||||
* @param aKey
|
||||
* The key name.
|
||||
* @return The key value or undefined if it doesn't exist. If the key is
|
||||
* a REG_MULTI_SZ, an array is returned.
|
||||
*/
|
||||
readRegKey: function(aRoot, aPath, aKey) {
|
||||
const kRegMultiSz = 7;
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
registry.open(aRoot, aPath, Ci.nsIWindowsRegKey.ACCESS_READ);
|
||||
if (registry.hasValue(aKey)) {
|
||||
let type = registry.getValueType(aKey);
|
||||
switch (type) {
|
||||
case kRegMultiSz:
|
||||
// nsIWindowsRegKey doesn't support REG_MULTI_SZ type out of the box.
|
||||
let str = registry.readStringValue(aKey);
|
||||
return [v for each (v in str.split("\0")) if (v)];
|
||||
case Ci.nsIWindowsRegKey.TYPE_STRING:
|
||||
return registry.readStringValue(aKey);
|
||||
case Ci.nsIWindowsRegKey.TYPE_INT:
|
||||
return registry.readIntValue(aKey);
|
||||
default:
|
||||
throw new Error("Unsupported registry value.");
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
};
|
|
@ -70,6 +70,12 @@ if 'Android' != CONFIG['OS_TARGET']:
|
|||
'LightweightThemeConsumer.jsm',
|
||||
]
|
||||
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXTRA_JS_MODULES += [
|
||||
'WindowsRegistry.jsm',
|
||||
]
|
||||
|
||||
DEFINES['MOZ_APP_NAME'] = CONFIG['MOZ_APP_NAME']
|
||||
DEFINES['MOZ_BUILD_APP'] = CONFIG['MOZ_BUILD_APP']
|
||||
|
||||
|
|
|
@ -1321,7 +1321,7 @@ function recursiveLastModifiedTime(aFile) {
|
|||
* Directory to look at
|
||||
* @param aSortEntries
|
||||
* True to sort entries by filename
|
||||
* @return An array of nsIFile, or null if aDir is not a readable directory
|
||||
* @return An array of nsIFile, or an empty array if aDir is not a readable directory
|
||||
*/
|
||||
function getDirectoryEntries(aDir, aSortEntries) {
|
||||
let dirEnum;
|
||||
|
@ -1340,10 +1340,13 @@ function getDirectoryEntries(aDir, aSortEntries) {
|
|||
return entries
|
||||
}
|
||||
catch (e) {
|
||||
return null;
|
||||
logger.warn("Can't iterate directory " + aDir.path, e);
|
||||
return [];
|
||||
}
|
||||
finally {
|
||||
dirEnum.close();
|
||||
if (dirEnum) {
|
||||
dirEnum.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1482,8 +1482,7 @@ this.XPIDatabase = {
|
|||
Services.prefs.setCharPref(PREF_EM_ENABLED_ADDONS, enabledAddons.join(","));
|
||||
}
|
||||
catch (e) {
|
||||
logger.error("Failed to write add-ons list to " + addonsListTmp.parent + "/" +
|
||||
FILE_XPI_ADDONS_LIST, e);
|
||||
logger.error("Failed to write add-ons list to profile directory", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -482,6 +482,7 @@ struct SizeConstraints {
|
|||
};
|
||||
|
||||
// IMEMessage is shared by IMEStateManager and TextComposition.
|
||||
// Update values in GeckoEditable.java if you make changes here.
|
||||
// XXX Negative values are used in Android...
|
||||
enum IMEMessage MOZ_ENUM_TYPE(int8_t)
|
||||
{
|
||||
|
|