diff --git a/browser/base/content/aboutaccounts/aboutaccounts.js b/browser/base/content/aboutaccounts/aboutaccounts.js
index f43f0fc831bd..7dca88dc8c2b 100644
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -16,8 +16,6 @@ Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
// for master-password utilities
Cu.import("resource://services-sync/util.js");
-const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
-
const ACTION_URL_PARAM = "action";
const OBSERVER_TOPICS = [
@@ -29,65 +27,6 @@ function log(msg) {
// dump("FXA: " + msg + "\n");
}
-function getPreviousAccountNameHash() {
- try {
- return Services.prefs.getStringPref(PREF_LAST_FXA_USER);
- } catch (_) {
- return "";
- }
-}
-
-function setPreviousAccountNameHash(acctName) {
- Services.prefs.setStringPref(PREF_LAST_FXA_USER, sha256(acctName));
-}
-
-function needRelinkWarning(acctName) {
- let prevAcctHash = getPreviousAccountNameHash();
- return prevAcctHash && prevAcctHash != sha256(acctName);
-}
-
-// Given a string, returns the SHA265 hash in base64
-function sha256(str) {
- let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Ci.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- // Data is an array of bytes.
- let data = converter.convertToByteArray(str, {});
- let hasher = Cc["@mozilla.org/security/hash;1"]
- .createInstance(Ci.nsICryptoHash);
- hasher.init(hasher.SHA256);
- hasher.update(data, data.length);
-
- return hasher.finish(true);
-}
-
-function promptForRelink(acctName) {
- let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
- let continueLabel = sb.GetStringFromName("continue.label");
- let title = sb.GetStringFromName("relinkVerify.title");
- let description = sb.formatStringFromName("relinkVerify.description",
- [acctName], 1);
- let body = sb.GetStringFromName("relinkVerify.heading") +
- "\n\n" + description;
- let ps = Services.prompt;
- let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
- (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
- ps.BUTTON_POS_1_DEFAULT;
- let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
- continueLabel, null, null, null,
- {});
- return pressed == 0; // 0 is the "continue" button
-}
-
-// If the last fxa account used for sync isn't this account, we display
-// a modal dialog checking they really really want to do this...
-// (This is sync-specific, so ideally would be in sync's identity module,
-// but it's a little more seamless to do here, and sync is currently the
-// only fxa consumer, so...
-function shouldAllowRelink(acctName) {
- return !needRelinkWarning(acctName) || promptForRelink(acctName);
-}
-
function updateDisplayedEmail(user) {
let emailDiv = document.getElementById("email");
if (emailDiv && user) {
@@ -112,7 +51,6 @@ var wrapper = {
docShell.addProgressListener(this.iframeListener,
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT |
Ci.nsIWebProgress.NOTIFY_LOCATION);
- iframe.addEventListener("load", this);
// Ideally we'd just merge urlParams with new URL(url).searchParams, but our
// URLSearchParams implementation doesn't support iteration (bug 1085284).
@@ -168,133 +106,7 @@ var wrapper = {
setErrorPage("networkError");
}
},
- },
-
- handleEvent(evt) {
- switch (evt.type) {
- case "load":
- this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
- this.iframe.removeEventListener("load", this);
- break;
- case "FirefoxAccountsCommand":
- this.handleRemoteCommand(evt);
- break;
- }
- },
-
- /**
- * onLogin handler receives user credentials from the jelly after a
- * sucessful login and stores it in the fxaccounts service
- *
- * @param accountData the user's account data and credentials
- */
- onLogin(accountData) {
- log("Received: 'login'. Data:" + JSON.stringify(accountData));
-
- // We don't act on customizeSync anymore, it used to open a dialog inside
- // the browser to selecte the engines to sync but we do it on the web now.
- delete accountData.customizeSync;
- // sessionTokenContext is erroneously sent by the content server.
- // https://github.com/mozilla/fxa-content-server/issues/2766
- // To avoid having the FxA storage manager not knowing what to do with
- // it we delete it here.
- delete accountData.sessionTokenContext;
-
- // We need to confirm a relink - see shouldAllowRelink for more
- let newAccountEmail = accountData.email;
- // The hosted code may have already checked for the relink situation
- // by sending the can_link_account command. If it did, then
- // it will indicate we don't need to ask twice.
- if (!accountData.verifiedCanLinkAccount && !shouldAllowRelink(newAccountEmail)) {
- // we need to tell the page we successfully received the message, but
- // then bail without telling fxAccounts
- this.injectData("message", { status: "login" });
- // after a successful login we return to preferences
- openPrefs();
- return;
- }
- delete accountData.verifiedCanLinkAccount;
-
- // Remember who it was so we can log out next time.
- setPreviousAccountNameHash(newAccountEmail);
-
- // A sync-specific hack - we want to ensure sync has been initialized
- // before we set the signed-in user.
- let xps = Cc["@mozilla.org/weave/service;1"]
- .getService(Ci.nsISupports)
- .wrappedJSObject;
- xps.whenLoaded().then(() => {
- updateDisplayedEmail(accountData);
- return fxAccounts.setSignedInUser(accountData);
- }).then(() => {
- // If the user data is verified, we want it to immediately look like
- // they are signed in without waiting for messages to bounce around.
- if (accountData.verified) {
- openPrefs();
- }
- this.injectData("message", { status: "login" });
- // until we sort out a better UX, just leave the jelly page in place.
- // If the account email is not yet verified, it will tell the user to
- // go check their email, but then it will *not* change state after
- // the verification completes (the browser will begin syncing, but
- // won't notify the user). If the email has already been verified,
- // the jelly will say "Welcome! You are successfully signed in as
- // EMAIL", but it won't then say "syncing started".
- }, (err) => this.injectData("message", { status: "error", error: err })
- );
- },
-
- onCanLinkAccount(accountData) {
- // We need to confirm a relink - see shouldAllowRelink for more
- let ok = shouldAllowRelink(accountData.email);
- this.injectData("message", { status: "can_link_account", data: { ok } });
- },
-
- /**
- * onSignOut handler erases the current user's session from the fxaccounts service
- */
- onSignOut() {
- log("Received: 'sign_out'.");
-
- fxAccounts.signOut().then(
- () => this.injectData("message", { status: "sign_out" }),
- (err) => this.injectData("message", { status: "error", error: err })
- );
- },
-
- handleRemoteCommand(evt) {
- log("command: " + evt.detail.command);
- let data = evt.detail.data;
-
- switch (evt.detail.command) {
- case "login":
- this.onLogin(data);
- break;
- case "can_link_account":
- this.onCanLinkAccount(data);
- break;
- case "sign_out":
- this.onSignOut(data);
- break;
- default:
- log("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
- break;
- }
- },
-
- injectData(type, content) {
- return fxAccounts.promiseAccountsSignUpURI().then(authUrl => {
- let data = {
- type,
- content
- };
- this.iframe.contentWindow.postMessage(data, authUrl);
- })
- .catch(e => {
- console.log("Failed to inject data", e);
- setErrorPage("configError");
- });
- },
+ }
};
diff --git a/browser/base/content/test/sync/accounts_testRemoteCommands.html b/browser/base/content/test/sync/accounts_testRemoteCommands.html
deleted file mode 100644
index 943e1f5fa3fb..000000000000
--- a/browser/base/content/test/sync/accounts_testRemoteCommands.html
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/browser/base/content/test/sync/browser.ini b/browser/base/content/test/sync/browser.ini
index c0e418001e17..b269ffd28adc 100644
--- a/browser/base/content/test/sync/browser.ini
+++ b/browser/base/content/test/sync/browser.ini
@@ -13,4 +13,3 @@ support-files=
skip-if = os == "linux" # Bug 958026
support-files =
content_aboutAccounts.js
- accounts_testRemoteCommands.html
diff --git a/browser/base/content/test/sync/browser_aboutAccounts.js b/browser/base/content/test/sync/browser_aboutAccounts.js
index 3f199f2cc10e..4b2757f7054e 100644
--- a/browser/base/content/test/sync/browser_aboutAccounts.js
+++ b/browser/base/content/test/sync/browser_aboutAccounts.js
@@ -26,44 +26,6 @@ registerCleanupFunction(function() {
});
var gTests = [
-{
- desc: "Test the remote commands",
- async teardown() {
- gBrowser.removeCurrentTab();
- await signOut();
- },
- async run() {
- setPref("identity.fxaccounts.remote.signup.uri",
- "https://example.com/browser/browser/base/content/test/sync/accounts_testRemoteCommands.html");
- let tab = await promiseNewTabLoadEvent("about:accounts");
- let mm = tab.linkedBrowser.messageManager;
-
- let deferred = Promise.defer();
-
- // We'll get a message when openPrefs() is called, which this test should
- // arrange.
- let promisePrefsOpened = promiseOneMessage(tab, "test:openPrefsCalled");
- let results = 0;
- try {
- mm.addMessageListener("test:response", function responseHandler(msg) {
- let data = msg.data.data;
- if (data.type == "testResult") {
- ok(data.pass, data.info);
- results++;
- } else if (data.type == "testsComplete") {
- is(results, data.count, "Checking number of results received matches the number of tests that should have run");
- mm.removeMessageListener("test:response", responseHandler);
- deferred.resolve();
- }
- });
- } catch (e) {
- ok(false, "Failed to get all commands");
- deferred.reject();
- }
- await deferred.promise;
- await promisePrefsOpened;
- }
-},
{
desc: "Test action=signin - no user logged in",
teardown: () => gBrowser.removeCurrentTab(),
diff --git a/browser/components/downloads/content/downloadsOverlay.xul b/browser/components/downloads/content/downloadsOverlay.xul
index fb24f1b8ffaa..0224cd7ad996 100644
--- a/browser/components/downloads/content/downloadsOverlay.xul
+++ b/browser/components/downloads/content/downloadsOverlay.xul
@@ -153,7 +153,8 @@
label="&downloadsHistory.label;"
accesskey="&downloadsHistory.accesskey;"
flex="1"
- oncommand="DownloadsPanel.showDownloadsHistory();"/>
+ oncommand="DownloadsPanel.showDownloadsHistory();"
+ pack="start"/>
diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js
index 7afa1dcb97f1..ae7489cf319a 100644
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -319,13 +319,6 @@ var gSyncPane = {
}).then(data => {
let fxaLoginStatus = document.getElementById("fxaLoginStatus");
if (data) {
- if (data.email) {
- // A hack to handle that the user's email address may have changed.
- // This can probably be removed as part of bug 1383663.
- fxaEmailAddressLabels.forEach((label) => {
- label.value = data.email;
- });
- }
if (data.displayName) {
fxaLoginStatus.setAttribute("hasName", true);
displayNameLabel.hidden = false;
diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css
index 7818a8f7e3fe..f8ee1014807c 100644
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -121,12 +121,11 @@
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
border-radius: 50%;
box-shadow: none;
- border: 2px solid -moz-dialog;
/* "!important" is necessary to override the rule in toolbarbutton.css */
- margin: -9px 0 0 !important;
- margin-inline-end: -6px !important;
- min-width: 16px;
- min-height: 16px;
+ margin: -7px 0 0 !important;
+ margin-inline-end: -4px !important;
+ min-width: 12px;
+ min-height: 12px;
}
.panel-banner-item[notificationid^=update]::after {
@@ -223,12 +222,18 @@ panelview {
.subviewbutton.panel-subview-footer {
box-sizing: border-box;
min-height: 41px;
- padding: 11px 12px;
}
-.cui-widget-panelview .subviewbutton.panel-subview-footer {
+.cui-widget-panelview menuitem.subviewbutton.panel-subview-footer {
margin: 4px 0 0;
- -moz-box-pack: center;
+}
+
+.cui-widget-panelview .subviewbutton.panel-subview-footer > .menu-text {
+ -moz-box-flex: 1;
+}
+
+.cui-widget-panelview .subviewbutton.panel-subview-footer .menu-accel-container {
+ -moz-box-pack: end;
}
#appMenu-popup > arrowscrollbox > autorepeatbutton,
@@ -384,7 +389,8 @@ panelview[id^=PanelUI-webext-] {
}
panelview:not([mainview]) .toolbarbutton-text,
-.cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text {
+.cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text,
+#overflowMenu-customize-button > .toolbarbutton-text {
text-align: start;
display: -moz-box;
}
@@ -1209,7 +1215,6 @@ panelview .toolbarbutton-1,
.subviewbutton > .toolbarbutton-text {
padding: 0;
- padding-inline-start: 24px; /* This is 16px for the icon + 8px for the padding as defined above. */
}
.subviewbutton > .menu-right,
@@ -1985,12 +1990,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
#PanelUI-panic-actionlist-newwindow {
background-image: -moz-image-rect(url(chrome://browser/skin/panic-panel/icons@2x.png), 0, 128, 32, 96);
}
-
- #PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
- #PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
- #PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
- border: 1px solid -moz-dialog;
- }
}
/* START photon adjustments */
diff --git a/browser/themes/shared/downloads/downloads.inc.css b/browser/themes/shared/downloads/downloads.inc.css
index 0a8ce216d0c7..3fd5c204d369 100644
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -92,8 +92,8 @@
}
#downloadsHistory {
- padding-inline-start: 10px;
- padding-inline-end: 10px;
+ padding-inline-start: 14px;
+ padding-inline-end: 14px;
}
@item@ > toolbarseparator {
diff --git a/browser/themes/shared/icons/menu-badged.svg b/browser/themes/shared/icons/menu-badged.svg
new file mode 100644
index 000000000000..58ad9a8ecfe0
--- /dev/null
+++ b/browser/themes/shared/icons/menu-badged.svg
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn
index 6182de3ab577..6f82e83704e3 100644
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -150,6 +150,7 @@
skin/classic/browser/link.svg (../shared/icons/link.svg)
skin/classic/browser/mail.svg (../shared/icons/mail.svg)
skin/classic/browser/menu.svg (../shared/icons/menu.svg)
+ skin/classic/browser/menu-badged.svg (../shared/icons/menu-badged.svg)
skin/classic/browser/new-tab.svg (../shared/icons/new-tab.svg)
skin/classic/browser/new-window.svg (../shared/icons/new-window.svg)
skin/classic/browser/open.svg (../shared/icons/open.svg)
diff --git a/browser/themes/shared/toolbarbutton-icons.inc.css b/browser/themes/shared/toolbarbutton-icons.inc.css
index 51e0b8e907eb..5c5c819dd596 100644
--- a/browser/themes/shared/toolbarbutton-icons.inc.css
+++ b/browser/themes/shared/toolbarbutton-icons.inc.css
@@ -275,6 +275,12 @@ toolbar[brighttext] {
list-style-image: url("chrome://browser/skin/menu.svg");
}
+#PanelUI-menu-button[badge-status="update-available"],
+#PanelUI-menu-button[badge-status="update-manual"],
+#PanelUI-menu-button[badge-status="update-restart"] {
+ list-style-image: url("chrome://browser/skin/menu-badged.svg");
+}
+
#cut-button {
list-style-image: url("chrome://browser/skin/edit-cut.svg");
}
diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css
index c929a6198390..6afcd06e7942 100644
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -78,6 +78,14 @@
margin-top: var(--space-above-tabbar);
}
+/* Add 4px extra margin on top of the tabs toolbar on Windows 7. */
+@media (-moz-os-version: windows-win7) {
+ :root[sizemode="normal"][chromehidden~="menubar"] #toolbar-menubar ~ #TabsToolbar,
+ :root[sizemode="normal"] #toolbar-menubar[autohide="true"][inactive] ~ #TabsToolbar {
+ margin-top: calc(var(--space-above-tabbar) + 4px);
+ }
+}
+
#navigator-toolbox,
#navigator-toolbox > toolbar {
-moz-appearance: none;
diff --git a/config/check_macroassembler_style.py b/config/check_macroassembler_style.py
index 77480903fc0e..6d00a44b3467 100644
--- a/config/check_macroassembler_style.py
+++ b/config/check_macroassembler_style.py
@@ -3,7 +3,7 @@
# 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/.
-#----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
# This script checks that SpiderMonkey MacroAssembler methods are properly
# annotated.
#
@@ -18,7 +18,7 @@
# MacroAssembler-inl.h for method definitions. The result of both scans are
# uniformized, and compared, to determine if the MacroAssembler.h header as
# proper methods annotations.
-#----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
from __future__ import print_function
@@ -30,10 +30,10 @@ import sys
from mozversioncontrol import get_repository_from_env
-architecture_independent = set([ 'generic' ])
-all_unsupported_architectures_names = set([ 'mips32', 'mips64', 'mips_shared' ])
-all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64' ])
-all_shared_architecture_names = set([ 'x86_shared', 'arm', 'arm64' ])
+architecture_independent = set(['generic'])
+all_unsupported_architectures_names = set(['mips32', 'mips64', 'mips_shared'])
+all_architecture_names = set(['x86', 'x64', 'arm', 'arm64'])
+all_shared_architecture_names = set(['x86_shared', 'arm', 'arm64'])
reBeforeArg = "(?<=[(,\s])"
reArgType = "(?P[\w\s:*&]+)"
@@ -42,7 +42,8 @@ reArgDefault = "(?P(?:\s=[^,)]+)?)"
reAfterArg = "(?=[,)])"
reMatchArg = re.compile(reBeforeArg + reArgType + reArgName + reArgDefault + reAfterArg)
-def get_normalized_signatures(signature, fileAnnot = None):
+
+def get_normalized_signatures(signature, fileAnnot=None):
# Remove static
signature = signature.replace('static', '')
# Remove semicolon.
@@ -88,18 +89,21 @@ def get_normalized_signatures(signature, fileAnnot = None):
inlinePrefx = ''
if inline:
inlinePrefx = 'inline '
- signatures = [
- { 'arch': a, 'sig': inlinePrefx + signature }
+ signatures = [
+ {'arch': a, 'sig': inlinePrefx + signature}
for a in archs
]
return signatures
+
file_suffixes = set([
a.replace('_', '-') for a in
all_architecture_names.union(all_shared_architecture_names)
.union(all_unsupported_architectures_names)
])
+
+
def get_file_annotation(filename):
origFilename = filename
filename = filename.split('/')[-1]
@@ -124,6 +128,7 @@ def get_file_annotation(filename):
'arch': arch.replace('-', '_')
}
+
def get_macroassembler_definitions(filename):
try:
fileAnnot = get_file_annotation(filename)
@@ -147,7 +152,7 @@ def get_macroassembler_definitions(filename):
if line.startswith('{') or line.strip() == "{}":
if 'MacroAssembler::' in lines:
signatures.extend(get_normalized_signatures(lines, fileAnnot))
- if line.strip() != "{}": # Empty declaration, no need to declare
+ if line.strip() != "{}": # Empty declaration, no need to declare
# a new code section
code_section = True
continue
@@ -172,6 +177,7 @@ def get_macroassembler_definitions(filename):
return signatures
+
def get_macroassembler_declaration(filename):
style_section = False
lines = ''
@@ -203,13 +209,15 @@ def get_macroassembler_declaration(filename):
return signatures
+
def append_signatures(d, sigs):
for s in sigs:
if s['sig'] not in d:
d[s['sig']] = []
- d[s['sig']].append(s['arch']);
+ d[s['sig']].append(s['arch'])
return d
+
def generate_file_content(signatures):
output = []
for s in sorted(signatures.keys()):
@@ -237,6 +245,7 @@ def generate_file_content(signatures):
output.append(' is defined in %s.cpp\n' % masm)
return output
+
def check_style():
# We read from the header file the signature of each function.
decls = dict() # type: dict(signature => ['x86', 'x64'])
@@ -278,7 +287,7 @@ def main():
if ok:
print('TEST-PASS | check_macroassembler_style.py | ok')
else:
- print('TEST-UNEXPECTED-FAIL | check_macroassembler_style.py | actual output does not match expected output; diff is above')
+ print('TEST-UNEXPECTED-FAIL | check_macroassembler_style.py | actual output does not match expected output; diff is above') # noqa: E501
sys.exit(0 if ok else 1)
diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java
index a2b297bd171d..b921bda24295 100644
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java
@@ -21,6 +21,7 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.RobocopUtils;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.toolbar.BrowserToolbar;
import org.mozilla.gecko.util.GeckoBundle;
import android.content.ContentValues;
@@ -424,7 +425,8 @@ abstract class BaseTest extends BaseRobocopTest {
public final void selectMenuItem(String menuItemName) {
// build the item name ready to be used
String itemName = "^" + menuItemName + "$";
- final View menuView = mSolo.getView(R.id.menu);
+ final BrowserToolbar toolbar = (BrowserToolbar) mSolo.getView(R.id.browser_toolbar);
+ final View menuView = toolbar.findViewById(R.id.menu);
mAsserter.isnot(menuView, null, "Menu view is not null");
mSolo.clickOnView(menuView, true);
mAsserter.ok(waitForEnabledText(itemName), "Waiting for menu item " + itemName, itemName + " is present and enabled");
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index d907c12a7edb..717807745b38 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -4,9 +4,9 @@
"lockfileVersion": 1,
"dependencies": {
"acorn": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz",
- "integrity": "sha1-U/4WERH5EquZnuiHqQoLxSgi/XU="
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz",
+ "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA=="
},
"acorn-jsx": {
"version": "3.0.1",
@@ -79,9 +79,9 @@
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
},
"babel-code-frame": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
- "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"requires": {
"chalk": "1.1.3",
"esutils": "2.0.2",
@@ -128,9 +128,9 @@
}
},
"circular-json": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz",
- "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0="
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="
},
"cli-cursor": {
"version": "1.0.2",
@@ -141,9 +141,9 @@
}
},
"cli-width": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
- "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao="
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
},
"co": {
"version": "4.6.0",
@@ -180,7 +180,7 @@
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
"requires": {
- "es5-ext": "0.10.24"
+ "es5-ext": "0.10.30"
}
},
"debug": {
@@ -207,7 +207,7 @@
"object-assign": "4.1.1",
"pify": "2.3.0",
"pinkie-promise": "2.0.1",
- "rimraf": "2.6.1"
+ "rimraf": "2.6.2"
}
},
"doctrine": {
@@ -263,9 +263,9 @@
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
},
"es5-ext": {
- "version": "0.10.24",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz",
- "integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=",
+ "version": "0.10.30",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
+ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
"requires": {
"es6-iterator": "2.0.1",
"es6-symbol": "3.1.1"
@@ -277,7 +277,7 @@
"integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24",
+ "es5-ext": "0.10.30",
"es6-symbol": "3.1.1"
}
},
@@ -287,7 +287,7 @@
"integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24",
+ "es5-ext": "0.10.30",
"es6-iterator": "2.0.1",
"es6-set": "0.1.5",
"es6-symbol": "3.1.1",
@@ -300,7 +300,7 @@
"integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24",
+ "es5-ext": "0.10.30",
"es6-iterator": "2.0.1",
"es6-symbol": "3.1.1",
"event-emitter": "0.3.5"
@@ -312,7 +312,7 @@
"integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24"
+ "es5-ext": "0.10.30"
}
},
"es6-weak-map": {
@@ -321,7 +321,7 @@
"integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24",
+ "es5-ext": "0.10.30",
"es6-iterator": "2.0.1",
"es6-symbol": "3.1.1"
}
@@ -347,25 +347,25 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
"integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=",
"requires": {
- "babel-code-frame": "6.22.0",
+ "babel-code-frame": "6.26.0",
"chalk": "1.1.3",
"concat-stream": "1.6.0",
"debug": "2.6.8",
"doctrine": "2.0.0",
"escope": "3.6.0",
- "espree": "3.4.3",
+ "espree": "3.5.1",
"esquery": "1.0.0",
"estraverse": "4.2.0",
"esutils": "2.0.2",
"file-entry-cache": "2.0.0",
"glob": "7.1.2",
"globals": "9.18.0",
- "ignore": "3.3.3",
+ "ignore": "3.3.5",
"imurmurhash": "0.1.4",
"inquirer": "0.12.0",
- "is-my-json-valid": "2.16.0",
+ "is-my-json-valid": "2.16.1",
"is-resolvable": "1.0.0",
- "js-yaml": "3.9.0",
+ "js-yaml": "3.10.0",
"json-stable-stringify": "1.0.1",
"levn": "0.3.0",
"lodash": "4.17.4",
@@ -395,10 +395,6 @@
"eslint-plugin-mozilla": {
"version": "file:tools/lint/eslint/eslint-plugin-mozilla",
"requires": {
- "escope": "3.6.0",
- "espree": "3.4.3",
- "estraverse": "4.2.0",
- "globals": "9.18.0",
"ini-parser": "0.0.2",
"sax": "1.2.4"
}
@@ -425,11 +421,11 @@
"version": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js"
},
"espree": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz",
- "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz",
+ "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=",
"requires": {
- "acorn": "5.1.1",
+ "acorn": "5.1.2",
"acorn-jsx": "3.0.1"
}
},
@@ -471,7 +467,7 @@
"integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.24"
+ "es5-ext": "0.10.30"
}
},
"exit-hook": {
@@ -507,7 +503,7 @@
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz",
"integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=",
"requires": {
- "circular-json": "0.3.1",
+ "circular-json": "0.3.3",
"del": "2.2.2",
"graceful-fs": "4.1.11",
"write": "0.2.1"
@@ -519,9 +515,9 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"function-bind": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz",
- "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"generate-function": {
"version": "2.0.0",
@@ -539,7 +535,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
@@ -552,7 +548,7 @@
"globals": {
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
- "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo="
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
},
"globby": {
"version": "5.0.0",
@@ -577,7 +573,7 @@
"resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
"integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
"requires": {
- "function-bind": "1.1.0"
+ "function-bind": "1.1.1"
}
},
"has-ansi": {
@@ -602,9 +598,9 @@
}
},
"ignore": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz",
- "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0="
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz",
+ "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw=="
},
"imurmurhash": {
"version": "0.1.4",
@@ -639,7 +635,7 @@
"ansi-regex": "2.1.1",
"chalk": "1.1.3",
"cli-cursor": "1.0.2",
- "cli-width": "2.1.0",
+ "cli-width": "2.2.0",
"figures": "1.7.0",
"lodash": "4.17.4",
"readline2": "1.0.1",
@@ -651,9 +647,9 @@
}
},
"interpret": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz",
- "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A="
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz",
+ "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA="
},
"is-fullwidth-code-point": {
"version": "1.0.0",
@@ -664,9 +660,9 @@
}
},
"is-my-json-valid": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz",
- "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=",
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz",
+ "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==",
"requires": {
"generate-function": "2.0.0",
"generate-object-property": "1.2.0",
@@ -719,9 +715,9 @@
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"js-yaml": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz",
- "integrity": "sha512-0LoUNELX4S+iofCT8f4uEHIiRBR+c2AINyC8qRWfC6QNruLtxVZRJaPcu/xwMgFIgDxF25tGHaDjvxzJCNE9yw==",
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
"requires": {
"argparse": "1.0.9",
"esprima": "4.0.0"
@@ -767,7 +763,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "1.1.8"
}
@@ -897,7 +893,7 @@
"readable-stream": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
- "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@@ -923,7 +919,7 @@
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"requires": {
- "resolve": "1.3.3"
+ "resolve": "1.4.0"
}
},
"require-uncached": {
@@ -936,9 +932,9 @@
}
},
"resolve": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
- "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",
+ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==",
"requires": {
"path-parse": "1.0.5"
}
@@ -958,9 +954,9 @@
}
},
"rimraf": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
- "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"requires": {
"glob": "7.1.2"
}
@@ -981,12 +977,12 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk="
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"shelljs": {
"version": "0.7.8",
@@ -994,7 +990,7 @@
"integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
"requires": {
"glob": "7.1.2",
- "interpret": "1.0.3",
+ "interpret": "1.0.4",
"rechoir": "0.6.2"
}
},
@@ -1021,7 +1017,7 @@
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
}
@@ -1059,7 +1055,7 @@
"chalk": "1.1.3",
"lodash": "4.17.4",
"slice-ansi": "0.0.4",
- "string-width": "2.1.0"
+ "string-width": "2.1.1"
},
"dependencies": {
"ansi-regex": {
@@ -1073,9 +1069,9 @@
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"string-width": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz",
- "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "2.0.0",
"strip-ansi": "4.0.0"
diff --git a/services/crypto/modules/utils.js b/services/crypto/modules/utils.js
index 9a5d8e65072a..aa0be9de0150 100644
--- a/services/crypto/modules/utils.js
+++ b/services/crypto/modules/utils.js
@@ -113,6 +113,15 @@ this.CryptoUtils = {
return CommonUtils.bytesAsHex(CryptoUtils.digestUTF8(message, hasher));
},
+ sha256Base64(message) {
+ let data = this._utf8Converter.convertToByteArray(message, {});
+ let hasher = Cc["@mozilla.org/security/hash;1"]
+ .createInstance(Ci.nsICryptoHash);
+ hasher.init(hasher.SHA256);
+ hasher.update(data, data.length);
+ return hasher.finish(true);
+ },
+
/**
* Produce an HMAC key object from a key string.
*/
diff --git a/services/fxaccounts/FxAccounts.jsm b/services/fxaccounts/FxAccounts.jsm
index 8242b229a6bb..b9f1118292e4 100644
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -51,8 +51,9 @@ var publicProperties = [
"getProfileCache",
"getSignedInUser",
"getSignedInUserProfile",
- "handleDeviceDisconnection",
"handleAccountDestroyed",
+ "handleDeviceDisconnection",
+ "handleEmailUpdated",
"hasLocalSession",
"invalidateCertificate",
"loadAndPoll",
@@ -593,7 +594,7 @@ FxAccountsInternal.prototype = {
*
* @param credentials
* The credentials object containing the fields to be updated.
- * This object must contain |email| and |uid| fields and they must
+ * This object must contain the |uid| field and it must
* match the currently signed in user.
*/
updateUserAccountData(credentials) {
@@ -603,15 +604,14 @@ FxAccountsInternal.prototype = {
}
let currentAccountState = this.currentAccountState;
return currentAccountState.promiseInitialized.then(() => {
- return currentAccountState.getUserAccountData(["email", "uid"]);
+ return currentAccountState.getUserAccountData(["uid"]);
}).then(existing => {
- if (existing.email != credentials.email || existing.uid != credentials.uid) {
+ if (existing.uid != credentials.uid) {
throw new Error("The specified credentials aren't for the current user");
}
- // We need to nuke email and uid as storage will complain if we try and
- // update them (even when the value is the same)
+ // We need to nuke uid as storage will complain if we try and
+ // update it (even when the value is the same)
credentials = Cu.cloneInto(credentials, {}); // clone it first
- delete credentials.email;
delete credentials.uid;
return currentAccountState.updateUserAccountData(credentials);
});
@@ -1607,6 +1607,11 @@ FxAccountsInternal.prototype = {
return null;
},
+ handleEmailUpdated(newEmail) {
+ Services.prefs.setStringPref(PREF_LAST_FXA_USER, CryptoUtils.sha256Base64(newEmail));
+ return this.currentAccountState.updateUserAccountData({ email: newEmail });
+ },
+
async handleAccountDestroyed(uid) {
const accountData = await this.currentAccountState.getUserAccountData();
const localUid = accountData ? accountData.uid : null;
diff --git a/services/fxaccounts/FxAccountsCommon.js b/services/fxaccounts/FxAccountsCommon.js
index 464c1606e125..e07710037d65 100644
--- a/services/fxaccounts/FxAccountsCommon.js
+++ b/services/fxaccounts/FxAccountsCommon.js
@@ -113,6 +113,8 @@ exports.FX_OAUTH_CLIENT_ID = "5882386c6d801776";
// Firefox Accounts WebChannel ID
exports.WEBCHANNEL_ID = "account_updates";
+exports.PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
+
// Server errno.
// From https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format
exports.ERRNO_ACCOUNT_ALREADY_EXISTS = 101;
diff --git a/services/fxaccounts/FxAccountsProfile.jsm b/services/fxaccounts/FxAccountsProfile.jsm
index 2543540973c5..ca89eaa7f2e0 100644
--- a/services/fxaccounts/FxAccountsProfile.jsm
+++ b/services/fxaccounts/FxAccountsProfile.jsm
@@ -71,45 +71,40 @@ this.FxAccountsProfile.prototype = {
},
// Cache fetched data and send out a notification so that UI can update.
- _cacheProfile(response) {
+ async _cacheProfile(response) {
+ const profile = response.body;
+ const userData = await this.fxa.getSignedInUser();
+ if (profile.uid != userData.uid) {
+ throw new Error("The fetched profile does not correspond with the current account.")
+ }
let profileCache = {
- profile: response.body,
+ profile,
etag: response.etag
};
-
- return this.fxa.setProfileCache(profileCache)
- .then(() => {
- return this.fxa.getSignedInUser();
- })
- .then(userData => {
- log.debug("notifying profile changed for user ${uid}", userData);
- this._notifyProfileChange(userData.uid);
- return response.body;
- });
+ await this.fxa.setProfileCache(profileCache);
+ if (profile.email != userData.email) {
+ await this.fxa.handleEmailUpdated(profile.email);
+ }
+ log.debug("notifying profile changed for user ${uid}", userData);
+ this._notifyProfileChange(userData.uid);
+ return profile;
},
- _fetchAndCacheProfileInternal() {
- let onFinally = () => {
+ async _fetchAndCacheProfileInternal() {
+ try {
+ const profileCache = await this.fxa.getProfileCache();
+ const etag = profileCache ? profileCache.etag : null;
+ const response = await this.client.fetchProfile(etag);
+
+ // response may be null if the profile was not modified (same ETag).
+ if (!response) {
+ return null;
+ }
+ return await this._cacheProfile(response);
+ } finally {
this._cachedAt = Date.now();
this._currentFetchPromise = null;
}
- return this.fxa.getProfileCache()
- .then(profileCache => {
- const etag = profileCache ? profileCache.etag : null;
- return this.client.fetchProfile(etag);
- })
- .then(response => {
- // response may be null if the profile was not modified (same ETag).
- return response ? this._cacheProfile(response) : null;
- })
- .then(body => { // finally block
- onFinally();
- // body may be null if the profile was not modified
- return body;
- }, err => {
- onFinally();
- throw err;
- });
},
_fetchAndCacheProfile() {
@@ -122,23 +117,21 @@ this.FxAccountsProfile.prototype = {
// Returns cached data right away if available, then fetches the latest profile
// data in the background. After data is fetched a notification will be sent
// out if the profile has changed.
- getProfile() {
- return this.fxa.getProfileCache()
- .then(profileCache => {
- if (profileCache) {
- if (Date.now() > this._cachedAt + this.PROFILE_FRESHNESS_THRESHOLD) {
- // Note that _fetchAndCacheProfile isn't returned, so continues
- // in the background.
- this._fetchAndCacheProfile().catch(err => {
- log.error("Background refresh of profile failed", err);
- });
- } else {
- log.trace("not checking freshness of profile as it remains recent");
- }
- return profileCache.profile;
- }
- return this._fetchAndCacheProfile();
+ async getProfile() {
+ const profileCache = await this.fxa.getProfileCache();
+ if (!profileCache) {
+ return this._fetchAndCacheProfile();
+ }
+ if (Date.now() > this._cachedAt + this.PROFILE_FRESHNESS_THRESHOLD) {
+ // Note that _fetchAndCacheProfile isn't returned, so continues
+ // in the background.
+ this._fetchAndCacheProfile().catch(err => {
+ log.error("Background refresh of profile failed", err);
});
+ } else {
+ log.trace("not checking freshness of profile as it remains recent");
+ }
+ return profileCache.profile;
},
QueryInterface: XPCOMUtils.generateQI([
diff --git a/services/fxaccounts/FxAccountsStorage.jsm b/services/fxaccounts/FxAccountsStorage.jsm
index b4ea0a00280a..b7d0078df937 100644
--- a/services/fxaccounts/FxAccountsStorage.jsm
+++ b/services/fxaccounts/FxAccountsStorage.jsm
@@ -208,11 +208,8 @@ this.FxAccountsStorageManager.prototype = {
// update fields.
throw new Error("No user is logged in");
}
- if (!newFields || "uid" in newFields || "email" in newFields) {
- // Once we support
- // user changing email address this may need to change, but it's not
- // clear how we would be told of such a change anyway...
- throw new Error("Can't change uid or email address");
+ if (!newFields || "uid" in newFields) {
+ throw new Error("Can't change uid");
}
log.debug("_updateAccountData with items", Object.keys(newFields));
// work out what bucket.
diff --git a/services/fxaccounts/FxAccountsWebChannel.jsm b/services/fxaccounts/FxAccountsWebChannel.jsm
index f5f594c16db9..c23a214fb963 100644
--- a/services/fxaccounts/FxAccountsWebChannel.jsm
+++ b/services/fxaccounts/FxAccountsWebChannel.jsm
@@ -29,6 +29,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
"resource://services-sync/main.js");
+XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils",
+ "resource://services-crypto/utils.js");
const COMMAND_PROFILE_CHANGE = "profile:change";
const COMMAND_CAN_LINK_ACCOUNT = "fxaccounts:can_link_account";
@@ -39,8 +41,6 @@ const COMMAND_SYNC_PREFERENCES = "fxaccounts:sync_preferences";
const COMMAND_CHANGE_PASSWORD = "fxaccounts:change_password";
const COMMAND_FXA_STATUS = "fxaccounts:fxa_status";
-const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
-
// These engines were added years after Sync had been introduced, they need
// special handling since they are system add-ons and are un-available on
// older versions of Firefox.
@@ -459,24 +459,7 @@ this.FxAccountsWebChannelHelpers.prototype = {
* @param acctName the account name of the user's account.
*/
setPreviousAccountNameHashPref(acctName) {
- Services.prefs.setStringPref(PREF_LAST_FXA_USER, this.sha256(acctName));
- },
-
- /**
- * Given a string, returns the SHA265 hash in base64
- */
- sha256(str) {
- let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Ci.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- // Data is an array of bytes.
- let data = converter.convertToByteArray(str, {});
- let hasher = Cc["@mozilla.org/security/hash;1"]
- .createInstance(Ci.nsICryptoHash);
- hasher.init(hasher.SHA256);
- hasher.update(data, data.length);
-
- return hasher.finish(true);
+ Services.prefs.setStringPref(PREF_LAST_FXA_USER, CryptoUtils.sha256Base64(acctName));
},
/**
@@ -504,7 +487,7 @@ this.FxAccountsWebChannelHelpers.prototype = {
*/
_needRelinkWarning(acctName) {
let prevAcctHash = this.getPreviousAccountNameHashPref();
- return prevAcctHash && prevAcctHash != this.sha256(acctName);
+ return prevAcctHash && prevAcctHash != CryptoUtils.sha256Base64(acctName);
},
/**
diff --git a/services/fxaccounts/tests/xpcshell/test_accounts.js b/services/fxaccounts/tests/xpcshell/test_accounts.js
index d026a063de77..807b2f842871 100644
--- a/services/fxaccounts/tests/xpcshell/test_accounts.js
+++ b/services/fxaccounts/tests/xpcshell/test_accounts.js
@@ -299,13 +299,7 @@ add_task(async function test_update_account_data() {
do_check_eq((await account.getSignedInUser()).assertion, "new_assertion",
"new field value was saved");
- // but we should fail attempting to change email or uid.
- newCreds = {
- email: "someoneelse@example.com",
- uid: credentials.uid,
- assertion: "new_assertion",
- }
- await Assert.rejects(account.updateUserAccountData(newCreds));
+ // but we should fail attempting to change the uid.
newCreds = {
email: credentials.email,
uid: "another_uid",
@@ -313,7 +307,7 @@ add_task(async function test_update_account_data() {
}
await Assert.rejects(account.updateUserAccountData(newCreds));
- // should fail without email or uid.
+ // should fail without the uid.
newCreds = {
assertion: "new_assertion",
}
diff --git a/services/fxaccounts/tests/xpcshell/test_profile.js b/services/fxaccounts/tests/xpcshell/test_profile.js
index 1b7b19f870d0..31cc3ee43374 100644
--- a/services/fxaccounts/tests/xpcshell/test_profile.js
+++ b/services/fxaccounts/tests/xpcshell/test_profile.js
@@ -6,6 +6,7 @@
Cu.import("resource://gre/modules/FxAccountsCommon.js");
Cu.import("resource://gre/modules/FxAccountsProfileClient.jsm");
Cu.import("resource://gre/modules/FxAccountsProfile.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
const URL_STRING = "https://example.com";
Services.prefs.setCharPref("identity.fxaccounts.settings.uri", "https://example.com/settings");
@@ -59,8 +60,11 @@ let mockClient = function(fxa) {
return new FxAccountsProfileClient(options);
};
+const ACCOUNT_UID = "abc123";
+const ACCOUNT_EMAIL = "foo@bar.com";
const ACCOUNT_DATA = {
- uid: "abc123"
+ uid: ACCOUNT_UID,
+ email: ACCOUNT_EMAIL
};
function FxaMock() {
@@ -122,13 +126,13 @@ add_test(function cacheProfile_change() {
run_next_test();
});
- return profile._cacheProfile({ body: { avatar: "myurl" }, etag: "bogusetag" });
+ return profile._cacheProfile({ body: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myurl" }, etag: "bogusetag" });
});
add_test(function fetchAndCacheProfile_ok() {
let client = mockClient(mockFxa());
client.fetchProfile = function() {
- return Promise.resolve({ body: { avatar: "myimg"} });
+ return Promise.resolve({ body: { uid: ACCOUNT_UID, avatar: "myimg"} });
};
let profile = CreateFxAccountsProfile(null, client);
profile._cachedAt = 12345;
@@ -169,7 +173,7 @@ add_test(function fetchAndCacheProfile_sendsETag() {
let client = mockClient(fxa);
client.fetchProfile = function(etag) {
do_check_eq(etag, "bogusETag");
- return Promise.resolve({ body: { avatar: "myimg"} });
+ return Promise.resolve({ body: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"} });
};
let profile = CreateFxAccountsProfile(fxa, client);
@@ -195,26 +199,18 @@ add_task(async function fetchAndCacheProfileOnce() {
return promiseProfile;
};
let fxa = mockFxa();
- fxa.getProfileCache = () => {
- // We do this because we are gonna have a race condition and fetchProfile will
- // not be called before we check numFetches.
- return {
- then(thenFunc) {
- return thenFunc();
- }
- }
- };
let profile = CreateFxAccountsProfile(fxa, client);
let request1 = profile._fetchAndCacheProfile();
profile._fetchAndCacheProfile();
+ await new Promise(res => setTimeout(res, 0)); // Yield so fetchProfile() is called (promise)
// should be one request made to fetch the profile (but the promise returned
// by it remains unresolved)
do_check_eq(numFetches, 1);
// resolve the promise.
- resolveProfile({ body: { avatar: "myimg"} });
+ resolveProfile({ body: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"} });
// both requests should complete with the same data.
let got1 = await request1;
@@ -242,19 +238,11 @@ add_task(async function fetchAndCacheProfileOnce() {
return promiseProfile;
};
let fxa = mockFxa();
- fxa.getProfileCache = () => {
- // We do this because we are gonna have a race condition and fetchProfile will
- // not be called before we check numFetches.
- return {
- then(thenFunc) {
- return thenFunc();
- }
- }
- };
let profile = CreateFxAccountsProfile(fxa, client);
let request1 = profile._fetchAndCacheProfile();
let request2 = profile._fetchAndCacheProfile();
+ await new Promise(res => setTimeout(res, 0)); // Yield so fetchProfile() is called (promise)
// should be one request made to fetch the profile (but the promise returned
// by it remains unresolved)
@@ -283,7 +271,7 @@ add_task(async function fetchAndCacheProfileOnce() {
// but a new request should works.
client.fetchProfile = function() {
- return Promise.resolve({body: { avatar: "myimg"}});
+ return Promise.resolve({body: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"}});
};
let got = await profile._fetchAndCacheProfile();
@@ -293,7 +281,7 @@ add_task(async function fetchAndCacheProfileOnce() {
add_test(function fetchAndCacheProfile_alreadyCached() {
let cachedUrl = "cachedurl";
let fxa = mockFxa();
- fxa.profileCache = { profile: { avatar: cachedUrl }, etag: "bogusETag" };
+ fxa.profileCache = { profile: { uid: ACCOUNT_UID, avatar: cachedUrl }, etag: "bogusETag" };
let client = mockClient(fxa);
client.fetchProfile = function(etag) {
do_check_eq(etag, "bogusETag");
@@ -318,9 +306,9 @@ add_test(function fetchAndCacheProfile_alreadyCached() {
add_task(async function fetchAndCacheProfileAfterThreshold() {
let numFetches = 0;
let client = mockClient(mockFxa());
- client.fetchProfile = function() {
+ client.fetchProfile = async function() {
numFetches += 1;
- return Promise.resolve({ avatar: "myimg"});
+ return {body: {uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"}};
};
let profile = CreateFxAccountsProfile(null, client);
profile.PROFILE_FRESHNESS_THRESHOLD = 1000;
@@ -335,7 +323,14 @@ add_task(async function fetchAndCacheProfileAfterThreshold() {
do_timeout(1000, resolve);
});
+ let origFetchAndCatch = profile._fetchAndCacheProfile;
+ let backgroundFetchDone = PromiseUtils.defer();
+ profile._fetchAndCacheProfile = async () => {
+ await origFetchAndCatch.call(profile);
+ backgroundFetchDone.resolve();
+ }
await profile.getProfile();
+ await backgroundFetchDone.promise;
do_check_eq(numFetches, 2);
});
@@ -345,9 +340,9 @@ add_task(async function fetchAndCacheProfileAfterThreshold() {
add_task(async function fetchAndCacheProfileBeforeThresholdOnNotification() {
let numFetches = 0;
let client = mockClient(mockFxa());
- client.fetchProfile = function() {
+ client.fetchProfile = async function() {
numFetches += 1;
- return Promise.resolve({ avatar: "myimg"});
+ return {body: {uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"}};
};
let profile = CreateFxAccountsProfile(null, client);
profile.PROFILE_FRESHNESS_THRESHOLD = 1000;
@@ -357,7 +352,14 @@ add_task(async function fetchAndCacheProfileBeforeThresholdOnNotification() {
Services.obs.notifyObservers(null, ON_PROFILE_CHANGE_NOTIFICATION);
+ let origFetchAndCatch = profile._fetchAndCacheProfile;
+ let backgroundFetchDone = PromiseUtils.defer();
+ profile._fetchAndCacheProfile = async () => {
+ await origFetchAndCatch.call(profile);
+ backgroundFetchDone.resolve();
+ }
await profile.getProfile();
+ await backgroundFetchDone.promise;
do_check_eq(numFetches, 2);
});
@@ -379,7 +381,7 @@ add_test(function getProfile_ok() {
let didFetch = false;
let fxa = mockFxa();
- fxa.profileCache = { profile: { avatar: cachedUrl } };
+ fxa.profileCache = { profile: { uid: ACCOUNT_UID, avatar: cachedUrl } };
let profile = CreateFxAccountsProfile(fxa);
profile._fetchAndCacheProfile = function() {
@@ -402,7 +404,7 @@ add_test(function getProfile_no_cache() {
let profile = CreateFxAccountsProfile(fxa);
profile._fetchAndCacheProfile = function() {
- return Promise.resolve({ avatar: fetchedUrl });
+ return Promise.resolve({ uid: ACCOUNT_UID, avatar: fetchedUrl });
};
return profile.getProfile()
@@ -418,11 +420,11 @@ add_test(function getProfile_has_cached_fetch_deleted() {
let fxa = mockFxa();
let client = mockClient(fxa);
client.fetchProfile = function() {
- return Promise.resolve({ body: { avatar: null } });
+ return Promise.resolve({ body: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: null } });
};
let profile = CreateFxAccountsProfile(fxa, client);
- fxa.profileCache = { profile: { avatar: cachedUrl } };
+ fxa.profileCache = { profile: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: cachedUrl } };
// instead of checking this in a mocked "save" function, just check after the
// observer
@@ -442,7 +444,7 @@ add_test(function getProfile_has_cached_fetch_deleted() {
add_test(function getProfile_fetchAndCacheProfile_throws() {
let fxa = mockFxa();
- fxa.profileCache = { profile: { avatar: "myimg" } };
+ fxa.profileCache = { profile: { uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg" } };
let profile = CreateFxAccountsProfile(fxa);
profile._fetchAndCacheProfile = () => Promise.reject(new Error());
@@ -454,6 +456,21 @@ add_test(function getProfile_fetchAndCacheProfile_throws() {
});
});
+add_test(function getProfile_email_changed() {
+ let fxa = mockFxa();
+ let client = mockClient(fxa);
+ client.fetchProfile = function() {
+ return Promise.resolve({ body: { uid: ACCOUNT_UID, email: "newemail@bar.com" } });
+ };
+ fxa.handleEmailUpdated = email => {
+ do_check_eq(email, "newemail@bar.com");
+ run_next_test();
+ };
+
+ let profile = CreateFxAccountsProfile(fxa, client);
+ return profile._fetchAndCacheProfile();
+});
+
function makeObserver(aObserveTopic, aObserveFunc) {
let callback = function(aSubject, aTopic, aData) {
log.debug("observed " + aTopic + " " + aData);
diff --git a/services/fxaccounts/tests/xpcshell/test_web_channel.js b/services/fxaccounts/tests/xpcshell/test_web_channel.js
index 2260688e3776..80987ca88326 100644
--- a/services/fxaccounts/tests/xpcshell/test_web_channel.js
+++ b/services/fxaccounts/tests/xpcshell/test_web_channel.js
@@ -4,6 +4,7 @@
"use strict";
Cu.import("resource://gre/modules/FxAccountsCommon.js");
+Cu.import("resource://services-crypto/utils.js");
const { FxAccountsWebChannel, FxAccountsWebChannelHelpers } =
Cu.import("resource://gre/modules/FxAccountsWebChannel.jsm", {});
@@ -338,7 +339,8 @@ add_task(async function test_helpers_login_without_customize_sync() {
do_check_false("verifiedCanLinkAccount" in accountData);
// previously signed in user preference is updated.
- do_check_eq(helpers.getPreviousAccountNameHashPref(), helpers.sha256("testuser@testuser.com"));
+ do_check_eq(helpers.getPreviousAccountNameHashPref(),
+ CryptoUtils.sha256Base64("testuser@testuser.com"));
resolve();
});
diff --git a/services/sync/modules/UIState.jsm b/services/sync/modules/UIState.jsm
index a6cbbc227f64..7019bf833518 100644
--- a/services/sync/modules/UIState.jsm
+++ b/services/sync/modules/UIState.jsm
@@ -162,9 +162,6 @@ const UIStateInternal = {
_populateWithProfile(state, profile) {
state.displayName = profile.displayName;
state.avatarURL = profile.avatar;
- // A hack to handle that the user's email address may have changed.
- // This can probably be removed as part of bug 1383663.
- state.email = profile.email;
},
async _getUserData() {
diff --git a/services/sync/tests/unit/test_uistate.js b/services/sync/tests/unit/test_uistate.js
index 1b85db539914..edb289793c1e 100644
--- a/services/sync/tests/unit/test_uistate.js
+++ b/services/sync/tests/unit/test_uistate.js
@@ -53,7 +53,7 @@ add_task(async function test_refreshState_signedin() {
UIStateInternal.fxAccounts = {
getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
- getSignedInUserProfile: () => Promise.resolve({ displayName: "Foo Bar", avatar: "https://foo/bar", email: "foo@bar.com" }),
+ getSignedInUserProfile: () => Promise.resolve({ displayName: "Foo Bar", avatar: "https://foo/bar" }),
hasLocalSession: () => Promise.resolve(true),
}
@@ -69,32 +69,6 @@ add_task(async function test_refreshState_signedin() {
UIStateInternal.fxAccounts = fxAccountsOrig;
});
-add_task(async function test_refreshState_preferProfileEmail() {
- UIState.reset();
- const fxAccountsOrig = UIStateInternal.fxAccounts;
-
- const now = new Date().toString();
- Services.prefs.setCharPref("services.sync.lastSync", now);
- UIStateInternal.syncing = false;
-
- UIStateInternal.fxAccounts = {
- getSignedInUser: () => Promise.resolve({ verified: true, email: "foo@bar.com" }),
- getSignedInUserProfile: () => Promise.resolve({ displayName: "Foo Bar", avatar: "https://foo/bar", email: "bar@foo.com" }),
- hasLocalSession: () => Promise.resolve(true),
- }
-
- let state = await UIState.refresh();
-
- equal(state.status, UIState.STATUS_SIGNED_IN);
- equal(state.email, "bar@foo.com");
- equal(state.displayName, "Foo Bar");
- equal(state.avatarURL, "https://foo/bar");
- equal(state.lastSync, now);
- equal(state.syncing, false);
-
- UIStateInternal.fxAccounts = fxAccountsOrig;
-});
-
add_task(async function test_refreshState_signedin_profile_unavailable() {
UIState.reset();
const fxAccountsOrig = UIStateInternal.fxAccounts;
diff --git a/servo/components/style/gecko/media_queries.rs b/servo/components/style/gecko/media_queries.rs
index 415700fef6de..2765547aaf9e 100644
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -752,7 +752,9 @@ impl Expression {
(&BoolInteger(one), &BoolInteger(ref other)) => one.cmp(other),
(&Float(one), &Float(ref other)) => one.partial_cmp(other).unwrap(),
(&IntRatio(one_num, one_den), &IntRatio(other_num, other_den)) => {
- (one_num * other_den).partial_cmp(&(other_num * one_den)).unwrap()
+ // Extend to avoid overflow.
+ (one_num as u64 * other_den as u64).cmp(
+ &(other_num as u64 * one_den as u64))
}
(&Resolution(ref one), &Resolution(ref other)) => {
let actual_dpi = unsafe {
diff --git a/servo/components/style/sharing/mod.rs b/servo/components/style/sharing/mod.rs
index d6d159a4bb75..a9c6a06181da 100644
--- a/servo/components/style/sharing/mod.rs
+++ b/servo/components/style/sharing/mod.rs
@@ -554,11 +554,6 @@ impl StyleSharingCache {
validation_data_holder: Option<&mut StyleSharingTarget>,
dom_depth: usize,
) {
- if style.0.reused_via_rule_node {
- debug!("Failing to insert into the cached: this was a cached style");
- return;
- }
-
let parent = match element.traversal_parent() {
Some(element) => element,
None => {
diff --git a/servo/components/style/traversal.rs b/servo/components/style/traversal.rs
index 20386d754b47..762e28644aad 100644
--- a/servo/components/style/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -723,12 +723,29 @@ where
resolver.cascade_styles_with_default_parents(cascade_inputs)
};
- context.thread_local.sharing_cache.insert_if_possible(
- &element,
- &new_styles.primary,
- None,
- traversal_data.current_dom_depth,
- );
+ // Insert into the cache, but only if this style isn't reused from a
+ // sibling or cousin. Otherwise, recascading a bunch of identical
+ // elements would unnecessarily flood the cache with identical entries.
+ //
+ // This is analagous to the obvious "don't insert an element that just
+ // got a hit in the style sharing cache" behavior in the MatchAndCascade
+ // handling above.
+ //
+ // Note that, for the MatchAndCascade path, we still insert elements that
+ // shared styles via the rule node, because we know that there's something
+ // different about them that caused them to miss the sharing cache before
+ // selector matching. If we didn't, we would still end up with the same
+ // number of eventual styles, but would potentially miss out on various
+ // opportunities for skipping selector matching, which could hurt
+ // performance.
+ if !new_styles.primary.0.reused_via_rule_node {
+ context.thread_local.sharing_cache.insert_if_possible(
+ &element,
+ &new_styles.primary,
+ None,
+ traversal_data.current_dom_depth,
+ );
+ }
new_styles
}
diff --git a/toolkit/themes/shared/extensions/extensions.inc.css b/toolkit/themes/shared/extensions/extensions.inc.css
index 0203e357a3a0..cd24da6a4ab9 100644
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -723,7 +723,7 @@ button.warning {
margin-bottom: 2em;
}
-#detail-name-container label {
+#detail-name-container {
font-size: 2.5rem;
font-weight: normal;
}
diff --git a/toolkit/themes/windows/global/menu.css b/toolkit/themes/windows/global/menu.css
index 822682a6c694..9f8b3ea6f9cb 100644
--- a/toolkit/themes/windows/global/menu.css
+++ b/toolkit/themes/windows/global/menu.css
@@ -58,7 +58,6 @@ menuitem.spell-suggestion {
}
.menu-text {
- padding-inline-start: 1.45em !important;
-moz-appearance: menuitemtext;
}
@@ -85,7 +84,6 @@ menucaption > .menu-iconic-text {
.menu-iconic-accel {
color: inherit;
margin-inline-start: 0.74em !important;
- margin-inline-end: 1.35em !important;
}
.menu-iconic-left {
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt b/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
index b48477df86e3..e4bc2a96decf 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
+++ b/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
@@ -4,7 +4,7 @@
"visibility": "public",
"filename": "eslint-plugin-mozilla.tar.gz",
"unpack": true,
- "digest": "15f798175702ec4603676fc6befb7ecf3f169901ae5509edeea73d2ee1861899de39c3ff3e797a65e3a733ac2f0a4b05b8159b17bf5fa2f351667ad34055bcd6",
- "size": 4243209
+ "digest": "e6494c4b71e94775b7b3341d42338a852c827e050692679b44ef15105b220ed63fa9a08b68ae1d103f8d9c88c7369c2c13079288df7c977699f8be798ac0a170",
+ "size": 3930721
}
]
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
index c34bfe8ebebd..ca877fab793b 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
@@ -5,14 +5,16 @@
"requires": true,
"dependencies": {
"acorn": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz",
- "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw=="
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz",
+ "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==",
+ "dev": true
},
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
"requires": {
"acorn": "3.3.0"
},
@@ -20,7 +22,8 @@
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
- "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true
}
}
},
@@ -91,9 +94,9 @@
"dev": true
},
"babel-code-frame": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
- "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "1.1.3",
@@ -152,9 +155,9 @@
}
},
"circular-json": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz",
- "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=",
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
"dev": true
},
"cli-cursor": {
@@ -167,9 +170,9 @@
}
},
"cli-width": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
- "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
"dev": true
},
"co": {
@@ -184,13 +187,13 @@
"integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
"dev": true,
"requires": {
- "color-name": "1.1.2"
+ "color-name": "1.1.3"
}
},
"color-name": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.2.tgz",
- "integrity": "sha1-XIq3K2S9IhXWF66VWeuxSEdc+Y0=",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"commander": {
@@ -225,14 +228,6 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
- "d": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
- "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
- "requires": {
- "es5-ext": "0.10.24"
- }
- },
"debug": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
@@ -260,7 +255,7 @@
"object-assign": "4.1.1",
"pify": "2.3.0",
"pinkie-promise": "2.0.1",
- "rimraf": "2.6.1"
+ "rimraf": "2.6.2"
}
},
"diff": {
@@ -279,87 +274,12 @@
"isarray": "1.0.0"
}
},
- "es5-ext": {
- "version": "0.10.24",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz",
- "integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=",
- "requires": {
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1"
- }
- },
- "es6-iterator": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
- "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24",
- "es6-symbol": "3.1.1"
- }
- },
- "es6-map": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
- "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24",
- "es6-iterator": "2.0.1",
- "es6-set": "0.1.5",
- "es6-symbol": "3.1.1",
- "event-emitter": "0.3.5"
- }
- },
- "es6-set": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
- "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24",
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1",
- "event-emitter": "0.3.5"
- }
- },
- "es6-symbol": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
- "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24"
- }
- },
- "es6-weak-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
- "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24",
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1"
- }
- },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
- "escope": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
- "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
- "requires": {
- "es6-map": "0.1.5",
- "es6-weak-map": "2.0.2",
- "esrecurse": "4.2.0",
- "estraverse": "4.2.0"
- }
- },
"eslint": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.2.0.tgz",
@@ -367,24 +287,24 @@
"dev": true,
"requires": {
"ajv": "5.2.2",
- "babel-code-frame": "6.22.0",
+ "babel-code-frame": "6.26.0",
"chalk": "1.1.3",
"concat-stream": "1.6.0",
"debug": "2.6.8",
"doctrine": "2.0.0",
"eslint-scope": "3.7.1",
- "espree": "3.4.3",
+ "espree": "3.5.1",
"esquery": "1.0.0",
"estraverse": "4.2.0",
"esutils": "2.0.2",
"file-entry-cache": "2.0.0",
"glob": "7.1.2",
"globals": "9.18.0",
- "ignore": "3.3.3",
+ "ignore": "3.3.5",
"imurmurhash": "0.1.4",
- "inquirer": "3.2.0",
+ "inquirer": "3.2.3",
"is-resolvable": "1.0.0",
- "js-yaml": "3.9.0",
+ "js-yaml": "3.10.0",
"json-stable-stringify": "1.0.1",
"levn": "0.3.0",
"lodash": "4.17.4",
@@ -412,11 +332,12 @@
}
},
"espree": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz",
- "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz",
+ "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=",
+ "dev": true,
"requires": {
- "acorn": "5.1.1",
+ "acorn": "5.1.2",
"acorn-jsx": "3.0.1"
}
},
@@ -439,6 +360,7 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
"integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+ "dev": true,
"requires": {
"estraverse": "4.2.0",
"object-assign": "4.1.1"
@@ -447,7 +369,8 @@
"estraverse": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "dev": true
},
"esutils": {
"version": "2.0.2",
@@ -455,23 +378,14 @@
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
- "event-emitter": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
- "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.24"
- }
- },
"external-editor": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz",
"integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=",
"dev": true,
"requires": {
- "iconv-lite": "0.4.18",
- "jschardet": "1.4.2",
+ "iconv-lite": "0.4.19",
+ "jschardet": "1.5.1",
"tmp": "0.0.31"
}
},
@@ -512,7 +426,7 @@
"integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=",
"dev": true,
"requires": {
- "circular-json": "0.3.1",
+ "circular-json": "0.3.3",
"del": "2.2.2",
"graceful-fs": "4.1.11",
"write": "0.2.1"
@@ -541,7 +455,8 @@
"globals": {
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
- "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
},
"globby": {
"version": "5.0.0",
@@ -591,15 +506,15 @@
"dev": true
},
"iconv-lite": {
- "version": "0.4.18",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
- "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==",
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
"dev": true
},
"ignore": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz",
- "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=",
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz",
+ "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==",
"dev": true
},
"imurmurhash": {
@@ -630,15 +545,15 @@
"integrity": "sha1-+kF4flZ3Y7P/Zdel2alO23QHh+8="
},
"inquirer": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.0.tgz",
- "integrity": "sha512-4CyUYMP7lOBkiUU1rR24WGrfRX6SucwbY2Mqb1PdApU24wnTIk4TsnkQwV72dDdIKZ2ycLP+fWCV+tA7wwgoew==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.3.tgz",
+ "integrity": "sha512-Bc3KbimpDTOeQdDj18Ir/rlsGuhBSSNqdOnxaAuKhpkdnMMuKsEGbZD2v5KFF9oso2OU+BPh7+/u5obmFDRmWw==",
"dev": true,
"requires": {
"ansi-escapes": "2.0.0",
- "chalk": "2.0.1",
+ "chalk": "2.1.0",
"cli-cursor": "2.1.0",
- "cli-width": "2.1.0",
+ "cli-width": "2.2.0",
"external-editor": "2.0.4",
"figures": "2.0.0",
"lodash": "4.17.4",
@@ -646,7 +561,7 @@
"run-async": "2.3.0",
"rx-lite": "4.0.8",
"rx-lite-aggregates": "4.0.8",
- "string-width": "2.1.0",
+ "string-width": "2.1.1",
"strip-ansi": "4.0.0",
"through": "2.3.8"
},
@@ -658,23 +573,23 @@
"dev": true
},
"ansi-styles": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz",
- "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
"dev": true,
"requires": {
"color-convert": "1.9.0"
}
},
"chalk": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz",
- "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"dev": true,
"requires": {
- "ansi-styles": "3.1.0",
+ "ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
- "supports-color": "4.2.0"
+ "supports-color": "4.4.0"
}
},
"strip-ansi": {
@@ -687,9 +602,9 @@
}
},
"supports-color": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz",
- "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"dev": true,
"requires": {
"has-flag": "2.0.0"
@@ -755,9 +670,9 @@
"dev": true
},
"js-yaml": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz",
- "integrity": "sha512-0LoUNELX4S+iofCT8f4uEHIiRBR+c2AINyC8qRWfC6QNruLtxVZRJaPcu/xwMgFIgDxF25tGHaDjvxzJCNE9yw==",
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
"dev": true,
"requires": {
"argparse": "1.0.9",
@@ -765,9 +680,9 @@
}
},
"jschardet": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz",
- "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=",
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz",
+ "integrity": "sha512-vE2hT1D0HLZCLLclfBSfkfTTedhVj0fubHpJBHKwwUWX0nSbhPAfk+SG9rTX95BYNmau8rGFfCeaT6T5OW1C2A==",
"dev": true
},
"json-schema-traverse": {
@@ -997,7 +912,8 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
},
"once": {
"version": "1.4.0",
@@ -1136,9 +1052,9 @@
}
},
"rimraf": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
- "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"dev": true,
"requires": {
"glob": "7.1.2"
@@ -1197,19 +1113,10 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
- "string_decoder": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.1"
- }
- },
"string-width": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz",
- "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "2.0.0",
@@ -1233,6 +1140,15 @@
}
}
},
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -1265,7 +1181,7 @@
"chalk": "1.1.3",
"lodash": "4.17.4",
"slice-ansi": "0.0.4",
- "string-width": "2.1.0"
+ "string-width": "2.1.1"
},
"dependencies": {
"ajv": {
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/package.json b/tools/lint/eslint/eslint-plugin-mozilla/package.json
index 1fad5c678758..df7d820ba236 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -20,10 +20,6 @@
"author": "Mike Ratcliffe",
"main": "lib/index.js",
"dependencies": {
- "escope": "3.6.0",
- "espree": "3.4.3",
- "estraverse": "4.2.0",
- "globals": "9.18.0",
"ini-parser": "0.0.2",
"sax": "1.2.4"
},
diff --git a/tools/lint/eslint/manifest.tt b/tools/lint/eslint/manifest.tt
index 5311bac9cb8e..bf01fcbff5ad 100644
--- a/tools/lint/eslint/manifest.tt
+++ b/tools/lint/eslint/manifest.tt
@@ -4,7 +4,7 @@
"visibility": "public",
"filename": "eslint.tar.gz",
"unpack": true,
- "digest": "9cb0212c8cd21b38edeeae2d00728625d442588bcd076b43a061c0994458698d6377ba28a708dca140202744cb03fcadb02c3153ae8585c5648a0b513b0cefa7",
- "size": 2912929
+ "digest": "4ed34c6d0b1831bce3ab5def5b7cf6248c7ef459a4c68acba8741e9e32e3ed84919c03b155a1518c6eba95a8c55ab3856a905f27cd861f547e684a37fff582e8",
+ "size": 2906797
}
]
diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json
index 96dd5f8ab154..7717b54faf00 100644
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -84,7 +84,7 @@
"fxa_utils.js": ["initializeIdentityWithTokenServerResponse"],
"fxaccounts.jsm": ["Authentication"],
"FxAccounts.jsm": ["fxAccounts", "FxAccounts"],
- "FxAccountsCommon.js": ["log", "logPII", "FXACCOUNTS_PERMISSION", "DATA_FORMAT_VERSION", "DEFAULT_STORAGE_FILENAME", "ASSERTION_LIFETIME", "ASSERTION_USE_PERIOD", "CERT_LIFETIME", "KEY_LIFETIME", "POLL_SESSION", "ONLOGIN_NOTIFICATION", "ONVERIFIED_NOTIFICATION", "ONLOGOUT_NOTIFICATION", "ON_FXA_UPDATE_NOTIFICATION", "ON_DEVICE_CONNECTED_NOTIFICATION", "ON_DEVICE_DISCONNECTED_NOTIFICATION", "ON_PROFILE_UPDATED_NOTIFICATION", "ON_PASSWORD_CHANGED_NOTIFICATION", "ON_PASSWORD_RESET_NOTIFICATION", "ON_VERIFY_LOGIN_NOTIFICATION", "ON_ACCOUNT_DESTROYED_NOTIFICATION", "ON_COLLECTION_CHANGED_NOTIFICATION", "FXA_PUSH_SCOPE_ACCOUNT_UPDATE", "ON_PROFILE_CHANGE_NOTIFICATION", "ON_ACCOUNT_STATE_CHANGE_NOTIFICATION", "UI_REQUEST_SIGN_IN_FLOW", "UI_REQUEST_REFRESH_AUTH", "FX_OAUTH_CLIENT_ID", "WEBCHANNEL_ID", "ERRNO_ACCOUNT_ALREADY_EXISTS", "ERRNO_ACCOUNT_DOES_NOT_EXIST", "ERRNO_INCORRECT_PASSWORD", "ERRNO_UNVERIFIED_ACCOUNT", "ERRNO_INVALID_VERIFICATION_CODE", "ERRNO_NOT_VALID_JSON_BODY", "ERRNO_INVALID_BODY_PARAMETERS", "ERRNO_MISSING_BODY_PARAMETERS", "ERRNO_INVALID_REQUEST_SIGNATURE", "ERRNO_INVALID_AUTH_TOKEN", "ERRNO_INVALID_AUTH_TIMESTAMP", "ERRNO_MISSING_CONTENT_LENGTH", "ERRNO_REQUEST_BODY_TOO_LARGE", "ERRNO_TOO_MANY_CLIENT_REQUESTS", "ERRNO_INVALID_AUTH_NONCE", "ERRNO_ENDPOINT_NO_LONGER_SUPPORTED", "ERRNO_INCORRECT_LOGIN_METHOD", "ERRNO_INCORRECT_KEY_RETRIEVAL_METHOD", "ERRNO_INCORRECT_API_VERSION", "ERRNO_INCORRECT_EMAIL_CASE", "ERRNO_ACCOUNT_LOCKED", "ERRNO_ACCOUNT_UNLOCKED", "ERRNO_UNKNOWN_DEVICE", "ERRNO_DEVICE_SESSION_CONFLICT", "ERRNO_SERVICE_TEMP_UNAVAILABLE", "ERRNO_PARSE", "ERRNO_NETWORK", "ERRNO_UNKNOWN_ERROR", "OAUTH_SERVER_ERRNO_OFFSET", "ERRNO_UNKNOWN_CLIENT_ID", "ERRNO_INCORRECT_CLIENT_SECRET", "ERRNO_INCORRECT_REDIRECT_URI", "ERRNO_INVALID_FXA_ASSERTION", "ERRNO_UNKNOWN_CODE", "ERRNO_INCORRECT_CODE", "ERRNO_EXPIRED_CODE", "ERRNO_OAUTH_INVALID_TOKEN", "ERRNO_INVALID_REQUEST_PARAM", "ERRNO_INVALID_RESPONSE_TYPE", "ERRNO_UNAUTHORIZED", "ERRNO_FORBIDDEN", "ERRNO_INVALID_CONTENT_TYPE", "ERROR_ACCOUNT_ALREADY_EXISTS", "ERROR_ACCOUNT_DOES_NOT_EXIST", "ERROR_ACCOUNT_LOCKED", "ERROR_ACCOUNT_UNLOCKED", "ERROR_ALREADY_SIGNED_IN_USER", "ERROR_DEVICE_SESSION_CONFLICT", "ERROR_ENDPOINT_NO_LONGER_SUPPORTED", "ERROR_INCORRECT_API_VERSION", "ERROR_INCORRECT_EMAIL_CASE", "ERROR_INCORRECT_KEY_RETRIEVAL_METHOD", "ERROR_INCORRECT_LOGIN_METHOD", "ERROR_INVALID_EMAIL", "ERROR_INVALID_AUDIENCE", "ERROR_INVALID_AUTH_TOKEN", "ERROR_INVALID_AUTH_TIMESTAMP", "ERROR_INVALID_AUTH_NONCE", "ERROR_INVALID_BODY_PARAMETERS", "ERROR_INVALID_PASSWORD", "ERROR_INVALID_VERIFICATION_CODE", "ERROR_INVALID_REFRESH_AUTH_VALUE", "ERROR_INVALID_REQUEST_SIGNATURE", "ERROR_INTERNAL_INVALID_USER", "ERROR_MISSING_BODY_PARAMETERS", "ERROR_MISSING_CONTENT_LENGTH", "ERROR_NO_TOKEN_SESSION", "ERROR_NO_SILENT_REFRESH_AUTH", "ERROR_NOT_VALID_JSON_BODY", "ERROR_OFFLINE", "ERROR_PERMISSION_DENIED", "ERROR_REQUEST_BODY_TOO_LARGE", "ERROR_SERVER_ERROR", "ERROR_SYNC_DISABLED", "ERROR_TOO_MANY_CLIENT_REQUESTS", "ERROR_SERVICE_TEMP_UNAVAILABLE", "ERROR_UI_ERROR", "ERROR_UI_REQUEST", "ERROR_PARSE", "ERROR_NETWORK", "ERROR_UNKNOWN", "ERROR_UNKNOWN_DEVICE", "ERROR_UNVERIFIED_ACCOUNT", "ERROR_UNKNOWN_CLIENT_ID", "ERROR_INCORRECT_CLIENT_SECRET", "ERROR_INCORRECT_REDIRECT_URI", "ERROR_INVALID_FXA_ASSERTION", "ERROR_UNKNOWN_CODE", "ERROR_INCORRECT_CODE", "ERROR_EXPIRED_CODE", "ERROR_OAUTH_INVALID_TOKEN", "ERROR_INVALID_REQUEST_PARAM", "ERROR_INVALID_RESPONSE_TYPE", "ERROR_UNAUTHORIZED", "ERROR_FORBIDDEN", "ERROR_INVALID_CONTENT_TYPE", "ERROR_NO_ACCOUNT", "ERROR_AUTH_ERROR", "ERROR_INVALID_PARAMETER", "ERROR_CODE_METHOD_NOT_ALLOWED", "ERROR_MSG_METHOD_NOT_ALLOWED", "FXA_PWDMGR_PLAINTEXT_FIELDS", "FXA_PWDMGR_SECURE_FIELDS", "FXA_PWDMGR_MEMORY_FIELDS", "FXA_PWDMGR_REAUTH_WHITELIST", "FXA_PWDMGR_HOST", "FXA_PWDMGR_REALM", "SERVER_ERRNO_TO_ERROR", "ERROR_TO_GENERAL_ERROR_CLASS"],
+ "FxAccountsCommon.js": ["log", "logPII", "FXACCOUNTS_PERMISSION", "DATA_FORMAT_VERSION", "DEFAULT_STORAGE_FILENAME", "ASSERTION_LIFETIME", "ASSERTION_USE_PERIOD", "CERT_LIFETIME", "KEY_LIFETIME", "POLL_SESSION", "ONLOGIN_NOTIFICATION", "ONVERIFIED_NOTIFICATION", "ONLOGOUT_NOTIFICATION", "ON_FXA_UPDATE_NOTIFICATION", "ON_DEVICE_CONNECTED_NOTIFICATION", "ON_DEVICE_DISCONNECTED_NOTIFICATION", "ON_PROFILE_UPDATED_NOTIFICATION", "ON_PASSWORD_CHANGED_NOTIFICATION", "ON_PASSWORD_RESET_NOTIFICATION", "ON_VERIFY_LOGIN_NOTIFICATION", "ON_ACCOUNT_DESTROYED_NOTIFICATION", "ON_COLLECTION_CHANGED_NOTIFICATION", "FXA_PUSH_SCOPE_ACCOUNT_UPDATE", "ON_PROFILE_CHANGE_NOTIFICATION", "ON_ACCOUNT_STATE_CHANGE_NOTIFICATION", "UI_REQUEST_SIGN_IN_FLOW", "UI_REQUEST_REFRESH_AUTH", "FX_OAUTH_CLIENT_ID", "WEBCHANNEL_ID", "PREF_LAST_FXA_USER", "ERRNO_ACCOUNT_ALREADY_EXISTS", "ERRNO_ACCOUNT_DOES_NOT_EXIST", "ERRNO_INCORRECT_PASSWORD", "ERRNO_UNVERIFIED_ACCOUNT", "ERRNO_INVALID_VERIFICATION_CODE", "ERRNO_NOT_VALID_JSON_BODY", "ERRNO_INVALID_BODY_PARAMETERS", "ERRNO_MISSING_BODY_PARAMETERS", "ERRNO_INVALID_REQUEST_SIGNATURE", "ERRNO_INVALID_AUTH_TOKEN", "ERRNO_INVALID_AUTH_TIMESTAMP", "ERRNO_MISSING_CONTENT_LENGTH", "ERRNO_REQUEST_BODY_TOO_LARGE", "ERRNO_TOO_MANY_CLIENT_REQUESTS", "ERRNO_INVALID_AUTH_NONCE", "ERRNO_ENDPOINT_NO_LONGER_SUPPORTED", "ERRNO_INCORRECT_LOGIN_METHOD", "ERRNO_INCORRECT_KEY_RETRIEVAL_METHOD", "ERRNO_INCORRECT_API_VERSION", "ERRNO_INCORRECT_EMAIL_CASE", "ERRNO_ACCOUNT_LOCKED", "ERRNO_ACCOUNT_UNLOCKED", "ERRNO_UNKNOWN_DEVICE", "ERRNO_DEVICE_SESSION_CONFLICT", "ERRNO_SERVICE_TEMP_UNAVAILABLE", "ERRNO_PARSE", "ERRNO_NETWORK", "ERRNO_UNKNOWN_ERROR", "OAUTH_SERVER_ERRNO_OFFSET", "ERRNO_UNKNOWN_CLIENT_ID", "ERRNO_INCORRECT_CLIENT_SECRET", "ERRNO_INCORRECT_REDIRECT_URI", "ERRNO_INVALID_FXA_ASSERTION", "ERRNO_UNKNOWN_CODE", "ERRNO_INCORRECT_CODE", "ERRNO_EXPIRED_CODE", "ERRNO_OAUTH_INVALID_TOKEN", "ERRNO_INVALID_REQUEST_PARAM", "ERRNO_INVALID_RESPONSE_TYPE", "ERRNO_UNAUTHORIZED", "ERRNO_FORBIDDEN", "ERRNO_INVALID_CONTENT_TYPE", "ERROR_ACCOUNT_ALREADY_EXISTS", "ERROR_ACCOUNT_DOES_NOT_EXIST", "ERROR_ACCOUNT_LOCKED", "ERROR_ACCOUNT_UNLOCKED", "ERROR_ALREADY_SIGNED_IN_USER", "ERROR_DEVICE_SESSION_CONFLICT", "ERROR_ENDPOINT_NO_LONGER_SUPPORTED", "ERROR_INCORRECT_API_VERSION", "ERROR_INCORRECT_EMAIL_CASE", "ERROR_INCORRECT_KEY_RETRIEVAL_METHOD", "ERROR_INCORRECT_LOGIN_METHOD", "ERROR_INVALID_EMAIL", "ERROR_INVALID_AUDIENCE", "ERROR_INVALID_AUTH_TOKEN", "ERROR_INVALID_AUTH_TIMESTAMP", "ERROR_INVALID_AUTH_NONCE", "ERROR_INVALID_BODY_PARAMETERS", "ERROR_INVALID_PASSWORD", "ERROR_INVALID_VERIFICATION_CODE", "ERROR_INVALID_REFRESH_AUTH_VALUE", "ERROR_INVALID_REQUEST_SIGNATURE", "ERROR_INTERNAL_INVALID_USER", "ERROR_MISSING_BODY_PARAMETERS", "ERROR_MISSING_CONTENT_LENGTH", "ERROR_NO_TOKEN_SESSION", "ERROR_NO_SILENT_REFRESH_AUTH", "ERROR_NOT_VALID_JSON_BODY", "ERROR_OFFLINE", "ERROR_PERMISSION_DENIED", "ERROR_REQUEST_BODY_TOO_LARGE", "ERROR_SERVER_ERROR", "ERROR_SYNC_DISABLED", "ERROR_TOO_MANY_CLIENT_REQUESTS", "ERROR_SERVICE_TEMP_UNAVAILABLE", "ERROR_UI_ERROR", "ERROR_UI_REQUEST", "ERROR_PARSE", "ERROR_NETWORK", "ERROR_UNKNOWN", "ERROR_UNKNOWN_DEVICE", "ERROR_UNVERIFIED_ACCOUNT", "ERROR_UNKNOWN_CLIENT_ID", "ERROR_INCORRECT_CLIENT_SECRET", "ERROR_INCORRECT_REDIRECT_URI", "ERROR_INVALID_FXA_ASSERTION", "ERROR_UNKNOWN_CODE", "ERROR_INCORRECT_CODE", "ERROR_EXPIRED_CODE", "ERROR_OAUTH_INVALID_TOKEN", "ERROR_INVALID_REQUEST_PARAM", "ERROR_INVALID_RESPONSE_TYPE", "ERROR_UNAUTHORIZED", "ERROR_FORBIDDEN", "ERROR_INVALID_CONTENT_TYPE", "ERROR_NO_ACCOUNT", "ERROR_AUTH_ERROR", "ERROR_INVALID_PARAMETER", "ERROR_CODE_METHOD_NOT_ALLOWED", "ERROR_MSG_METHOD_NOT_ALLOWED", "FXA_PWDMGR_PLAINTEXT_FIELDS", "FXA_PWDMGR_SECURE_FIELDS", "FXA_PWDMGR_MEMORY_FIELDS", "FXA_PWDMGR_REAUTH_WHITELIST", "FXA_PWDMGR_HOST", "FXA_PWDMGR_REALM", "SERVER_ERRNO_TO_ERROR", "ERROR_TO_GENERAL_ERROR_CLASS"],
"FxAccountsOAuthGrantClient.jsm": ["FxAccountsOAuthGrantClient", "FxAccountsOAuthGrantClientError"],
"FxAccountsProfileClient.jsm": ["FxAccountsProfileClient", "FxAccountsProfileClientError"],
"FxAccountsPush.js": ["FxAccountsPushService"],