--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -280,17 +280,17 @@
accesskey="&savePageCmd.accesskey2;"
oncommand="gContextMenu.savePageAs();"/>
<menuseparator id="context-sep-sendpagetodevice" hidden="true"/>
<menu id="context-sendpagetodevice"
label="&sendPageToDevice.label;"
accesskey="&sendPageToDevice.accesskey;"
hidden="true">
<menupopup id="context-sendpagetodevice-popup"
- onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gFxAccounts.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
+ onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gSync.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
</menu>
<menuseparator id="context-sep-viewbgimage"/>
<menuitem id="context-viewbgimage"
label="&viewBGImageCmd.label;"
accesskey="&viewBGImageCmd.accesskey;"
oncommand="gContextMenu.viewBGImage(event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-undo"
@@ -327,17 +327,17 @@
<menuitem id="context-searchselect"
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/>
<menuseparator id="context-sep-sendlinktodevice" hidden="true"/>
<menu id="context-sendlinktodevice"
label="&sendLinkToDevice.label;"
accesskey="&sendLinkToDevice.accesskey;"
hidden="true">
<menupopup id="context-sendlinktodevice-popup"
- onpopupshowing="gFxAccounts.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
+ onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
</menu>
<menuitem id="context-shareselect"
label="&shareSelect.label;"
accesskey="&shareSelect.accesskey;"
oncommand="gContextMenu.shareSelect();"/>
<menuseparator id="frame-sep"/>
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
<menupopup>
deleted file mode 100644
--- a/browser/base/content/browser-fxaccounts.js
+++ /dev/null
@@ -1,340 +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://services-sync/UIState.jsm");
-
-var gFxAccounts = {
- _initialized: false,
-
- 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 sendTabToDeviceEnabled() {
- return Services.prefs.getBoolPref("services.sync.sendTabToDevice.enabled");
- },
-
- isSendableURI(aURISpec) {
- if (!aURISpec) {
- return false;
- }
- // Disallow sending tabs with more than 65535 characters.
- if (aURISpec.length > 65535) {
- return false;
- }
- try {
- // Filter out un-sendable URIs -- things like local files, object urls, etc.
- const unsendableRegexp = new RegExp(
- Services.prefs.getCharPref("services.sync.engine.tabs.filteredUrls"), "i");
- return !unsendableRegexp.test(aURISpec);
- } catch (e) {
- // The preference has been removed, or is an invalid regexp, so we log an
- // error and treat it as a valid URI -- and the more problematic case is
- // the length, which we've already addressed.
- Cu.reportError(`Failed to build url filter regexp for send tab: ${e}`);
- return true;
- }
- },
-
- get remoteClients() {
- return Weave.Service.clientsEngine.remoteClients
- .sort((a, b) => a.name.localeCompare(b.name));
- },
-
- init() {
- // Bail out if we're already initialized and for pop-up windows.
- if (this._initialized || !window.toolbar.visible) {
- return;
- }
-
- Services.obs.addObserver(this, UIState.ON_UPDATE);
- setTimeout(() => {
- if (UIState.ensureReady()) {
- const state = UIState.get();
- // The UI is already in the right state, optimize this.
- if (state.status != UIState.STATUS_NOT_CONFIGURED) {
- this.updateAllUI(state);
- }
- }
- }, 1000);
-
- EnsureFxAccountsWebChannel();
- this._initialized = true;
- },
-
- uninit() {
- if (!this._initialized) {
- return;
- }
-
- Services.obs.removeObserver(this, UIState.ON_UPDATE);
-
- this._initialized = false;
- },
-
- observe(subject, topic, data) {
- if (topic != UIState.ON_UPDATE) {
- return;
- }
- const state = UIState.get();
- this.updateAllUI(state);
- },
-
- updateAllUI(state) {
- this.updatePanelBadge(state);
- this.updatePanelPopup(state);
- gSyncUI.updateStateBroadcasters(state);
- gSyncUI.updateSyncButtonsTooltip(state);
- gSyncUI.updateSyncStatus(state);
- },
-
- updatePanelPopup(state) {
- this.panelUIFooter.hidden = false;
-
- let defaultLabel = this.panelUIStatus.getAttribute("defaultlabel");
- let errorLabel = this.panelUIStatus.getAttribute("errorlabel");
- let unverifiedLabel = this.panelUIStatus.getAttribute("unverifiedlabel");
- // The localization string is for the signed in text, but it's the default text as well
- let defaultTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
-
- const status = state.status;
- // 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 (status == UIState.STATUS_NOT_CONFIGURED) {
- // If we're not configured, we won't have a profile, bail early.
- return;
- }
-
- // At this point we consider the user as logged-in (but still can be in an error state)
- if (status == UIState.STATUS_LOGIN_FAILED) {
- let tooltipDescription = this.strings.formatStringFromName("reconnectDescription", [state.email], 1);
- this.panelUIFooter.setAttribute("fxastatus", "error");
- this.panelUILabel.setAttribute("label", errorLabel);
- this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
- } else if (status == UIState.STATUS_NOT_VERIFIED) {
- let tooltipDescription = this.strings.formatStringFromName("verifyDescription", [state.email], 1);
- this.panelUIFooter.setAttribute("fxastatus", "error");
- this.panelUIFooter.setAttribute("unverified", "true");
- this.panelUILabel.setAttribute("label", unverifiedLabel);
- this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
- } else {
- this.panelUIFooter.setAttribute("fxastatus", "signedin");
- this.panelUILabel.setAttribute("label", state.email);
- }
- this.panelUIFooter.setAttribute("fxaprofileimage", "enabled");
-
- if (state.displayName) {
- this.panelUILabel.setAttribute("label", state.displayName);
- }
- if (state.avatarURL) {
- this.panelUIFooter.setAttribute("fxaprofileimage", "set");
- let bgImage = "url(\"" + state.avatarURL + "\")";
- 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 = state.avatarURL;
- }
- },
-
- updatePanelBadge(state) {
- if (state.status == UIState.STATUS_LOGIN_FAILED ||
- state.status == UIState.STATUS_NOT_VERIFIED) {
- PanelUI.showBadgeOnlyNotification("fxa-needs-authentication");
- } else {
- PanelUI.removeNotification("fxa-needs-authentication");
- }
- },
-
- onMenuPanelCommand() {
- 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() {
- openPreferences("paneSync", { urlParams: { entrypoint: "menupanel" } });
- },
-
- openAccountsPage(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(entryPoint) {
- this.openAccountsPage("reauth", { entrypoint: entryPoint });
- },
-
- async openDevicesManagementPage(entryPoint) {
- let url = await fxAccounts.promiseAccountsManageDevicesURI(entryPoint);
- switchToTabHavingURI(url, true, {
- replaceQueryString: true
- });
- },
-
- sendTabToDevice(url, clientId, title) {
- Weave.Service.clientsEngine.sendURIToClientForDisplay(url, clientId, title);
- },
-
- populateSendTabToDevicesMenu(devicesPopup, url, title) {
- // remove existing menu items
- while (devicesPopup.hasChildNodes()) {
- devicesPopup.firstChild.remove();
- }
-
- const fragment = document.createDocumentFragment();
-
- const onTargetDeviceCommand = (event) => {
- let clients = event.target.getAttribute("clientId") ?
- [event.target.getAttribute("clientId")] :
- this.remoteClients.map(client => client.id);
-
- clients.forEach(clientId => this.sendTabToDevice(url, clientId, title));
- }
-
- function addTargetDevice(clientId, name) {
- const targetDevice = document.createElement("menuitem");
- targetDevice.addEventListener("command", onTargetDeviceCommand, true);
- targetDevice.setAttribute("class", "sendtab-target");
- targetDevice.setAttribute("clientId", clientId);
- targetDevice.setAttribute("label", name);
- fragment.appendChild(targetDevice);
- }
-
- const clients = this.remoteClients;
- for (let client of clients) {
- addTargetDevice(client.id, client.name);
- }
-
- // "All devices" menu item
- if (clients.length > 1) {
- const separator = document.createElement("menuseparator");
- fragment.appendChild(separator);
- const allDevicesLabel = this.strings.GetStringFromName("sendTabToAllDevices.menuitem");
- addTargetDevice("", allDevicesLabel);
- }
-
- devicesPopup.appendChild(fragment);
- },
-
- updateTabContextMenu(aPopupMenu, aTargetTab) {
- if (!this.sendTabToDeviceEnabled ||
- !this.weaveService.ready) {
- return;
- }
-
- const targetURI = aTargetTab.linkedBrowser.currentURI.spec;
- const showSendTab = this.remoteClients.length > 0 && this.isSendableURI(targetURI);
-
- ["context_sendTabToDevice", "context_sendTabToDevice_separator"]
- .forEach(id => { document.getElementById(id).hidden = !showSendTab });
- },
-
- initPageContextMenu(contextMenu) {
- if (!this.sendTabToDeviceEnabled ||
- !this.weaveService.ready) {
- return;
- }
-
- const remoteClientPresent = this.remoteClients.length > 0;
- // showSendLink and showSendPage are mutually exclusive
- let showSendLink = remoteClientPresent
- && (contextMenu.onSaveableLink || contextMenu.onPlainTextLink);
- const showSendPage = !showSendLink && remoteClientPresent
- && !(contextMenu.isContentSelected ||
- contextMenu.onImage || contextMenu.onCanvas ||
- contextMenu.onVideo || contextMenu.onAudio ||
- contextMenu.onLink || contextMenu.onTextInput)
- && this.isSendableURI(contextMenu.browser.currentURI.spec);
-
- if (showSendLink) {
- // This isn't part of the condition above since we don't want to try and
- // send the page if a link is clicked on or selected but is not sendable.
- showSendLink = this.isSendableURI(contextMenu.linkURL);
- }
-
- ["context-sendpagetodevice", "context-sep-sendpagetodevice"]
- .forEach(id => contextMenu.showItem(id, showSendPage));
- ["context-sendlinktodevice", "context-sep-sendlinktodevice"]
- .forEach(id => contextMenu.showItem(id, showSendLink));
- }
-};
-
-XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function() {
- return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
-});
-
-XPCOMUtils.defineLazyModuleGetter(this, "EnsureFxAccountsWebChannel",
- "resource://gre/modules/FxAccountsWebChannel.jsm");
-
-
-XPCOMUtils.defineLazyGetter(gFxAccounts, "weaveService", function() {
- return Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
-});
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -487,27 +487,27 @@
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.openPrefs('menubar')"/>
+ oncommand="gSync.openPrefs('menubar')"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
observes="sync-syncnow-state"
- oncommand="gSyncUI.doSync(event);"/>
+ oncommand="gSync.doSync(event);"/>
<menuitem id="sync-reauthitem"
label="&syncReAuthItem.label;"
accesskey="&syncReAuthItem.accesskey;"
observes="sync-reauth-state"
- oncommand="gSyncUI.openSignInAgainPage('menubar');"/>
+ oncommand="gSync.openSignInAgainPage('menubar');"/>
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup">
<menuitem id="menu_pageSource"
observes="devtoolsMenuBroadcaster_PageSource"
accesskey="&pageSourceCmd.accesskey;"/>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-sync.js
@@ -0,0 +1,644 @@
+/* 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://services-sync/UIState.jsm");
+
+const MIN_STATUS_ANIMATION_DURATION = 1600;
+
+var gSync = {
+ _initialized: false,
+ // The last sync start time. Used to calculate the leftover animation time
+ // once syncing completes (bug 1239042).
+ _syncStartTime: 0,
+ _syncAnimationTimer: 0,
+ _withinLastWeekFormat: null,
+ _oneWeekOrOlderFormat: null,
+
+ _obs: [
+ "weave:engine:sync:finish",
+ "quit-application",
+ UIState.ON_UPDATE
+ ],
+
+ 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 syncStrings() {
+ delete this.syncStrings;
+ // XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
+ // but for now just make it work
+ return this.syncStrings = Services.strings.createBundle(
+ "chrome://weave/locale/sync.properties"
+ );
+ },
+
+ get sendTabToDeviceEnabled() {
+ return Services.prefs.getBoolPref("services.sync.sendTabToDevice.enabled");
+ },
+
+ get remoteClients() {
+ return Weave.Service.clientsEngine.remoteClients
+ .sort((a, b) => a.name.localeCompare(b.name));
+ },
+
+ init() {
+ // Bail out if we're already initialized and for pop-up windows.
+ if (this._initialized || !window.toolbar.visible) {
+ return;
+ }
+
+ for (let topic of this._obs) {
+ Services.obs.addObserver(this, topic, true);
+ }
+
+ // initial label for the sync buttons.
+ let broadcaster = document.getElementById("sync-status");
+ broadcaster.setAttribute("label", this.syncStrings.GetStringFromName("syncnow.label"));
+
+ this.maybeMoveSyncedTabsButton();
+
+ EnsureFxAccountsWebChannel();
+
+ setTimeout(() => {
+ if (UIState.ensureReady()) {
+ const state = UIState.get();
+ // The UI is already in the right state, optimize this.
+ if (state.status != UIState.STATUS_NOT_CONFIGURED) {
+ this.updateAllUI(state);
+ }
+ }
+ }, 1000);
+
+ this._initialized = true;
+ },
+
+ uninit() {
+ if (!this._initialized) {
+ return;
+ }
+
+ for (let topic of this._obs) {
+ Services.obs.removeObserver(this, topic);
+ }
+
+ this._initialized = false;
+ },
+
+ observe(subject, topic, data) {
+ if (!this._initialized) {
+ Cu.reportError("browser-sync observer called after unload: " + topic);
+ return;
+ }
+ switch (topic) {
+ case UIState.ON_UPDATE:
+ const state = UIState.get();
+ this.updateAllUI(state);
+ break;
+ case "quit-application":
+ // Stop the animation timer on shutdown, since we can't update the UI
+ // after this.
+ clearTimeout(this._syncAnimationTimer);
+ break;
+ case "weave:engine:sync:finish":
+ if (data != "clients") {
+ return;
+ }
+ this.onClientsSynced();
+ break;
+ }
+ },
+
+ updateAllUI(state) {
+ this.updatePanelBadge(state);
+ this.updatePanelPopup(state);
+ this.updateStateBroadcasters(state);
+ this.updateSyncButtonsTooltip(state);
+ this.updateSyncStatus(state);
+ },
+
+ updatePanelPopup(state) {
+ this.panelUIFooter.hidden = false;
+
+ let defaultLabel = this.panelUIStatus.getAttribute("defaultlabel");
+ let errorLabel = this.panelUIStatus.getAttribute("errorlabel");
+ let unverifiedLabel = this.panelUIStatus.getAttribute("unverifiedlabel");
+ // The localization string is for the signed in text, but it's the default text as well
+ let defaultTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
+
+ const status = state.status;
+ // 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 (status == UIState.STATUS_NOT_CONFIGURED) {
+ // If we're not configured, we won't have a profile, bail early.
+ return;
+ }
+
+ // At this point we consider the user as logged-in (but still can be in an error state)
+ if (status == UIState.STATUS_LOGIN_FAILED) {
+ let tooltipDescription = this.strings.formatStringFromName("reconnectDescription", [state.email], 1);
+ this.panelUIFooter.setAttribute("fxastatus", "error");
+ this.panelUILabel.setAttribute("label", errorLabel);
+ this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
+ } else if (status == UIState.STATUS_NOT_VERIFIED) {
+ let tooltipDescription = this.strings.formatStringFromName("verifyDescription", [state.email], 1);
+ this.panelUIFooter.setAttribute("fxastatus", "error");
+ this.panelUIFooter.setAttribute("unverified", "true");
+ this.panelUILabel.setAttribute("label", unverifiedLabel);
+ this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
+ } else {
+ this.panelUIFooter.setAttribute("fxastatus", "signedin");
+ this.panelUILabel.setAttribute("label", state.email);
+ }
+ this.panelUIFooter.setAttribute("fxaprofileimage", "enabled");
+
+ if (state.displayName) {
+ this.panelUILabel.setAttribute("label", state.displayName);
+ }
+ if (state.avatarURL) {
+ this.panelUIFooter.setAttribute("fxaprofileimage", "set");
+ let bgImage = "url(\"" + state.avatarURL + "\")";
+ 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 = state.avatarURL;
+ }
+ },
+
+ updatePanelBadge(state) {
+ if (state.status == UIState.STATUS_LOGIN_FAILED ||
+ state.status == UIState.STATUS_NOT_VERIFIED) {
+ PanelUI.showBadgeOnlyNotification("fxa-needs-authentication");
+ } else {
+ PanelUI.removeNotification("fxa-needs-authentication");
+ }
+ },
+
+ updateStateBroadcasters(state) {
+ const status = state.status;
+
+ // 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 (CloudSync && CloudSync.ready && CloudSync().adapters.count) {
+ document.getElementById("sync-syncnow-state").hidden = false;
+ } else if (status == UIState.STATUS_LOGIN_FAILED) {
+ // unhiding this element makes the menubar show the login failure state.
+ document.getElementById("sync-reauth-state").hidden = false;
+ } else if (status == UIState.STATUS_NOT_CONFIGURED ||
+ status == UIState.STATUS_NOT_VERIFIED) {
+ document.getElementById("sync-setup-state").hidden = false;
+ } else {
+ document.getElementById("sync-syncnow-state").hidden = false;
+ }
+ },
+
+ updateSyncStatus(state) {
+ const broadcaster = document.getElementById("sync-status");
+ const syncingUI = broadcaster.getAttribute("syncstatus") == "active";
+ if (state.syncing != syncingUI) { // Do we need to update the UI?
+ state.syncing ? this.onActivityStart() : this.onActivityStop();
+ }
+ },
+
+ onMenuPanelCommand() {
+ 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() {
+ openPreferences("paneSync", { urlParams: { entrypoint: "menupanel" } });
+ },
+
+ openAccountsPage(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(entryPoint) {
+ this.openAccountsPage("reauth", { entrypoint: entryPoint });
+ },
+
+ async openDevicesManagementPage(entryPoint) {
+ let url = await fxAccounts.promiseAccountsManageDevicesURI(entryPoint);
+ switchToTabHavingURI(url, true, {
+ replaceQueryString: true
+ });
+ },
+
+ sendTabToDevice(url, clientId, title) {
+ Weave.Service.clientsEngine.sendURIToClientForDisplay(url, clientId, title);
+ },
+
+ populateSendTabToDevicesMenu(devicesPopup, url, title) {
+ // remove existing menu items
+ while (devicesPopup.hasChildNodes()) {
+ devicesPopup.firstChild.remove();
+ }
+
+ const fragment = document.createDocumentFragment();
+
+ const onTargetDeviceCommand = (event) => {
+ let clients = event.target.getAttribute("clientId") ?
+ [event.target.getAttribute("clientId")] :
+ this.remoteClients.map(client => client.id);
+
+ clients.forEach(clientId => this.sendTabToDevice(url, clientId, title));
+ }
+
+ function addTargetDevice(clientId, name) {
+ const targetDevice = document.createElement("menuitem");
+ targetDevice.addEventListener("command", onTargetDeviceCommand, true);
+ targetDevice.setAttribute("class", "sendtab-target");
+ targetDevice.setAttribute("clientId", clientId);
+ targetDevice.setAttribute("label", name);
+ fragment.appendChild(targetDevice);
+ }
+
+ const clients = this.remoteClients;
+ for (let client of clients) {
+ addTargetDevice(client.id, client.name);
+ }
+
+ // "All devices" menu item
+ if (clients.length > 1) {
+ const separator = document.createElement("menuseparator");
+ fragment.appendChild(separator);
+ const allDevicesLabel = this.strings.GetStringFromName("sendTabToAllDevices.menuitem");
+ addTargetDevice("", allDevicesLabel);
+ }
+
+ devicesPopup.appendChild(fragment);
+ },
+
+ isSendableURI(aURISpec) {
+ if (!aURISpec) {
+ return false;
+ }
+ // Disallow sending tabs with more than 65535 characters.
+ if (aURISpec.length > 65535) {
+ return false;
+ }
+ try {
+ // Filter out un-sendable URIs -- things like local files, object urls, etc.
+ const unsendableRegexp = new RegExp(
+ Services.prefs.getCharPref("services.sync.engine.tabs.filteredUrls"), "i");
+ return !unsendableRegexp.test(aURISpec);
+ } catch (e) {
+ // The preference has been removed, or is an invalid regexp, so we log an
+ // error and treat it as a valid URI -- and the more problematic case is
+ // the length, which we've already addressed.
+ Cu.reportError(`Failed to build url filter regexp for send tab: ${e}`);
+ return true;
+ }
+ },
+
+ updateTabContextMenu(aPopupMenu, aTargetTab) {
+ if (!this.sendTabToDeviceEnabled ||
+ !this.weaveService.ready) {
+ return;
+ }
+
+ const targetURI = aTargetTab.linkedBrowser.currentURI.spec;
+ const showSendTab = this.remoteClients.length > 0 && this.isSendableURI(targetURI);
+
+ ["context_sendTabToDevice", "context_sendTabToDevice_separator"]
+ .forEach(id => { document.getElementById(id).hidden = !showSendTab });
+ },
+
+ initPageContextMenu(contextMenu) {
+ if (!this.sendTabToDeviceEnabled ||
+ !this.weaveService.ready) {
+ return;
+ }
+
+ const remoteClientPresent = this.remoteClients.length > 0;
+ // showSendLink and showSendPage are mutually exclusive
+ let showSendLink = remoteClientPresent
+ && (contextMenu.onSaveableLink || contextMenu.onPlainTextLink);
+ const showSendPage = !showSendLink && remoteClientPresent
+ && !(contextMenu.isContentSelected ||
+ contextMenu.onImage || contextMenu.onCanvas ||
+ contextMenu.onVideo || contextMenu.onAudio ||
+ contextMenu.onLink || contextMenu.onTextInput)
+ && this.isSendableURI(contextMenu.browser.currentURI.spec);
+
+ if (showSendLink) {
+ // This isn't part of the condition above since we don't want to try and
+ // send the page if a link is clicked on or selected but is not sendable.
+ showSendLink = this.isSendableURI(contextMenu.linkURL);
+ }
+
+ ["context-sendpagetodevice", "context-sep-sendpagetodevice"]
+ .forEach(id => contextMenu.showItem(id, showSendPage));
+ ["context-sendlinktodevice", "context-sep-sendlinktodevice"]
+ .forEach(id => contextMenu.showItem(id, showSendLink));
+ },
+
+ // Functions called by observers
+ onActivityStart() {
+ 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.syncStrings.GetStringFromName("syncing2.label"));
+ broadcaster.setAttribute("disabled", "true");
+ },
+
+ _updateSyncStatus() {
+ if (!gBrowser)
+ return;
+ let broadcaster = document.getElementById("sync-status");
+ broadcaster.removeAttribute("syncstatus");
+ broadcaster.removeAttribute("disabled");
+ broadcaster.setAttribute("label", this.syncStrings.GetStringFromName("syncnow.label"));
+ },
+
+ onActivityStop() {
+ 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();
+ }
+ },
+
+ // Commands
+ // doSync forces a sync - it *does not* return a promise as it is called
+ // via the various UI components.
+ doSync() {
+ const state = UIState.get();
+ if (state.status == UIState.STATUS_SIGNED_IN) {
+ setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0);
+ }
+ Services.obs.notifyObservers(null, "cloudsync:user-sync");
+ },
+
+ // 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() {
+ const state = UIState.get();
+ if (state.status == UIState.STATUS_SIGNED_IN) {
+ this.doSync();
+ } else {
+ this.openPrefs();
+ }
+ },
+
+ /**
+ * Open the Sync preferences.
+ *
+ * @param entryPoint
+ * Indicates the entrypoint from where this method was called.
+ */
+ openPrefs(entryPoint = "syncbutton") {
+ openPreferences("paneSync", { urlParams: { entrypoint: entryPoint } });
+ },
+
+ openSignInAgainPage(entryPoint = "syncbutton") {
+ gSync.openSignInAgainPage(entryPoint);
+ },
+
+ openSyncedTabsPanel() {
+ let placement = CustomizableUI.getPlacementOfWidget("sync-button");
+ let area = placement ? placement.area : CustomizableUI.AREA_NAVBAR;
+ let anchor = document.getElementById("sync-button") ||
+ document.getElementById("PanelUI-menu-button");
+ if (area == CustomizableUI.AREA_PANEL) {
+ // The button is in the panel, so we need to show the panel UI, then our
+ // subview.
+ PanelUI.show().then(() => {
+ PanelUI.showSubView("PanelUI-remotetabs", anchor, area);
+ }).catch(Cu.reportError);
+ } else {
+ // It is placed somewhere else - just try and show it.
+ PanelUI.showSubView("PanelUI-remotetabs", anchor, area);
+ }
+ },
+
+ /* 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 = Services.prefs.getBoolPref(prefName, false);
+ 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(state) {
+ const status = state.status;
+
+ // 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 gSync for strings.
+ let tooltiptext;
+ if (status == UIState.STATUS_NOT_VERIFIED) {
+ // "needs verification"
+ tooltiptext = gSync.strings.formatStringFromName("verifyDescription", [state.email], 1);
+ } else if (status == UIState.STATUS_NOT_CONFIGURED) {
+ // "needs setup".
+ tooltiptext = this.syncStrings.GetStringFromName("signInToSync.description");
+ } else if (status == UIState.STATUS_LOGIN_FAILED) {
+ // "need to reconnect/re-enter your password"
+ tooltiptext = gSync.strings.formatStringFromName("reconnectDescription", [state.email], 1);
+ } else {
+ // Sync appears configured - format the "last synced at" time.
+ try {
+ let lastSync = new Date(state.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.
+ }
+ }
+
+ let broadcaster = document.getElementById("sync-status");
+ if (broadcaster) {
+ if (tooltiptext) {
+ broadcaster.setAttribute("tooltiptext", tooltiptext);
+ } else {
+ broadcaster.removeAttribute("tooltiptext");
+ }
+ }
+ },
+
+ getWithinLastWeekFormat() {
+ return this._withinLastWeekFormat ||
+ (this._withinLastWeekFormat =
+ new Intl.DateTimeFormat(undefined, {weekday: "long", hour: "numeric", minute: "numeric"}));
+ },
+
+ getOneWeekOrOlderFormat() {
+ return this._oneWeekOrOlderFormat ||
+ (this._oneWeekOrOlderFormat =
+ new Intl.DateTimeFormat(undefined, {month: "long", day: "numeric"}));
+ },
+
+ formatLastSyncDate(date) {
+ let sixDaysAgo = (() => {
+ let tempDate = new Date();
+ tempDate.setDate(tempDate.getDate() - 6);
+ tempDate.setHours(0, 0, 0, 0);
+ return tempDate;
+ })();
+
+ // It may be confusing for the user to see "Last Sync: Monday" when the last
+ // sync was indeed a Monday, but 3 weeks ago.
+ let dateFormat = date < sixDaysAgo ? this.getOneWeekOrOlderFormat() : this.getWithinLastWeekFormat();
+
+ let lastSyncDateString = dateFormat.format(date);
+ return this.syncStrings.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
+ },
+
+ onClientsSynced() {
+ 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");
+ }
+ }
+ },
+
+ // 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() {
+ // 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;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIObserver,
+ Ci.nsISupportsWeakReference
+ ])
+};
+
+XPCOMUtils.defineLazyGetter(gSync, "FxAccountsCommon", function() {
+ return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
+});
+
+XPCOMUtils.defineLazyModuleGetter(this, "EnsureFxAccountsWebChannel",
+ "resource://gre/modules/FxAccountsWebChannel.jsm");
+
+
+XPCOMUtils.defineLazyGetter(gSync, "weaveService", function() {
+ return Components.classes["@mozilla.org/weave/service;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+});
+
+if (AppConstants.MOZ_SERVICES_CLOUDSYNC) {
+ XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
+ "resource://gre/modules/CloudSync.jsm");
+}
+
+XPCOMUtils.defineLazyGetter(gSync, "log", function() {
+ return Log.repository.getLogger("browserwindow.sync");
+});
deleted file mode 100644
--- a/browser/base/content/browser-syncui.js
+++ /dev/null
@@ -1,395 +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");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://services-sync/UIState.jsm");
-
-if (AppConstants.MOZ_SERVICES_CLOUDSYNC) {
- XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
- "resource://gre/modules/CloudSync.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: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,
- _withinLastWeekFormat: null,
- _oneWeekOrOlderFormat: null,
-
- init() {
- // 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;
- }
-
- 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", () => {
- this._unloaded = true;
- Services.obs.removeObserver(this, "weave:service:ready");
- Services.obs.removeObserver(this, "quit-application");
-
- if (this.weaveService.ready) {
- this._obs.forEach(topic => {
- Services.obs.removeObserver(this, topic);
- });
- }
- }, { once: true });
- },
-
- 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();
- },
-
-
- // Returns a promise that resolves with true if Sync needs to be configured,
- // false otherwise.
- _needsSetup() {
- return fxAccounts.getSignedInUser().then(user => {
- // We want to treat "account needs verification" as "needs setup".
- return !(user && user.verified);
- });
- },
-
- // Returns a promise that resolves with true if the user currently signed in
- // to Sync needs to be verified, false otherwise.
- _needsVerification() {
- return fxAccounts.getSignedInUser().then(user => {
- // If there is no user, they can't be in a "needs verification" state.
- if (!user) {
- return false;
- }
- return !user.verified;
- });
- },
-
- // 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() {
- // 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;
- },
-
- updateStateBroadcasters(state) {
- const status = state.status;
-
- // 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 (CloudSync && CloudSync.ready && CloudSync().adapters.count) {
- document.getElementById("sync-syncnow-state").hidden = false;
- } else if (status == UIState.STATUS_LOGIN_FAILED) {
- // unhiding this element makes the menubar show the login failure state.
- document.getElementById("sync-reauth-state").hidden = false;
- } else if (status == UIState.STATUS_NOT_CONFIGURED ||
- status == UIState.STATUS_NOT_VERIFIED) {
- document.getElementById("sync-setup-state").hidden = false;
- } else {
- document.getElementById("sync-syncnow-state").hidden = false;
- }
- },
-
- updateSyncStatus(state) {
- const broadcaster = document.getElementById("sync-status");
- const syncingUI = broadcaster.getAttribute("syncstatus") == "active";
- if (state.syncing != syncingUI) { // Do we need to update the UI?
- state.syncing ? this.onActivityStart() : this.onActivityStop();
- }
- },
-
- // Functions called by observers
- onActivityStart() {
- 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");
- },
-
- _updateSyncStatus() {
- if (!gBrowser)
- return;
- let broadcaster = document.getElementById("sync-status");
- broadcaster.removeAttribute("syncstatus");
- broadcaster.removeAttribute("disabled");
- broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
- },
-
- onActivityStop() {
- 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();
- }
- },
-
- // 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");
- }).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.openPrefs();
- } else {
- this.doSync();
- }
- }).catch(err => {
- this.log.error("Failed to handle toolbar button command", err);
- });
- },
-
- /**
- * Open the Sync preferences.
- *
- * @param entryPoint
- * Indicates the entrypoint from where this method was called.
- */
- openPrefs(entryPoint = "syncbutton") {
- openPreferences("paneSync", { urlParams: { entrypoint: entryPoint } });
- },
-
- openSignInAgainPage(entryPoint = "syncbutton") {
- gFxAccounts.openSignInAgainPage(entryPoint);
- },
-
- openSyncedTabsPanel() {
- let placement = CustomizableUI.getPlacementOfWidget("sync-button");
- let area = placement ? placement.area : CustomizableUI.AREA_NAVBAR;
- let anchor = document.getElementById("sync-button") ||
- document.getElementById("PanelUI-menu-button");
- if (area == CustomizableUI.AREA_PANEL) {
- // The button is in the panel, so we need to show the panel UI, then our
- // subview.
- PanelUI.show().then(() => {
- PanelUI.showSubView("PanelUI-remotetabs", anchor, area);
- }).catch(Cu.reportError);
- } else {
- // It is placed somewhere else - just try and show it.
- PanelUI.showSubView("PanelUI-remotetabs", anchor, area);
- }
- },
-
- /* 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 = Services.prefs.getBoolPref(prefName, false);
- 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(state) {
- const status = state.status;
-
- // 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 (status == UIState.STATUS_NOT_VERIFIED) {
- // "needs verification"
- tooltiptext = gFxAccounts.strings.formatStringFromName("verifyDescription", [state.email], 1);
- } else if (status == UIState.STATUS_NOT_CONFIGURED) {
- // "needs setup".
- tooltiptext = this._stringBundle.GetStringFromName("signInToSync.description");
- } else if (status == UIState.STATUS_LOGIN_FAILED) {
- // "need to reconnect/re-enter your password"
- tooltiptext = gFxAccounts.strings.formatStringFromName("reconnectDescription", [state.email], 1);
- } else {
- // Sync appears configured - format the "last synced at" time.
- try {
- let lastSync = new Date(state.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.
- }
- }
-
- let broadcaster = document.getElementById("sync-status");
- if (broadcaster) {
- if (tooltiptext) {
- broadcaster.setAttribute("tooltiptext", tooltiptext);
- } else {
- broadcaster.removeAttribute("tooltiptext");
- }
- }
- },
-
- getWithinLastWeekFormat() {
- return this._withinLastWeekFormat ||
- (this._withinLastWeekFormat =
- new Intl.DateTimeFormat(undefined, {weekday: "long", hour: "numeric", minute: "numeric"}));
- },
-
- getOneWeekOrOlderFormat() {
- return this._oneWeekOrOlderFormat ||
- (this._oneWeekOrOlderFormat =
- new Intl.DateTimeFormat(undefined, {month: "long", day: "numeric"}));
- },
-
- formatLastSyncDate(date) {
- let sixDaysAgo = (() => {
- let tempDate = new Date();
- tempDate.setDate(tempDate.getDate() - 6);
- tempDate.setHours(0, 0, 0, 0);
- return tempDate;
- })();
-
- // It may be confusing for the user to see "Last Sync: Monday" when the last
- // sync was indeed a Monday, but 3 weeks ago.
- let dateFormat = date < sixDaysAgo ? this.getOneWeekOrOlderFormat() : this.getWithinLastWeekFormat();
-
- let lastSyncDateString = dateFormat.format(date);
- return this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
- },
-
- onClientsSynced() {
- 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");
- }
- }
- },
-
- 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;
- }
-
- // Now non-activity state (eg, enabled, errors, etc)
- // Note that sync uses the ":ui:" notifications for errors because sync.
- switch (topic) {
- 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 Services.strings.createBundle(
- "chrome://weave/locale/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;
-});
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1502,18 +1502,17 @@ var gBrowserInit = {
if (Win7Features)
Win7Features.onOpenWindow();
FullScreen.init();
PointerLock.init();
// initialize the sync UI
- gSyncUI.init();
- gFxAccounts.init();
+ gSync.init();
if (AppConstants.MOZ_DATA_REPORTING)
gDataNotificationInfoBar.init();
gBrowserThumbnails.init();
gMenuButtonUpdateBadge.init();
@@ -1648,17 +1647,17 @@ var gBrowserInit = {
CombinedStopReload.uninit();
gGestureSupport.init(false);
gHistorySwipeAnimation.uninit();
FullScreen.uninit();
- gFxAccounts.uninit();
+ gSync.uninit();
gExtensionsNotifications.uninit();
Services.obs.removeObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
try {
gBrowser.removeProgressListener(window.XULBrowserWindow);
gBrowser.removeTabsProgressListener(window.TabsProgressListener);
@@ -1810,19 +1809,16 @@ if (AppConstants.platform == "macosx") {
this._delayedStartupTimeoutId = null;
// initialise the offline listener
BrowserOffline.init();
// initialize the private browsing UI
gPrivateBrowsingUI.init();
- // initialize the sync UI
- gSyncUI.init();
-
if (AppConstants.E10S_TESTING_ONLY) {
gRemoteTabsUI.init();
}
};
gBrowserInit.nonBrowserWindowShutdown = function() {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
@@ -6741,17 +6737,17 @@ function checkEmptyPageOrigin(browser =
}
// ... so for those that don't have them, enforce that the page has the
// system principal (this matches e.g. on about:newtab).
let ssm = Services.scriptSecurityManager;
return ssm.isSystemPrincipal(contentPrincipal);
}
function BrowserOpenSyncTabs() {
- gSyncUI.openSyncedTabsPanel();
+ gSync.openSyncedTabsPanel();
}
function ReportFalseDeceptiveSite() {
let docURI = gBrowser.selectedBrowser.documentURI;
let isPhishingPage =
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
if (isPhishingPage) {
@@ -8083,17 +8079,17 @@ var TabContextMenu = {
}
this.contextTab.toggleMuteMenuItem = toggleMute;
this._updateToggleMuteMenuItem(this.contextTab);
this.contextTab.addEventListener("TabAttrModified", this);
aPopupMenu.addEventListener("popuphiding", this);
- gFxAccounts.updateTabContextMenu(aPopupMenu, this.contextTab);
+ gSync.updateTabContextMenu(aPopupMenu, this.contextTab);
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "popuphiding":
gBrowser.removeEventListener("TabAttrModified", this);
aEvent.target.removeEventListener("popuphiding", this);
break;
case "TabAttrModified":
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -102,17 +102,17 @@
tbattr="tabbrowser-remote"
hidden="true"
oncommand="gBrowser.openNonRemoteWindow(TabContextMenu.contextTab);"/>
#endif
<menuseparator id="context_sendTabToDevice_separator" hidden="true"/>
<menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
accesskey="&sendTabToDevice.accesskey;" hidden="true">
<menupopup id="context_sendTabToDevicePopupMenu"
- onpopupshowing="gFxAccounts.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle);"/>
+ onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle);"/>
</menu>
<menuseparator/>
<menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
tbattr="tabbrowser-multiple-visible"
oncommand="gBrowser.reloadAllTabs();"/>
<menuitem id="context_bookmarkAllTabs"
label="&bookmarkAllTabs.label;"
accesskey="&bookmarkAllTabs.accesskey;"
@@ -477,17 +477,17 @@
id="syncedTabsCopySelected"/>
<menuseparator/>
<menuitem label="&syncedTabs.context.openAllInTabs.label;"
accesskey="&syncedTabs.context.openAllInTabs.accesskey;"
id="syncedTabsOpenAllInTabs"/>
<menuitem label="&syncedTabs.context.managedevices.label;"
accesskey="&syncedTabs.context.managedevices.accesskey;"
id="syncedTabsManageDevices"
- oncommand="gFxAccounts.openDevicesManagementPage('syncedtabs-sidebar');"/>
+ oncommand="gSync.openDevicesManagementPage('syncedtabs-sidebar');"/>
<menuitem label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
id="syncedTabsRefresh"/>
</menupopup>
<menupopup id="SyncedTabsSidebarTabsFilterContext"
class="textbox-contextmenu">
<menuitem label="&undoCmd.label;"
accesskey="&undoCmd.accesskey;"
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -25,18 +25,17 @@
<script type="application/javascript" src="chrome://browser/content/browser-gestureSupport.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-media.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-plugins.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-refreshblocker.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-safebrowsing.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-sidebar.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-social.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"/>
#ifdef MOZ_DATA_REPORTING
<script type="application/javascript" src="chrome://browser/content/browser-data-submission-info-bar.js"/>
#endif
-<script type="application/javascript" src="chrome://browser/content/browser-fxaccounts.js"/>
+<script type="application/javascript" src="chrome://browser/content/browser-sync.js"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -596,17 +596,17 @@ nsContextMenu.prototype = {
return;
}
let popup = document.getElementById("fill-login-popup");
let insertBeforeElement = document.getElementById("fill-login-no-logins");
popup.insertBefore(fragment, insertBeforeElement);
},
initSyncItems() {
- gFxAccounts.initPageContextMenu(this);
+ gSync.initPageContextMenu(this);
},
openPasswordManager() {
LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
},
inspectNode() {
let gBrowser = this.browser.ownerGlobal.gBrowser;
--- a/browser/base/content/test/general/browser_contextmenu.js
+++ b/browser/base/content/test/general/browser_contextmenu.js
@@ -888,17 +888,17 @@ add_task(function* test_input_spell_fals
]
);
*/
});
const remoteClientsFixture = [ { id: 1, name: "Foo"}, { id: 2, name: "Bar"} ];
add_task(function* test_plaintext_sendpagetodevice() {
- if (!gFxAccounts.sendTabToDeviceEnabled) {
+ if (!gSync.sendTabToDeviceEnabled) {
return;
}
yield ensureSyncReady();
const oldGetter = setupRemoteClientsFixture(remoteClientsFixture);
let plainTextItemsWithSendPage =
["context-navigation", null,
["context-back", false,
@@ -926,17 +926,17 @@ add_task(function* test_plaintext_sendpa
yield openMenuItemSubmenu("context-sendpagetodevice");
}
});
restoreRemoteClients(oldGetter);
});
add_task(function* test_link_sendlinktodevice() {
- if (!gFxAccounts.sendTabToDeviceEnabled) {
+ if (!gSync.sendTabToDeviceEnabled) {
return;
}
yield ensureSyncReady();
const oldGetter = setupRemoteClientsFixture(remoteClientsFixture);
yield test_contextmenu("#test-link",
["context-openlinkintab", true,
...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
--- a/browser/base/content/test/general/browser_fxaccounts.js
+++ b/browser/base/content/test/general/browser_fxaccounts.js
@@ -4,45 +4,45 @@
var {Log} = Cu.import("resource://gre/modules/Log.jsm", {});
var {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
var {fxAccounts} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
var FxAccountsCommon = {};
Cu.import("resource://gre/modules/FxAccountsCommon.js", FxAccountsCommon);
const TEST_ROOT = "http://example.com/browser/browser/base/content/test/general/";
-// instrument gFxAccounts to send observer notifications when it's done
+// instrument gSync to send observer notifications when it's done
// what it does.
(function() {
let unstubs = {}; // The original functions we stub out.
// The stub functions.
let stubs = {
updateUI() {
- return unstubs["updateUI"].call(gFxAccounts).then(() => {
+ return unstubs["updateUI"].call(gSync).then(() => {
Services.obs.notifyObservers(null, "test:browser_fxaccounts:updateUI");
});
},
// Opening preferences is trickier than it should be as leaks are reported
// due to the promises it fires off at load time and there's no clear way to
// know when they are done.
// So just ensure openPreferences is called rather than whether it opens.
openPreferences() {
Services.obs.notifyObservers(null, "test:browser_fxaccounts:openPreferences");
}
};
for (let name in stubs) {
- unstubs[name] = gFxAccounts[name];
- gFxAccounts[name] = stubs[name];
+ unstubs[name] = gSync[name];
+ gSync[name] = stubs[name];
}
// and undo our damage at the end.
registerCleanupFunction(() => {
for (let name in unstubs) {
- gFxAccounts[name] = unstubs[name];
+ gSync[name] = unstubs[name];
}
stubs = unstubs = null;
});
})();
// Other setup/cleanup
var newTab;
@@ -111,17 +111,17 @@ add_task(function* test_unverifiedUser()
});
*/
add_task(function* test_verifiedUserEmptyProfile() {
// We see 2 updateUI() calls - one for the signedInUser and one after
// we first fetch the profile. We want them both to fire or we aren't testing
// the state we think we are testing.
let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 2);
- gFxAccounts._cachedProfile = null;
+ gSync._cachedProfile = null;
configureProfileURL({}); // successful but empty profile.
yield setSignedInUser(true); // this will fire the observer that does the update.
yield promiseUpdateDone;
// Check the world.
Assert.ok(isFooterVisible())
Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
@@ -131,41 +131,41 @@ add_task(function* test_verifiedUserEmpt
let promisePreferencesOpened = promiseObserver("test:browser_fxaccounts:openPreferences");
panelUIStatus.click();
yield promisePreferencesOpened;
yield signOut();
});
add_task(function* test_verifiedUserDisplayName() {
let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 2);
- gFxAccounts._cachedProfile = null;
+ gSync._cachedProfile = null;
configureProfileURL({ displayName: "Test User Display Name" });
yield setSignedInUser(true); // this will fire the observer that does the update.
yield promiseUpdateDone;
Assert.ok(isFooterVisible())
Assert.equal(panelUILabel.getAttribute("label"), "Test User Display Name");
Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
panelUIStatus.getAttribute("signedinTooltiptext"));
Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
yield signOut();
});
add_task(function* test_profileNotificationsClearsCache() {
let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 1);
- gFxAccounts._cachedProfile = { foo: "bar" };
+ gSync._cachedProfile = { foo: "bar" };
Services.obs.notifyObservers(null, this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION);
- Assert.ok(!gFxAccounts._cachedProfile);
+ Assert.ok(!gSync._cachedProfile);
yield promiseUpdateDone;
});
add_task(function* test_verifiedUserProfileFailure() {
// profile failure means only one observer fires.
let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 1);
- gFxAccounts._cachedProfile = null;
+ gSync._cachedProfile = null;
configureProfileURL(null, 500);
yield setSignedInUser(true); // this will fire the observer that does the update.
yield promiseUpdateDone;
Assert.ok(isFooterVisible());
Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
panelUIStatus.getAttribute("signedinTooltiptext"));
--- a/browser/base/content/test/general/browser_visibleTabs_contextMenu.js
+++ b/browser/base/content/test/general/browser_visibleTabs_contextMenu.js
@@ -12,35 +12,35 @@ add_task(function* test() {
is(gBrowser.visibleTabs.length, 2, "there are now two visible tabs");
// Check the context menu with two tabs
updateTabContextMenu(origTab);
is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled");
is(document.getElementById("context_reloadAllTabs").disabled, false, "Reload All Tabs is enabled");
- if (gFxAccounts.sendTabToDeviceEnabled) {
- const origIsSendableURI = gFxAccounts.isSendableURI;
- gFxAccounts.isSendableURI = () => true;
+ if (gSync.sendTabToDeviceEnabled) {
+ const origIsSendableURI = gSync.isSendableURI;
+ gSync.isSendableURI = () => true;
// Check the send tab to device menu item
yield ensureSyncReady();
const oldGetter = setupRemoteClientsFixture(remoteClientsFixture);
yield updateTabContextMenu(origTab, function* () {
yield openMenuItemSubmenu("context_sendTabToDevice");
});
is(document.getElementById("context_sendTabToDevice").hidden, false, "Send tab to device is shown");
let targets = document.getElementById("context_sendTabToDevicePopupMenu").childNodes;
is(targets[0].getAttribute("label"), "Foo", "Foo target is present");
is(targets[1].getAttribute("label"), "Bar", "Bar target is present");
is(targets[3].getAttribute("label"), "All Devices", "All Devices target is present");
- gFxAccounts.isSendableURI = () => false;
+ gSync.isSendableURI = () => false;
updateTabContextMenu(origTab);
is(document.getElementById("context_sendTabToDevice").hidden, true, "Send tab to device is hidden");
restoreRemoteClients(oldGetter);
- gFxAccounts.isSendableURI = origIsSendableURI;
+ gSync.isSendableURI = origIsSendableURI;
}
// Hide the original tab.
gBrowser.selectedTab = testTab;
gBrowser.showOnlyTheseTabs([testTab]);
is(gBrowser.visibleTabs.length, 1, "now there is only one visible tab");
// Check the context menu with one tab.
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -831,26 +831,26 @@ function getCertExceptionDialog(aLocatio
}
}
}
return undefined;
}
function setupRemoteClientsFixture(fixture) {
let oldRemoteClientsGetter =
- Object.getOwnPropertyDescriptor(gFxAccounts, "remoteClients").get;
+ Object.getOwnPropertyDescriptor(gSync, "remoteClients").get;
- Object.defineProperty(gFxAccounts, "remoteClients", {
+ Object.defineProperty(gSync, "remoteClients", {
get() { return fixture; }
});
return oldRemoteClientsGetter;
}
function restoreRemoteClients(getter) {
- Object.defineProperty(gFxAccounts, "remoteClients", {
+ Object.defineProperty(gSync, "remoteClients", {
get: getter
});
}
function* openMenuItemSubmenu(id) {
let menuPopup = document.getElementById(id).menupopup;
let menuPopupPromise = BrowserTestUtils.waitForEvent(menuPopup, "popupshown");
menuPopup.showPopup();
--- a/browser/base/content/web-panels.xul
+++ b/browser/base/content/web-panels.xul
@@ -19,17 +19,17 @@
<page id="webpanels-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="load()" onunload="unload()">
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-social.js"/>
- <script type="application/javascript" src="chrome://browser/content/browser-fxaccounts.js"/>
+ <script type="application/javascript" src="chrome://browser/content/browser-sync.js"/>
<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
<script type="application/javascript" src="chrome://browser/content/web-panels.js"/>
<stringbundleset id="stringbundleset">
<stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
</stringbundleset>
<broadcasterset id="mainBroadcasterSet">
--- a/browser/base/content/webext-panels.xul
+++ b/browser/base/content/webext-panels.xul
@@ -19,17 +19,17 @@
<page id="webextpanels-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="load()">
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-social.js"/>
- <script type="application/javascript" src="chrome://browser/content/browser-fxaccounts.js"/>
+ <script type="application/javascript" src="chrome://browser/content/browser-sync.js"/>
<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
<script type="application/javascript" src="chrome://browser/content/webext-panels.js"/>
<stringbundleset id="stringbundleset">
<stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
</stringbundleset>
<broadcasterset id="mainBroadcasterSet">
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -68,26 +68,25 @@ browser.jar:
content/browser/browser-captivePortal.js (content/browser-captivePortal.js)
content/browser/browser-ctrlTab.js (content/browser-ctrlTab.js)
content/browser/browser-customization.js (content/browser-customization.js)
content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
content/browser/browser-compacttheme.js (content/browser-compacttheme.js)
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)
content/browser/browser-plugins.js (content/browser-plugins.js)
content/browser/browser-refreshblocker.js (content/browser-refreshblocker.js)
content/browser/browser-safebrowsing.js (content/browser-safebrowsing.js)
content/browser/browser-sidebar.js (content/browser-sidebar.js)
content/browser/browser-social.js (content/browser-social.js)
- content/browser/browser-syncui.js (content/browser-syncui.js)
+ content/browser/browser-sync.js (content/browser-sync.js)
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
#ifdef CAN_DRAW_IN_TITLEBAR
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
#else
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar-stub.js)
#endif
content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -467,17 +467,17 @@ const CustomizableWidgets = [
},
_appendClient(client, attachFragment, maxTabs = this.TABS_PER_PAGE) {
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)));
+ window.gSync.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 {
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -32,25 +32,25 @@
<hbox id="PanelUI-footer-fxa">
<hbox id="PanelUI-fxa-status"
label="&fxaSignedIn.tooltip;"
defaultlabel="&fxaSignIn.label;"
signedinTooltiptext="&fxaSignedIn.tooltip;"
tooltiptext="&fxaSignedIn.tooltip;"
errorlabel="&fxaSignInError.label;"
unverifiedlabel="&fxaUnverified.label;"
- onclick="if (event.which == 1) gFxAccounts.onMenuPanelCommand();">
+ onclick="if (event.which == 1) gSync.onMenuPanelCommand();">
<image id="PanelUI-fxa-avatar"/>
<toolbarbutton id="PanelUI-fxa-label"
label="&fxaSignIn.label;"
fxabrandname="&syncBrand.fxAccount.label;"/>
</hbox>
<toolbarseparator/>
<toolbarbutton id="PanelUI-fxa-icon"
- oncommand="gSyncUI.doSync();"
+ oncommand="gSync.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;"
@@ -122,21 +122,21 @@
<vbox id="PanelUI-remotetabs-buttons">
<toolbarbutton id="PanelUI-remotetabs-view-sidebar"
class="subviewbutton"
observes="viewTabsSidebar"
label="&appMenuRemoteTabs.sidebar.label;"/>
<toolbarbutton id="PanelUI-remotetabs-view-managedevices"
class="subviewbutton"
label="&appMenuRemoteTabs.managedevices.label;"
- oncommand="gFxAccounts.openDevicesManagementPage('syncedtabs-menupanel');"/>
+ oncommand="gSync.openDevicesManagementPage('syncedtabs-menupanel');"/>
<toolbarbutton id="PanelUI-remotetabs-syncnow"
observes="sync-status"
class="subviewbutton"
- oncommand="gSyncUI.doSync();"
+ oncommand="gSync.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"
showAllLabel="&appMenuRemoteTabs.showAll.label;"
@@ -151,17 +151,17 @@
<vbox class="PanelUI-remotetabs-instruction-box">
<hbox pack="center">
<html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg"/>
</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.openPrefs('synced-tabs');"/>
+ oncommand="gSync.openPrefs('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 -->
@@ -185,31 +185,31 @@
flex="1"
align="center"
class="PanelUI-remotetabs-instruction-box"
observes="sync-setup-state">
<html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg"/>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
<toolbarbutton class="PanelUI-remotetabs-prefs-button"
label="&appMenuRemoteTabs.signin.label;"
- oncommand="gSyncUI.openPrefs('synced-tabs');"/>
+ oncommand="gSync.openPrefs('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">
<html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg"/>
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
<toolbarbutton class="PanelUI-remotetabs-prefs-button"
label="&appMenuRemoteTabs.signin.label;"
- oncommand="gSyncUI.openPrefs('synced-tabs');"/>
+ oncommand="gSync.openPrefs('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">
--- a/browser/components/syncedtabs/SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/SyncedTabsDeckComponent.js
@@ -117,17 +117,17 @@ SyncedTabsDeckComponent.prototype = {
// There's no good way to mock fxAccounts in browser tests where it's already
// been instantiated, so we have this method for stubbing.
_accountStatus() {
return this._fxAccounts.accountStatus();
},
getPanelStatus() {
return this._accountStatus().then(exists => {
- if (!exists || this._getChromeWindow(this._window).gSyncUI.loginFailed()) {
+ if (!exists || this._getChromeWindow(this._window).gSync.loginFailed()) {
return this.PANELS.NOT_AUTHED_INFO;
}
if (!this._SyncedTabs.isConfiguredToSyncTabs) {
return this.PANELS.TABS_DISABLED;
}
if (!this._SyncedTabs.hasSyncedThisSession) {
return this.PANELS.TABS_FETCHING;
}
@@ -161,12 +161,12 @@ SyncedTabsDeckComponent.prototype = {
this._openUrl(href, event);
},
_openUrl(url, event) {
this._window.openUILink(url, event);
},
openSyncPrefs() {
- this._getChromeWindow(this._window).gSyncUI.openPrefs("tabs-sidebar");
+ this._getChromeWindow(this._window).gSync.openPrefs("tabs-sidebar");
}
};
--- a/browser/components/syncedtabs/TabListView.js
+++ b/browser/components/syncedtabs/TabListView.js
@@ -208,17 +208,17 @@ TabListView.prototype = {
* Update the element representing an item, ensuring it's in sync with the
* underlying data.
* @param {client} item - Item to use as a source.
* @param {Element} itemNode - Element to update.
*/
_updateClient(item, itemNode) {
itemNode.setAttribute("id", "item-" + item.id);
let lastSync = new Date(item.lastModified);
- let lastSyncTitle = getChromeWindow(this._window).gSyncUI.formatLastSyncDate(lastSync);
+ let lastSyncTitle = getChromeWindow(this._window).gSync.formatLastSyncDate(lastSync);
itemNode.setAttribute("title", lastSyncTitle);
if (item.closed) {
itemNode.classList.add("closed");
} else {
itemNode.classList.remove("closed");
}
if (item.selected) {
itemNode.classList.add("selected");
--- a/browser/components/uitour/test/browser_fxa.js
+++ b/browser/components/uitour/test/browser_fxa.js
@@ -13,34 +13,34 @@ var gContentAPI;
var gContentWindow;
function test() {
UITourTest();
}
registerCleanupFunction(function*() {
yield signOut();
- gFxAccounts.updateUI();
+ gSync.updateUI();
});
var tests = [
taskify(function* test_highlight_accountStatus_loggedOut() {
let userData = yield fxAccounts.getSignedInUser();
is(userData, null, "Not logged in initially");
yield showMenuPromise("appMenu");
yield showHighlightPromise("accountStatus");
let highlight = document.getElementById("UITourHighlightContainer");
is(highlight.getAttribute("targetName"), "accountStatus", "Correct highlight target");
}),
taskify(function* test_highlight_accountStatus_loggedIn() {
yield setSignedInUser();
let userData = yield fxAccounts.getSignedInUser();
isnot(userData, null, "Logged in now");
- gFxAccounts.updateUI(); // Causes a leak (see bug 1332985)
+ gSync.updateUI(); // Causes a leak (see bug 1332985)
yield showMenuPromise("appMenu");
yield showHighlightPromise("accountStatus");
let highlight = document.getElementById("UITourHighlightContainer");
is(highlight.popupBoxObject.anchorNode.id, "PanelUI-fxa-avatar", "Anchored on avatar");
is(highlight.getAttribute("targetName"), "accountStatus", "Correct highlight target");
}),
];
--- a/services/sync/modules/UIState.jsm
+++ b/services/sync/modules/UIState.jsm
@@ -201,17 +201,21 @@ const UIStateInternal = {
} catch (e) {
// Not fetching the profile is sad but the FxA logs will already have noise.
return null;
}
},
_setLastSyncTime(state) {
if (state.status == UIState.STATUS_SIGNED_IN) {
- state.lastSync = Services.prefs.getCharPref("services.sync.lastSync");
+ try {
+ state.lastSync = Services.prefs.getCharPref("services.sync.lastSync");
+ } catch (e) {
+ // This is ok
+ }
}
},
_calculateStateChecksum(state) {
let desc = `${state.status}|${state.email}|${state.displayName}|
${state.avatarURL}|${state.lastSync}|${this._syncing}`;
let checksum = 0, i = 0, len = desc.length;
while (i < len) {