This commit is contained in:
Wes Kocher 2014-03-21 17:57:23 -07:00
Родитель 06a79a3b5a f0483db35d
Коммит 677c923c03
55 изменённых файлов: 834 добавлений и 164 удалений

Просмотреть файл

@ -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

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 535 B

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
browser/themes/linux/syncProgress-menuPanel.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
browser/themes/linux/syncProgress-toolbar-inverted.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 537 B

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
browser/themes/osx/syncProgress-menuPanel.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
browser/themes/osx/syncProgress-menuPanel@2x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 55 KiB

Двоичные данные
browser/themes/osx/syncProgress-toolbar-inverted.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
browser/themes/osx/syncProgress-toolbar-inverted@2x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 31 KiB

Двоичные данные
browser/themes/osx/syncProgress-toolbar.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
browser/themes/osx/syncProgress-toolbar@2x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 535 B

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 370 B

После

Ширина:  |  Высота:  |  Размер: 5.3 KiB

Двоичные данные
browser/themes/windows/syncProgress-menuPanel.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
browser/themes/windows/syncProgress-toolbar-XPVista7.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
browser/themes/windows/syncProgress-toolbar-inverted.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
browser/themes/windows/syncProgress-toolbar.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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)
{