[BASILISK] Remove FxA infected Sync - Part 1: Remove or condition CUI and Integration Points

This commit is contained in:
Matt A. Tobin 2019-03-30 20:11:32 -04:00 committed by Roy Tam
commit b07b0d18b5
17 changed files with 30 additions and 1425 deletions

View file

@ -1,314 +0,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/. */
var gFxAccounts = {
_initialized: false,
_inCustomizationMode: false,
_cachedProfile: null,
get weave() {
delete this.weave;
return this.weave = Cc["@mozilla.org/weave/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
},
get topics() {
// Do all this dance to lazy-load FxAccountsCommon.
delete this.topics;
return this.topics = [
"weave:service:ready",
"weave:service:login:change",
"weave:service:setup-complete",
"weave:service:sync:error",
"weave:ui:login:error",
this.FxAccountsCommon.ONLOGIN_NOTIFICATION,
this.FxAccountsCommon.ONLOGOUT_NOTIFICATION,
this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
];
},
get panelUIFooter() {
delete this.panelUIFooter;
return this.panelUIFooter = document.getElementById("PanelUI-footer-fxa");
},
get panelUIStatus() {
delete this.panelUIStatus;
return this.panelUIStatus = document.getElementById("PanelUI-fxa-status");
},
get panelUIAvatar() {
delete this.panelUIAvatar;
return this.panelUIAvatar = document.getElementById("PanelUI-fxa-avatar");
},
get panelUILabel() {
delete this.panelUILabel;
return this.panelUILabel = document.getElementById("PanelUI-fxa-label");
},
get panelUIIcon() {
delete this.panelUIIcon;
return this.panelUIIcon = document.getElementById("PanelUI-fxa-icon");
},
get strings() {
delete this.strings;
return this.strings = Services.strings.createBundle(
"chrome://browser/locale/accounts.properties"
);
},
get loginFailed() {
// Referencing Weave.Service will implicitly initialize sync, and we don't
// want to force that - so first check if it is ready.
let service = Cc["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
if (!service.ready) {
return false;
}
// LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in".
// All other login failures are assumed to be transient and should go
// away by themselves, so aren't reflected here.
return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
},
init: function () {
// Bail out if we're already initialized and for pop-up windows.
if (this._initialized || !window.toolbar.visible) {
return;
}
for (let topic of this.topics) {
Services.obs.addObserver(this, topic, false);
}
gNavToolbox.addEventListener("customizationstarting", this);
gNavToolbox.addEventListener("customizationending", this);
EnsureFxAccountsWebChannel();
this._initialized = true;
this.updateUI();
},
uninit: function () {
if (!this._initialized) {
return;
}
for (let topic of this.topics) {
Services.obs.removeObserver(this, topic);
}
this._initialized = false;
},
observe: function (subject, topic, data) {
switch (topic) {
case this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION:
this._cachedProfile = null;
// Fallthrough intended
default:
this.updateUI();
break;
}
},
handleEvent: function (event) {
this._inCustomizationMode = event.type == "customizationstarting";
this.updateAppMenuItem();
},
updateUI: function () {
// It's possible someone signed in to FxA after seeing our notification
// about "Legacy Sync migration" (which now is actually "Legacy Sync
// auto-disconnect") so kill that notification if it still exists.
let nb = window.document.getElementById("global-notificationbox");
let n = nb.getNotificationWithValue(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
if (n) {
nb.removeNotification(n, true);
}
this.updateAppMenuItem();
},
// Note that updateAppMenuItem() returns a Promise that's only used by tests.
updateAppMenuItem: function () {
let profileInfoEnabled = false;
try {
profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
} catch (e) { }
this.panelUIFooter.hidden = false;
// Make sure the button is disabled in customization mode.
if (this._inCustomizationMode) {
this.panelUIStatus.setAttribute("disabled", "true");
this.panelUILabel.setAttribute("disabled", "true");
this.panelUIAvatar.setAttribute("disabled", "true");
this.panelUIIcon.setAttribute("disabled", "true");
} else {
this.panelUIStatus.removeAttribute("disabled");
this.panelUILabel.removeAttribute("disabled");
this.panelUIAvatar.removeAttribute("disabled");
this.panelUIIcon.removeAttribute("disabled");
}
let defaultLabel = this.panelUIStatus.getAttribute("defaultlabel");
let errorLabel = this.panelUIStatus.getAttribute("errorlabel");
let unverifiedLabel = this.panelUIStatus.getAttribute("unverifiedlabel");
let settingslabel = this.panelUIStatus.getAttribute("settingslabel");
// The localization string is for the signed in text, but it's the default text as well
let defaultTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
let updateWithUserData = (userData) => {
// Window might have been closed while fetching data.
if (window.closed) {
return;
}
// Reset the button to its original state.
this.panelUILabel.setAttribute("label", defaultLabel);
this.panelUIStatus.setAttribute("tooltiptext", defaultTooltiptext);
this.panelUIFooter.removeAttribute("fxastatus");
this.panelUIFooter.removeAttribute("fxaprofileimage");
this.panelUIAvatar.style.removeProperty("list-style-image");
if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED) {
// Leave the default state
return;
}
if (this.loginFailed) {
this.panelUIFooter.setAttribute("fxastatus", "error");
this.panelUILabel.setAttribute("label", errorLabel);
} else {
this.panelUIFooter.setAttribute("fxastatus", "signedin");
this.panelUILabel.setAttribute("label", settingslabel);
this.panelUIStatus.setAttribute("tooltiptext", "");
}
}
let updateWithProfile = (profile) => {
if (profileInfoEnabled) {
if (profile.displayName) {
this.panelUILabel.setAttribute("label", profile.displayName);
}
if (profile.avatar) {
this.panelUIFooter.setAttribute("fxaprofileimage", "set");
let bgImage = "url(\"" + profile.avatar + "\")";
this.panelUIAvatar.style.listStyleImage = bgImage;
let img = new Image();
img.onerror = () => {
// Clear the image if it has trouble loading. Since this callback is asynchronous
// we check to make sure the image is still the same before we clear it.
if (this.panelUIAvatar.style.listStyleImage === bgImage) {
this.panelUIFooter.removeAttribute("fxaprofileimage");
this.panelUIAvatar.style.removeProperty("list-style-image");
}
};
img.src = profile.avatar;
}
}
}
return fxAccounts.getSignedInUser().then(userData => {
// userData may be null here when the user is not signed-in, but that's expected
updateWithUserData(userData);
// unverified users cause us to spew log errors fetching an OAuth token
// to fetch the profile, so don't even try in that case.
if (!userData || !userData.verified || !profileInfoEnabled) {
return null; // don't even try to grab the profile.
}
if (this._cachedProfile) {
return this._cachedProfile;
}
return fxAccounts.getSignedInUserProfile().catch(err => {
// Not fetching the profile is sad but the FxA logs will already have noise.
return null;
});
}).then(profile => {
if (!profile) {
return;
}
updateWithProfile(profile);
this._cachedProfile = profile; // Try to avoid fetching the profile on every UI update
}).catch(error => {
// This is most likely in tests, were we quickly log users in and out.
// The most likely scenario is a user logged out, so reflect that.
// Bug 995134 calls for better errors so we could retry if we were
// sure this was the failure reason.
this.FxAccountsCommon.log.error("Error updating FxA account info", error);
updateWithUserData(null);
});
},
onMenuPanelCommand: function () {
switch (this.panelUIFooter.getAttribute("fxastatus")) {
case "signedin":
this.openPreferences();
break;
case "error":
if (this.panelUIFooter.getAttribute("unverified")) {
this.openPreferences();
} else {
this.openSignInAgainPage("menupanel");
}
break;
default:
this.openPreferences();
break;
}
PanelUI.hide();
},
openPreferences: function () {
openPreferences("paneSync", { urlParams: { entrypoint: "menupanel" } });
},
openAccountsPage: function (action, urlParams={}) {
let params = new URLSearchParams();
if (action) {
params.set("action", action);
}
for (let name in urlParams) {
if (urlParams[name] !== undefined) {
params.set(name, urlParams[name]);
}
}
let url = "about:accounts?" + params;
switchToTabHavingURI(url, true, {
replaceQueryString: true
});
},
openSignInAgainPage: function (entryPoint) {
this.openAccountsPage("reauth", { entrypoint: entryPoint });
},
updateTabContextMenu: function (aPopupMenu) {
// STUB
},
initPageContextMenu: function (contextMenu) {
// STUB
}
};
XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function () {
return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
});
XPCOMUtils.defineLazyModuleGetter(gFxAccounts, "fxaMigrator",
"resource://services-sync/FxaMigrator.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "EnsureFxAccountsWebChannel",
"resource://gre/modules/FxAccountsWebChannel.jsm");

View file

@ -436,12 +436,7 @@
label="&toolsMenu.label;"
accesskey="&toolsMenu.accesskey;"
onpopupshowing="mirrorShow(this)">
<menupopup id="menu_ToolsPopup"
# We have to use setTimeout() here to avoid a flickering menu bar when opening
# the Tools menu, see bug 970769. This can be removed once we got rid of the
# event loop spinning in Weave.Status._authManager.
onpopupshowing="setTimeout(() => gSyncUI.updateUI());"
>
<menupopup id="menu_ToolsPopup">
<menuitem id="menu_openDownloads"
label="&downloads.label;"
accesskey="&downloads.accesskey;"
@ -452,23 +447,6 @@
accesskey="&addons.accesskey;"
key="key_openAddons"
command="Tools:Addons"/>
<!-- only one of sync-setup, sync-syncnowitem or sync-reauthitem will be showing at once -->
<menuitem id="sync-setup"
label="&syncSignIn.label;"
accesskey="&syncSignIn.accesskey;"
observes="sync-setup-state"
oncommand="gSyncUI.openSetup(null, 'menubar')"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
observes="sync-syncnow-state"
oncommand="gSyncUI.doSync(event);"/>
<menuitem id="sync-reauthitem"
label="&syncReAuthItem.label;"
accesskey="&syncReAuthItem.accesskey;"
observes="sync-reauth-state"
oncommand="gSyncUI.openSignInAgainPage('menubar');"/>
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"

View file

@ -1,545 +0,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/. */
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
const MIN_STATUS_ANIMATION_DURATION = 1600;
// gSyncUI handles updating the tools menu and displaying notifications.
var gSyncUI = {
_obs: ["weave:service:sync:start",
"weave:service:sync:finish",
"weave:service:sync:error",
"weave:service:quota:remaining",
"weave:service:setup-complete",
"weave:service:login:start",
"weave:service:login:finish",
"weave:service:login:error",
"weave:service:logout:finish",
"weave:service:start-over",
"weave:service:start-over:finish",
"weave:ui:login:error",
"weave:ui:sync:error",
"weave:ui:sync:finish",
"weave:ui:clear-error",
"weave:engine:sync:finish"
],
_unloaded: false,
// The last sync start time. Used to calculate the leftover animation time
// once syncing completes (bug 1239042).
_syncStartTime: 0,
_syncAnimationTimer: 0,
init: function () {
Cu.import("resource://services-common/stringbundle.js");
// Proceed to set up the UI if Sync has already started up.
// Otherwise we'll do it when Sync is firing up.
if (this.weaveService.ready) {
this.initUI();
return;
}
// Sync isn't ready yet, but we can still update the UI with an initial
// state - we haven't called initUI() yet, but that's OK - that's more
// about observers for state changes, and will be called once Sync is
// ready to start sending notifications.
this.updateUI();
Services.obs.addObserver(this, "weave:service:ready", true);
Services.obs.addObserver(this, "quit-application", true);
// Remove the observer if the window is closed before the observer
// was triggered.
window.addEventListener("unload", function onUnload() {
gSyncUI._unloaded = true;
window.removeEventListener("unload", onUnload, false);
Services.obs.removeObserver(gSyncUI, "weave:service:ready");
Services.obs.removeObserver(gSyncUI, "quit-application");
if (Weave.Status.ready) {
gSyncUI._obs.forEach(function(topic) {
Services.obs.removeObserver(gSyncUI, topic);
});
}
}, false);
},
initUI: function SUI_initUI() {
// If this is a browser window?
if (gBrowser) {
this._obs.push("weave:notification:added");
}
this._obs.forEach(function(topic) {
Services.obs.addObserver(this, topic, true);
}, this);
// initial label for the sync buttons.
let broadcaster = document.getElementById("sync-status");
broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
this.maybeMoveSyncedTabsButton();
this.updateUI();
},
// Returns a promise that resolves with true if Sync needs to be configured,
// false otherwise.
_needsSetup() {
let firstSync = "";
try {
firstSync = Services.prefs.getCharPref("services.sync.firstSync");
} catch (e) { }
return Promise.resolve(Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
firstSync == "notReady");
},
// Returns a promise that resolves with true if the user currently signed in
// to Sync needs to be verified, false otherwise.
_needsVerification() {
// For callers who care about the distinction between "needs setup" and
// "needs verification". Only for fxAccounts. XXX: remove this check.
// Since we are configured for legacy Sync only, which has no verification
// concept, just return false.
return Promise.resolve(false);
},
// Note that we don't show login errors in a notification bar here, but do
// still need to track a login-failed state so the "Tools" menu updates
// with the correct state.
_loginFailed: function () {
// If Sync isn't already ready, we don't want to force it to initialize
// by referencing Weave.Status - and it isn't going to be accurate before
// Sync is ready anyway.
if (!this.weaveService.ready) {
this.log.debug("_loginFailed has sync not ready, so returning false");
return false;
}
this.log.debug("_loginFailed has sync state=${sync}",
{ sync: Weave.Status.login});
return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
},
// Kick off an update of the UI - does *not* return a promise.
updateUI() {
this._promiseUpdateUI().catch(err => {
this.log.error("updateUI failed", err);
})
},
// Updates the UI - returns a promise.
_promiseUpdateUI() {
return this._needsSetup().then(needsSetup => {
if (!gBrowser)
return Promise.resolve();
let loginFailed = this._loginFailed();
// Start off with a clean slate
document.getElementById("sync-reauth-state").hidden = true;
document.getElementById("sync-setup-state").hidden = true;
document.getElementById("sync-syncnow-state").hidden = true;
if (loginFailed) {
// unhiding this element makes the menubar show the login failure state.
document.getElementById("sync-reauth-state").hidden = false;
} else if (needsSetup) {
document.getElementById("sync-setup-state").hidden = false;
} else {
document.getElementById("sync-syncnow-state").hidden = false;
}
return this._updateSyncButtonsTooltip();
});
},
// Functions called by observers
onActivityStart() {
if (!gBrowser)
return;
this.log.debug("onActivityStart");
clearTimeout(this._syncAnimationTimer);
this._syncStartTime = Date.now();
let broadcaster = document.getElementById("sync-status");
broadcaster.setAttribute("syncstatus", "active");
broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncing2.label"));
broadcaster.setAttribute("disabled", "true");
this.updateUI();
},
_updateSyncStatus() {
if (!gBrowser)
return;
let broadcaster = document.getElementById("sync-status");
broadcaster.removeAttribute("syncstatus");
broadcaster.removeAttribute("disabled");
broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
this.updateUI();
},
onActivityStop() {
if (!gBrowser)
return;
this.log.debug("onActivityStop");
let now = Date.now();
let syncDuration = now - this._syncStartTime;
if (syncDuration < MIN_STATUS_ANIMATION_DURATION) {
let animationTime = MIN_STATUS_ANIMATION_DURATION - syncDuration;
clearTimeout(this._syncAnimationTimer);
this._syncAnimationTimer = setTimeout(() => this._updateSyncStatus(), animationTime);
} else {
this._updateSyncStatus();
}
},
onLoginError: function SUI_onLoginError() {
this.log.debug("onLoginError: login=${login}, sync=${sync}", Weave.Status);
// We don't show any login errors here; browser-fxaccounts shows them in
// the hamburger menu.
this.updateUI();
},
onLogout: function SUI_onLogout() {
this.updateUI();
},
onQuotaNotice: function onQuotaNotice(subject, data) {
let title = this._stringBundle.GetStringFromName("warning.sync.quota.label");
let description = this._stringBundle.GetStringFromName("warning.sync.quota.description");
let buttons = [];
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"),
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"),
function() { gSyncUI.openQuotaDialog(); return true; }
));
let notification = new Weave.Notification(
title, description, null, Weave.Notifications.PRIORITY_WARNING, buttons);
Weave.Notifications.replaceTitle(notification);
},
_getAppName: function () {
let brand = new StringBundle("chrome://branding/locale/brand.properties");
return brand.get("brandShortName");
},
// Commands
// doSync forces a sync - it *does not* return a promise as it is called
// via the various UI components.
doSync() {
this._needsSetup().then(needsSetup => {
if (!needsSetup) {
setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0);
}
Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
}).catch(err => {
this.log.error("Failed to force a sync", err);
});
},
// Handle clicking the toolbar button - which either opens the Sync setup
// pages or forces a sync now. Does *not* return a promise as it is called
// via the UI.
handleToolbarButton() {
this._needsSetup().then(needsSetup => {
if (needsSetup || this._loginFailed()) {
this.openSetup();
} else {
this.doSync();
}
}).catch(err => {
this.log.error("Failed to handle toolbar button command", err);
});
},
/**
* Invoke the Sync setup wizard.
*
* @param wizardType
* Indicates type of wizard to launch:
* null -- regular set up wizard
* "pair" -- pair a device first
* "reset" -- reset sync
* @param entryPoint
* Indicates the entrypoint from where this method was called.
*/
openSetup: function SUI_openSetup(wizardType, entryPoint = "syncbutton") {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win)
win.focus();
else {
window.openDialog("chrome://browser/content/sync/setup.xul",
"weaveSetup", "centerscreen,chrome,resizable=no",
wizardType);
}
},
// Open the legacy-sync device pairing UI. Note used for FxA Sync.
openAddDevice: function () {
if (!Weave.Utils.ensureMPUnlocked())
return;
let win = Services.wm.getMostRecentWindow("Sync:AddDevice");
if (win)
win.focus();
else
window.openDialog("chrome://browser/content/sync/addDevice.xul",
"syncAddDevice", "centerscreen,chrome,resizable=no");
},
openPrefs: function (entryPoint) {
openPreferences("paneSync", { urlParams: { entrypoint: entryPoint } });
},
openSignInAgainPage: function (entryPoint = "syncbutton") {
gFxAccounts.openSignInAgainPage(entryPoint);
},
/* After Sync is initialized we perform a once-only check for the sync
button being in "customize purgatory" and if so, move it to the panel.
This is done primarily for profiles created before SyncedTabs landed,
where the button defaulted to being in that purgatory.
We use a preference to ensure we only do it once, so people can still
customize it away and have it stick.
*/
maybeMoveSyncedTabsButton() {
const prefName = "browser.migrated-sync-button";
let migrated = false;
try {
migrated = Services.prefs.getBoolPref(prefName);
} catch (_) {}
if (migrated) {
return;
}
if (!CustomizableUI.getPlacementOfWidget("sync-button")) {
CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
}
Services.prefs.setBoolPref(prefName, true);
},
/* Update the tooltip for the sync-status broadcaster (which will update the
Sync Toolbar button and the Sync spinner in the FxA hamburger area.)
If Sync is configured, the tooltip is when the last sync occurred,
otherwise the tooltip reflects the fact that Sync needs to be
(re-)configured.
*/
_updateSyncButtonsTooltip: Task.async(function* () {
if (!gBrowser)
return;
let email;
try {
email = Services.prefs.getCharPref("services.sync.username");
} catch (ex) {}
let needsSetup = yield this._needsSetup();
let needsVerification = yield this._needsVerification();
let loginFailed = this._loginFailed();
// This is a little messy as the Sync buttons are 1/2 Sync related and
// 1/2 FxA related - so for some strings we use Sync strings, but for
// others we reach into gFxAccounts for strings.
let tooltiptext;
if (needsVerification) {
// "needs verification"
tooltiptext = gFxAccounts.strings.formatStringFromName("verifyDescription", [email], 1);
} else if (needsSetup) {
// "needs setup".
tooltiptext = this._stringBundle.GetStringFromName("signInToSync.description");
} else if (loginFailed) {
// "need to reconnect/re-enter your password"
tooltiptext = gFxAccounts.strings.formatStringFromName("reconnectDescription", [email], 1);
} else {
// Sync appears configured - format the "last synced at" time.
try {
let lastSync = new Date(Services.prefs.getCharPref("services.sync.lastSync"));
tooltiptext = this.formatLastSyncDate(lastSync);
}
catch (e) {
// pref doesn't exist (which will be the case until we've seen the
// first successful sync) or is invalid (which should be impossible!)
// Just leave tooltiptext as the empty string in these cases, which
// will cause the tooltip to be removed below.
}
}
// We've done all our promise-y work and ready to update the UI - make
// sure it hasn't been torn down since we started.
if (!gBrowser)
return;
let broadcaster = document.getElementById("sync-status");
if (broadcaster) {
if (tooltiptext) {
broadcaster.setAttribute("tooltiptext", tooltiptext);
} else {
broadcaster.removeAttribute("tooltiptext");
}
}
}),
formatLastSyncDate: function(date) {
let dateFormat;
let sixDaysAgo = (() => {
let date = new Date();
date.setDate(date.getDate() - 6);
date.setHours(0, 0, 0, 0);
return date;
})();
// It may be confusing for the user to see "Last Sync: Monday" when the last sync was a indeed a Monday but 3 weeks ago
if (date < sixDaysAgo) {
dateFormat = {month: 'long', day: 'numeric'};
} else {
dateFormat = {weekday: 'long', hour: 'numeric', minute: 'numeric'};
}
let lastSyncDateString = date.toLocaleDateString(undefined, dateFormat);
return this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
},
onClientsSynced: function() {
let broadcaster = document.getElementById("sync-syncnow-state");
if (broadcaster) {
if (Weave.Service.clientsEngine.stats.numClients > 1) {
broadcaster.setAttribute("devices-status", "multi");
} else {
broadcaster.setAttribute("devices-status", "single");
}
}
},
onSyncError: function SUI_onSyncError() {
this.log.debug("onSyncError: login=${login}, sync=${sync}", Weave.Status);
let title = this._stringBundle.GetStringFromName("error.sync.title");
let error = Weave.Utils.getErrorString(Weave.Status.sync);
let description =
this._stringBundle.formatStringFromName("error.sync.description", [error], 1);
let priority = Weave.Notifications.PRIORITY_WARNING;
let buttons = [];
if (Weave.Status.sync == Weave.OVER_QUOTA) {
description = this._stringBundle.GetStringFromName("error.sync.quota.description");
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"),
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"),
function() { gSyncUI.openQuotaDialog(); return true; } )
);
// Only show the notification bar on Quota error. the panel will show the rest.
let notification =
new Weave.Notification(title, description, null, priority, buttons);
Weave.Notifications.replaceTitle(notification);
}
this.updateUI();
},
observe: function SUI_observe(subject, topic, data) {
this.log.debug("observed", topic);
if (this._unloaded) {
Cu.reportError("SyncUI observer called after unload: " + topic);
return;
}
// Unwrap, just like Svc.Obs, but without pulling in that dependency.
if (subject && typeof subject == "object" &&
("wrappedJSObject" in subject) &&
("observersModuleSubjectWrapper" in subject.wrappedJSObject)) {
subject = subject.wrappedJSObject.object;
}
// First handle "activity" only.
switch (topic) {
case "weave:service:sync:start":
this.onActivityStart();
break;
case "weave:service:sync:finish":
case "weave:service:sync:error":
this.onActivityStop();
break;
}
// Now non-activity state (eg, enabled, errors, etc)
// Note that sync uses the ":ui:" notifications for errors because sync.
switch (topic) {
case "weave:ui:sync:finish":
// Do nothing.
break;
case "weave:ui:sync:error":
this.onSyncError();
break;
case "weave:service:setup-complete":
case "weave:service:login:finish":
case "weave:service:login:start":
case "weave:service:start-over":
this.updateUI();
break;
case "weave:service:quota:remaining":
this.onQuotaNotice();
break;
case "weave:ui:login:error":
case "weave:service:login:error":
this.onLoginError();
break;
case "weave:service:logout:finish":
this.onLogout();
break;
case "weave:service:start-over:finish":
this.updateUI();
break;
case "weave:service:ready":
this.initUI();
break;
case "weave:notification:added":
this.initNotifications();
break;
case "weave:engine:sync:finish":
if (data != "clients") {
return;
}
this.onClientsSynced();
break;
case "quit-application":
// Stop the animation timer on shutdown, since we can't update the UI
// after this.
clearTimeout(this._syncAnimationTimer);
break;
}
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference
])
};
XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
// XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
// but for now just make it work
return Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService).
createBundle("chrome://weave/locale/services/sync.properties");
});
XPCOMUtils.defineLazyGetter(gSyncUI, "log", function() {
return Log.repository.getLogger("browserwindow.syncui");
});
XPCOMUtils.defineLazyGetter(gSyncUI, "weaveService", function() {
return Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
});

View file

@ -46,7 +46,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
["Task", "resource://gre/modules/Task.jsm"],
["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
["Weave", "resource://services-sync/main.js"],
["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
#ifdef MOZ_DEVTOOLS
// Note: Do not delete! It is used for: base/content/nsContextMenu.js
["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
@ -1310,10 +1309,6 @@ var gBrowserInit = {
FullScreen.init();
PointerLock.init();
// initialize the sync UI
gSyncUI.init();
gFxAccounts.init();
if (AppConstants.MOZ_DATA_REPORTING)
gDataNotificationInfoBar.init();
@ -1450,8 +1445,6 @@ var gBrowserInit = {
FullScreen.uninit();
gFxAccounts.uninit();
Services.obs.removeObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
try {
@ -1611,9 +1604,6 @@ if (AppConstants.platform == "macosx") {
// initialize the private browsing UI
gPrivateBrowsingUI.init();
// initialize the sync UI
gSyncUI.init();
};
gBrowserInit.nonBrowserWindowShutdown = function() {
@ -7548,8 +7538,6 @@ var TabContextMenu = {
this.contextTab.addEventListener("TabAttrModified", this, false);
aPopupMenu.addEventListener("popuphiding", this, false);
gFxAccounts.updateTabContextMenu(aPopupMenu);
},
handleEvent(aEvent) {
switch (aEvent.type) {

View file

@ -27,7 +27,6 @@
<script type="application/javascript" src="chrome://browser/content/browser-safebrowsing.js"/>
#endif
<script type="application/javascript" src="chrome://browser/content/browser-sidebar.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-syncui.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-tabsintitlebar.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-thumbnails.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-trackingprotection.js"/>

View file

@ -112,7 +112,6 @@ nsContextMenu.prototype = {
this.initLeaveDOMFullScreenItems();
this.initClickToPlayItems();
this.initPasswordManagerItems();
this.initSyncItems();
},
initPageMenuSeparator: function CM_initPageMenuSeparator() {
@ -522,10 +521,6 @@ nsContextMenu.prototype = {
popup.insertBefore(fragment, insertBeforeElement);
},
initSyncItems: function() {
gFxAccounts.initPageContextMenu(this);
},
openPasswordManager: function() {
LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
},

View file

@ -76,7 +76,6 @@ browser.jar:
content/browser/browser-feeds.js (content/browser-feeds.js)
content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
content/browser/browser-fxaccounts.js (content/browser-fxaccounts.js)
content/browser/browser-gestureSupport.js (content/browser-gestureSupport.js)
* content/browser/browser-media.js (content/browser-media.js)
content/browser/browser-places.js (content/browser-places.js)
@ -86,7 +85,6 @@ browser.jar:
content/browser/browser-safebrowsing.js (content/browser-safebrowsing.js)
#endif
content/browser/browser-sidebar.js (content/browser-sidebar.js)
* content/browser/browser-syncui.js (content/browser-syncui.js)
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
#ifdef CAN_DRAW_IN_TITLEBAR
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)

View file

@ -200,7 +200,6 @@ var CustomizableUIInternal = {
"find-button",
"preferences-button",
"add-ons-button",
"sync-button",
];
if (!AppConstants.MOZ_DEV_EDITION) {

View file

@ -285,144 +285,6 @@ const CustomizableWidgets = [
onViewHiding: function(aEvent) {
log.debug("History view is being hidden!");
}
}, {
id: "sync-button",
label: "remotetabs-panelmenu.label",
tooltiptext: "remotetabs-panelmenu.tooltiptext2",
type: "view",
viewId: "PanelUI-remotetabs",
defaultArea: CustomizableUI.AREA_PANEL,
deckIndices: {
DECKINDEX_TABS: 0,
DECKINDEX_TABSDISABLED: 1,
DECKINDEX_FETCHING: 2,
DECKINDEX_NOCLIENTS: 3,
},
onCreated(aNode) {
// Add an observer to the button so we get the animation during sync.
// (Note the observer sets many attributes, including label and
// tooltiptext, but we only want the 'syncstatus' attribute for the
// animation)
let doc = aNode.ownerDocument;
let obnode = doc.createElementNS(kNSXUL, "observes");
obnode.setAttribute("element", "sync-status");
obnode.setAttribute("attribute", "syncstatus");
aNode.appendChild(obnode);
},
setDeckIndex(index) {
let deck = this._tabsList.ownerDocument.getElementById("PanelUI-remotetabs-deck");
// We call setAttribute instead of relying on the XBL property setter due
// to things going wrong when we try and set the index before the XBL
// binding has been created - see bug 1241851 for the gory details.
deck.setAttribute("selectedIndex", index);
},
_showTabsPromise: Promise.resolve(),
// Update the tab list after any existing in-flight updates are complete.
_showTabs() {
this._showTabsPromise = this._showTabsPromise.then(() => {
return this.__showTabs();
});
},
// Return a new promise to update the tab list.
__showTabs() {
let doc = this._tabsList.ownerDocument;
return SyncedTabs.getTabClients().then(clients => {
// The view may have been hidden while the promise was resolving.
if (!this._tabsList) {
return;
}
if (clients.length === 0 && !SyncedTabs.hasSyncedThisSession) {
// the "fetching tabs" deck is being shown - let's leave it there.
// When that first sync completes we'll be notified and update.
return;
}
if (clients.length === 0) {
this.setDeckIndex(this.deckIndices.DECKINDEX_NOCLIENTS);
return;
}
this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
this._clearTabList();
SyncedTabs.sortTabClientsByLastUsed(clients, 50 /* maxTabs */);
let fragment = doc.createDocumentFragment();
for (let client of clients) {
// add a menu separator for all clients other than the first.
if (fragment.lastChild) {
let separator = doc.createElementNS(kNSXUL, "menuseparator");
fragment.appendChild(separator);
}
this._appendClient(client, fragment);
}
this._tabsList.appendChild(fragment);
}).catch(err => {
Cu.reportError(err);
}).then(() => {
// an observer for tests.
Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated", null);
});
},
_clearTabList () {
let list = this._tabsList;
while (list.lastChild) {
list.lastChild.remove();
}
},
_showNoClientMessage() {
this._appendMessageLabel("notabslabel");
},
_appendMessageLabel(messageAttr, appendTo = null) {
if (!appendTo) {
appendTo = this._tabsList;
}
let message = this._tabsList.getAttribute(messageAttr);
let doc = this._tabsList.ownerDocument;
let messageLabel = doc.createElementNS(kNSXUL, "label");
messageLabel.textContent = message;
appendTo.appendChild(messageLabel);
return messageLabel;
},
_appendClient: function (client, attachFragment) {
let doc = attachFragment.ownerDocument;
// Create the element for the remote client.
let clientItem = doc.createElementNS(kNSXUL, "label");
clientItem.setAttribute("itemtype", "client");
let window = doc.defaultView;
clientItem.setAttribute("tooltiptext",
window.gSyncUI.formatLastSyncDate(new Date(client.lastModified)));
clientItem.textContent = client.name;
attachFragment.appendChild(clientItem);
if (client.tabs.length == 0) {
let label = this._appendMessageLabel("notabsforclientlabel", attachFragment);
label.setAttribute("class", "PanelUI-remotetabs-notabsforclient-label");
} else {
for (let tab of client.tabs) {
let tabEnt = this._createTabElement(doc, tab);
attachFragment.appendChild(tabEnt);
}
}
},
_createTabElement(doc, tabInfo) {
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
let tooltipText = (tabInfo.title ? tabInfo.title + "\n" : "") + tabInfo.url;
item.setAttribute("itemtype", "tab");
item.setAttribute("class", "subviewbutton");
item.setAttribute("targetURI", tabInfo.url);
item.setAttribute("label", tabInfo.title != "" ? tabInfo.title : tabInfo.url);
item.setAttribute("image", tabInfo.icon);
item.setAttribute("tooltiptext", tooltipText);
// We need to use "click" instead of "command" here so openUILink
// respects different buttons (eg, to open in a new tab).
item.addEventListener("click", e => {
doc.defaultView.openUILink(tabInfo.url, e);
CustomizableUI.hidePanelForNode(item);
});
return item;
},
}, {
id: "privatebrowsing-button",
shortcutId: "key_privatebrowsing",

View file

@ -20,27 +20,6 @@
oncommand="gMenuButtonUpdateBadge.onMenuPanelCommand(event);"
wrap="true"
hidden="true"/>
<hbox id="PanelUI-footer-fxa">
<hbox id="PanelUI-fxa-status"
defaultlabel="&fxaSignIn.label;"
signedinTooltiptext="&syncSettings.label;"
tooltiptext="&syncSettings.label;"
errorlabel="&fxaSignInError.label;"
unverifiedlabel="&fxaUnverified.label;"
settingslabel="&syncSettings.label;"
onclick="if (event.which == 1) gFxAccounts.onMenuPanelCommand();">
<image id="PanelUI-fxa-avatar"/>
<toolbarbutton id="PanelUI-fxa-label"
fxabrandname="&syncBrand.fxAccount.label;"/>
</hbox>
<toolbarseparator/>
<toolbarbutton id="PanelUI-fxa-icon"
oncommand="gSyncUI.doSync();"
closemenu="none">
<observes element="sync-status" attribute="syncstatus"/>
<observes element="sync-status" attribute="tooltiptext"/>
</toolbarbutton>
</hbox>
<hbox id="PanelUI-footer-inner">
<toolbarbutton id="PanelUI-customize" label="&appMenuCustomize.label;"
@ -103,95 +82,6 @@
oncommand="PlacesCommandHook.showPlacesOrganizer('History'); CustomizableUI.hidePanelForNode(this);"/>
</panelview>
<panelview id="PanelUI-remotetabs" flex="1" class="PanelUI-subView">
<label value="&appMenuRemoteTabs.label;" class="panel-subview-header"/>
<vbox class="panel-subview-body">
<!-- this widget has 3 boxes in the body, but only 1 is ever visible -->
<!-- When Sync is ready to sync -->
<vbox id="PanelUI-remotetabs-main" observes="sync-syncnow-state">
<vbox id="PanelUI-remotetabs-buttons">
<toolbarbutton id="PanelUI-remotetabs-view-sidebar"
class="subviewbutton"
oncommand="BrowserOpenSyncTabs();"
label="&appMenuRemoteTabs.sidebar.label;"/>
<toolbarbutton id="PanelUI-remotetabs-syncnow"
observes="sync-status"
class="subviewbutton"
oncommand="gSyncUI.doSync();"
closemenu="none"/>
<menuseparator id="PanelUI-remotetabs-separator"/>
</vbox>
<deck id="PanelUI-remotetabs-deck">
<!-- Sync is ready to Sync and the "tabs" engine is enabled -->
<vbox id="PanelUI-remotetabs-tabspane">
<vbox id="PanelUI-remotetabs-tabslist"
notabsforclientlabel="&appMenuRemoteTabs.notabs.label;"
/>
</vbox>
<!-- Sync is ready to Sync but the "tabs" engine isn't enabled-->
<hbox id="PanelUI-remotetabs-tabsdisabledpane" pack="center" flex="1">
<vbox class="PanelUI-remotetabs-instruction-box">
<hbox pack="center">
<image class="fxaSyncIllustration" alt=""/>
</hbox>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.tabsnotsyncing.label;</label>
<hbox pack="center">
<toolbarbutton class="PanelUI-remotetabs-prefs-button"
label="&appMenuRemoteTabs.openprefs.label;"
oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
</hbox>
</vbox>
</hbox>
<!-- Sync is ready to Sync but we are still fetching the tabs to show -->
<vbox id="PanelUI-remotetabs-fetching">
<!-- Show intentionally blank panel, see bug 1239845 -->
</vbox>
<!-- Sync has only 1 (ie, this) device connected -->
<hbox id="PanelUI-remotetabs-nodevicespane" pack="center" flex="1">
<vbox class="PanelUI-remotetabs-instruction-box">
<hbox pack="center">
<image class="fxaSyncIllustration" alt=""/>
</hbox>
<label class="PanelUI-remotetabs-instruction-title">&appMenuRemoteTabs.noclients.title;</label>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.noclients.subtitle;</label>
<!-- The inner HTML for PanelUI-remotetabs-mobile-promo is built at runtime -->
<label id="PanelUI-remotetabs-mobile-promo" fxAccountsBrand="&syncBrand.fxAccount.label;"/>
</vbox>
</hbox>
</deck>
</vbox>
<!-- a box to ensure contained boxes are centered horizonally -->
<hbox pack="center" flex="1">
<!-- When Sync is not configured -->
<vbox id="PanelUI-remotetabs-setupsync"
flex="1"
align="center"
class="PanelUI-remotetabs-instruction-box"
observes="sync-setup-state">
<image class="fxaSyncIllustration" alt=""/>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
<toolbarbutton class="PanelUI-remotetabs-prefs-button"
label="&appMenuRemoteTabs.signin.label;"
oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
</vbox>
<!-- When Sync needs re-authentication. This uses the exact same messaging
as "Sync is not configured" but remains a separate box so we get
the goodness of observing broadcasters to manage the hidden states -->
<vbox id="PanelUI-remotetabs-reauthsync"
flex="1"
align="center"
class="PanelUI-remotetabs-instruction-box"
observes="sync-reauth-state">
<image class="fxaSyncIllustration" alt=""/>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
<toolbarbutton class="PanelUI-remotetabs-prefs-button"
label="&appMenuRemoteTabs.signin.label;"
oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
</vbox>
</hbox>
</vbox>
</panelview>
<panelview id="PanelUI-bookmarks" flex="1" class="PanelUI-subView">
<label value="&bookmarksMenu.label;" class="panel-subview-header"/>
<vbox class="panel-subview-body">

View file

@ -9,7 +9,6 @@ DIRS += [
]
EXTRA_JS_MODULES += [
'CustomizableUI.jsm',
'CustomizableWidgets.jsm',
'CustomizeMode.jsm',
'DragPositionManager.jsm',
@ -17,5 +16,9 @@ EXTRA_JS_MODULES += [
'ScrollbarSampler.jsm',
]
EXTRA_PP_JS_MODULES += [
'CustomizableUI.jsm',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1

View file

@ -1418,9 +1418,9 @@ this.PlacesUIUtils = {
},
shouldShowTabsFromOtherComputersMenuitem: function() {
let weaveOK = Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED &&
Weave.Svc.Prefs.get("firstSync", "") != "notReady";
return weaveOK;
#ifdef MOZ_SERVICES_SYNC
// Weave code to enable menu item
#endif
},
/**

View file

@ -6,6 +6,6 @@
JAR_MANIFESTS += ['jar.mn']
EXTRA_JS_MODULES += [
EXTRA_PP_JS_MODULES += [
'PlacesUIUtils.jsm',
]

View file

@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/preferences/in-content/preferences.js
* content/browser/preferences/in-content/preferences.js
* content/browser/preferences/in-content/preferences.xul
content/browser/preferences/in-content/subdialogs.js
@ -12,6 +12,8 @@ browser.jar:
content/browser/preferences/in-content/advanced.js
content/browser/preferences/in-content/applications.js
* content/browser/preferences/in-content/content.js
#ifdef MOZ_SERVICES_SYNC
content/browser/preferences/in-content/sync.js
#endif
* content/browser/preferences/in-content/security.js
content/browser/preferences/in-content/search.js

View file

@ -64,7 +64,9 @@ function init_all() {
register_module("paneAdvanced", gAdvancedPane);
register_module("paneApplications", gApplicationsPane);
register_module("paneContent", gContentPane);
#ifdef MOZ_SERVICES_SYNC
register_module("paneSync", gSyncPane);
#endif
register_module("paneSecurity", gSecurityPane);
let categories = document.getElementById("categories");

View file

@ -22,8 +22,10 @@
<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
<!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
<!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences/search.dtd">
#ifdef MOZ_SERVICES_SYNC
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
#endif
<!ENTITY % securityDTD SYSTEM
"chrome://browser/locale/preferences/security.dtd">
<!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
@ -40,8 +42,10 @@
%privacyDTD;
%tabsDTD;
%searchDTD;
#ifdef MOZ_SERVICES_SYNC
%syncBrandDTD;
%syncDTD;
#endif
%securityDTD;
%sanitizeDTD;
%mainDTD;
@ -140,6 +144,7 @@
<label class="category-name" flex="1">&paneSecurity.title;</label>
</richlistitem>
#ifdef MOZ_SERVICES_SYNC
<richlistitem id="category-sync"
class="category"
value="paneSync"
@ -149,6 +154,7 @@
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSync.title;</label>
</richlistitem>
#endif
<richlistitem id="category-advanced"
class="category"
@ -177,7 +183,9 @@
#include applications.xul
#include content.xul
#include security.xul
#ifdef MOZ_SERVICES_SYNC
#include sync.xul
#endif
</prefpane>
</vbox>

View file

@ -61,8 +61,7 @@
height: 13px;
}
#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
box-shadow: none;
filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
}
@ -86,13 +85,7 @@
background: #D90000;
}
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
height: 13px;
background: transparent url(chrome://browser/skin/warning.svg) no-repeat center;
}
#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: none;
}
@ -381,9 +374,6 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"] > iframe {
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .panel-wide-item,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .toolbarbutton-1:not([panel-multiview-anchor="true"]),
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-update-status,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-status > #PanelUI-fxa-avatar,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-status > #PanelUI-fxa-label,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-icon,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > toolbarseparator,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-customize,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-help:not([panel-multiview-anchor="true"]) {
@ -481,26 +471,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
margin: 0;
}
#main-window[customizing] #PanelUI-footer-fxa {
display: none;
}
#PanelUI-footer-fxa:not([fxastatus="signedin"]) > toolbarseparator,
#PanelUI-footer-fxa:not([fxastatus="signedin"]) > #PanelUI-fxa-icon,
#PanelUI-footer-fxa:not([fxaprofileimage]) > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
display: none;
}
#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status::after {
content: url(chrome://browser/skin/warning.svg);
filter: drop-shadow(0 1px 0 hsla(206,50%,10%,.15));
width: 47px;
padding-top: 1px;
display: block;
text-align: center;
position: relative;
top: 25%;
}
#PanelUI-update-status[update-status]::after {
content: "";
@ -523,40 +493,28 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
background-color: #D90000;
}
#PanelUI-fxa-status {
display: flex;
flex: 1 1 0%;
width: 1px;
}
#PanelUI-footer-inner,
#PanelUI-footer-fxa:not([hidden]) {
#PanelUI-footer-inner {
display: flex;
border-top: 1px solid var(--panel-separator-color);
}
#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-inner,
#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-fxa {
#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-inner {
position: relative;
}
#PanelUI-footer-inner > toolbarseparator,
#PanelUI-footer-fxa > toolbarseparator {
#PanelUI-footer-inner > toolbarseparator {
border: 0;
border-left: 1px solid var(--panel-separator-color);
margin: 7px 0 7px;
-moz-appearance: none;
}
#PanelUI-footer-inner:hover > toolbarseparator,
#PanelUI-footer-fxa:hover > toolbarseparator {
#PanelUI-footer-inner:hover > toolbarseparator {
margin: 0;
}
#PanelUI-update-status,
#PanelUI-help,
#PanelUI-fxa-label,
#PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-quit {
margin: 0;
@ -590,7 +548,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-update-status > .toolbarbutton-text,
#PanelUI-fxa-label > .toolbarbutton-text,
#PanelUI-customize > .toolbarbutton-text {
margin: 0;
padding: 0 6px;
@ -598,37 +555,23 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-help > .toolbarbutton-text,
#PanelUI-quit > .toolbarbutton-text,
#PanelUI-fxa-avatar > .toolbarbutton-text {
#PanelUI-quit > .toolbarbutton-text {
display: none;
}
#PanelUI-update-status > .toolbarbutton-icon,
#PanelUI-fxa-label > .toolbarbutton-icon,
#PanelUI-fxa-icon > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,
#PanelUI-help > .toolbarbutton-icon,
#PanelUI-quit > .toolbarbutton-icon {
margin-inline-end: 0;
}
#PanelUI-fxa-icon {
padding-inline-start: 15px;
padding-inline-end: 15px;
}
#PanelUI-fxa-label,
#PanelUI-customize {
flex: 1;
padding-inline-start: 15px;
border-inline-start-style: none;
}
#PanelUI-footer-fxa[fxaprofileimage="set"] > #PanelUI-fxa-status > #PanelUI-fxa-label,
#PanelUI-footer-fxa[fxaprofileimage="enabled"]:not([fxastatus="error"]) > #PanelUI-fxa-status > #PanelUI-fxa-label {
padding-inline-start: 0px;
}
#PanelUI-update-status {
width: calc(@menuPanelWidth@ + 30px);
padding-inline-start: 15px;
@ -639,130 +582,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
list-style-image: url(chrome://branding/content/icon16.png);
}
#PanelUI-fxa-label,
#PanelUI-fxa-icon {
list-style-image: url(chrome://browser/skin/sync-horizontalbar.png);
}
#PanelUI-remotetabs {
--panel-ui-sync-illustration-height: 157.5px;
}
.PanelUI-remotetabs-instruction-title,
.PanelUI-remotetabs-instruction-label,
#PanelUI-remotetabs-mobile-promo {
/* If you change the margin here, the min-height of the synced tabs panel
(e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
need adjusting (see bug 1248506) */
margin: 15px;
text-align: center;
text-shadow: none;
max-width: 15em;
color: GrayText;
}
.PanelUI-remotetabs-instruction-title {
font-size: 1.3em;
}
/* The boxes with "instructions" get extra top and bottom padding for space
around the illustration and buttons */
.PanelUI-remotetabs-instruction-box {
/* If you change the padding here, the min-height of the synced tabs panel
(e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
need adjusting (see bug 1248506) */
padding-bottom: 30px;
padding-top: 15px;
}
.PanelUI-remotetabs-prefs-button {
-moz-appearance: none;
background-color: #0096dd;
/* !important for the color as an OSX specific rule when a lightweight theme
is used for buttons in the toolbox overrides. See bug 1238531 for details */
color: white !important;
border-radius: 2px;
/* If you change the margin or padding below, the min-height of the synced tabs
panel (e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync,
etc) may need adjusting (see bug 1248506) */
margin-top: 10px;
margin-bottom: 10px;
padding: 8px;
text-shadow: none;
min-width: 200px;
}
.PanelUI-remotetabs-prefs-button:hover,
.PanelUI-remotetabs-prefs-button:hover:active {
background-color: #018acb;
}
.remotetabs-promo-link {
margin: 0;
}
.PanelUI-remotetabs-notabsforclient-label {
color: GrayText;
/* This margin is to line this label up with the labels in toolbarbuttons. */
margin-left: 28px;
}
.fxaSyncIllustration {
height: var(--panel-ui-sync-illustration-height);
list-style-image: url(chrome://browser/skin/fxa/sync-illustration.svg);
}
.PanelUI-remotetabs-prefs-button > .toolbarbutton-text {
/* !important to override ".cui-widget-panel toolbarbutton > .toolbarbutton-text" above. */
text-align: center !important;
text-shadow: none;
}
#PanelUI-remotetabs[mainview] { /* panel anchored to toolbar button might be too skinny */
min-width: 19em;
}
/* Work around bug 1224412 - these boxes will cause scrollbars to appear when
the panel is anchored to a toolbar button.
*/
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync,
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-reauthsync,
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-nodevicespane,
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-tabsdisabledpane {
min-height: calc(var(--panel-ui-sync-illustration-height) +
20px + /* margin of .PanelUI-remotetabs-prefs-button */
16px + /* padding of .PanelUI-remotetabs-prefs-button */
30px + /* margin of .PanelUI-remotetabs-instruction-label */
30px + 15px + /* padding of .PanelUI-remotetabs-instruction-box */
11em);
}
#PanelUI-remotetabs-tabslist > label[itemtype="client"] {
color: GrayText;
}
/* Collapse the non-active vboxes in the remotetabs deck to use only the
height the active box needs */
#PanelUI-remotetabs-deck:not([selectedIndex="1"]) > #PanelUI-remotetabs-tabsdisabledpane,
#PanelUI-remotetabs-deck:not([selectedIndex="2"]) > #PanelUI-remotetabs-fetching,
#PanelUI-remotetabs-deck:not([selectedIndex="3"]) > #PanelUI-remotetabs-nodevicespane {
visibility: collapse;
}
#PanelUI-remotetabs-main[devices-status="single"] > #PanelUI-remotetabs-buttons {
display: none;
}
#PanelUI-fxa-icon[syncstatus="active"]:not([disabled]) {
list-style-image: url(chrome://browser/skin/syncProgress-horizontalbar.png);
}
#PanelUI-footer-fxa[fxastatus="migrate-signup"] > #PanelUI-fxa-status > #PanelUI-fxa-label,
#PanelUI-footer-fxa[fxastatus="migrate-verify"] > #PanelUI-fxa-status > #PanelUI-fxa-label {
list-style-image: url(chrome://browser/skin/warning.svg);
-moz-image-region: auto;
}
#PanelUI-customize {
list-style-image: url(chrome://browser/skin/menuPanel-customize.png);
}
@ -780,46 +599,12 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
list-style-image: url(chrome://browser/skin/menuPanel-exit.png);
}
#PanelUI-fxa-label,
#PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-help,
#PanelUI-quit {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#PanelUI-footer-fxa[fxastatus="signedin"] > #PanelUI-fxa-status > #PanelUI-fxa-label > .toolbarbutton-icon,
#PanelUI-footer-fxa[fxastatus="error"][fxaprofileimage="set"] > #PanelUI-fxa-status > #PanelUI-fxa-label > .toolbarbutton-icon {
display: none;
}
#PanelUI-footer-fxa[fxastatus="error"]:not([fxaprofileimage="set"]) > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
display: none;
}
#PanelUI-fxa-status[disabled],
#PanelUI-fxa-icon[disabled] {
pointer-events: none;
}
#PanelUI-fxa-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background-repeat: no-repeat;
background-position: 0 0;
background-size: contain;
align-self: center;
margin: 0px 7px;
padding: 0px;
border: 0px none;
margin-inline-end: 0;
}
#PanelUI-footer-fxa[fxaprofileimage="enabled"] > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
list-style-image: url(chrome://browser/skin/fxa/default-avatar.svg);
}
#PanelUI-customize:hover,
#PanelUI-help:not([disabled]):hover,
#PanelUI-quit:not([disabled]):hover {
@ -837,16 +622,10 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-help[disabled],
#PanelUI-quit[disabled],
#PanelUI-fxa-icon[disabled],
#PanelUI-fxa-avatar[disabled],
#PanelUI-fxa-label[disabled] > .toolbarbutton-icon,
#PanelUI-fxa-status::after {
#PanelUI-quit[disabled] {
opacity: 0.4;
}
#PanelUI-fxa-status:not([disabled]):hover,
#PanelUI-fxa-icon:not([disabled]):hover,
#PanelUI-help:not([disabled]):hover,
#PanelUI-customize:hover,
#PanelUI-quit:not([disabled]):hover {
@ -854,8 +633,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
background-color: var(--arrowpanel-dimmed);
}
#PanelUI-fxa-status:not([disabled]):hover:active,
#PanelUI-fxa-icon:not([disabled]):hover:active,
#PanelUI-help:not([disabled]):hover:active,
#PanelUI-customize:hover:active,
#PanelUI-quit:not([disabled]):hover:active {
@ -864,27 +641,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
#PanelUI-fxa-status:not([disabled]):hover,
#PanelUI-fxa-status:not([disabled]):hover:active,
#PanelUI-fxa-icon:not([disabled]):hover,
#PanelUI-fxa-icon:not([disabled]):hover:active {
outline: none;
}
#PanelUI-footer-fxa[fxastatus="error"] {
background-color: hsl(42,94%,88%);
border-top: 1px solid hsl(42,94%,70%);
}
#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status:hover {
background-color: hsl(42,94%,85%);
}
#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status:hover:active {
background-color: hsl(42,94%,82%);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
#PanelUI-update-status {
color: black;
}
@ -1150,19 +906,16 @@ menuitem.panel-subview-footer@menuStateActive@,
color: GrayText;
}
#PanelUI-remotetabs-tabslist > toolbarbutton,
#PanelUI-historyItems > toolbarbutton {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
}
@media (min-resolution: 1.1dppx) {
#PanelUI-remotetabs-tabslist > toolbarbutton,
#PanelUI-historyItems > toolbarbutton {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
}
}
#PanelUI-remotetabs-tabslist > toolbarbutton > .toolbarbutton-icon,
#PanelUI-recentlyClosedWindows > toolbarbutton > .toolbarbutton-icon,
#PanelUI-recentlyClosedTabs > toolbarbutton > .toolbarbutton-icon,
#PanelUI-historyItems > toolbarbutton > .toolbarbutton-icon {
@ -1616,15 +1369,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
list-style-image: url(chrome://branding/content/icon32.png);
}
#PanelUI-fxa-label,
#PanelUI-fxa-icon {
list-style-image: url(chrome://browser/skin/sync-horizontalbar@2x.png);
}
#PanelUI-fxa-icon[syncstatus="active"]:not([disabled]) {
list-style-image: url(chrome://browser/skin/syncProgress-horizontalbar@2x.png);
}
#PanelUI-customize {
list-style-image: url(chrome://browser/skin/menuPanel-customize@2x.png);
}
@ -1641,8 +1385,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
list-style-image: url(chrome://browser/skin/menuPanel-exit@2x.png);
}
#PanelUI-fxa-label,
#PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-help,
#PanelUI-quit {
@ -1650,8 +1392,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
}
#PanelUI-update-status > .toolbarbutton-icon,
#PanelUI-fxa-label > .toolbarbutton-icon,
#PanelUI-fxa-icon > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,
#PanelUI-help > .toolbarbutton-icon,
#PanelUI-quit > .toolbarbutton-icon {