зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 22901b9f9199 (bug 1434706) for browser-chrome failures browser_contextmenu_sendtab.js. CLOSED TREE
This commit is contained in:
Родитель
c5b3bb6ce0
Коммит
c8a2d994c8
|
@ -1416,10 +1416,6 @@ pref("browser.uiCustomization.debug", false);
|
||||||
// CustomizableUI state of the browser's user interface
|
// CustomizableUI state of the browser's user interface
|
||||||
pref("browser.uiCustomization.state", "");
|
pref("browser.uiCustomization.state", "");
|
||||||
|
|
||||||
// If set to false, FxAccounts and Sync will be unavailable.
|
|
||||||
// A restart is mandatory after flipping that preference.
|
|
||||||
pref("identity.fxaccounts.enabled", true);
|
|
||||||
|
|
||||||
// The remote FxA root content URL. Must use HTTPS.
|
// The remote FxA root content URL. Must use HTTPS.
|
||||||
pref("identity.fxaccounts.remote.root", "https://accounts.firefox.com/");
|
pref("identity.fxaccounts.remote.root", "https://accounts.firefox.com/");
|
||||||
|
|
||||||
|
|
|
@ -263,13 +263,11 @@
|
||||||
label="&savePageCmd.label;"
|
label="&savePageCmd.label;"
|
||||||
accesskey="&savePageCmd.accesskey2;"
|
accesskey="&savePageCmd.accesskey2;"
|
||||||
oncommand="gContextMenu.savePageAs();"/>
|
oncommand="gContextMenu.savePageAs();"/>
|
||||||
<menuseparator id="context-sep-sendpagetodevice" class="sync-ui-item"
|
<menuseparator id="context-sep-sendpagetodevice" hidden="true"/>
|
||||||
hidden="true"/>
|
|
||||||
<menu id="context-sendpagetodevice"
|
<menu id="context-sendpagetodevice"
|
||||||
class="sync-ui-item"
|
label="&sendPageToDevice.label;"
|
||||||
label="&sendPageToDevice.label;"
|
accesskey="&sendPageToDevice.accesskey;"
|
||||||
accesskey="&sendPageToDevice.accesskey;"
|
hidden="true">
|
||||||
hidden="true">
|
|
||||||
<menupopup id="context-sendpagetodevice-popup"
|
<menupopup id="context-sendpagetodevice-popup"
|
||||||
onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gSync.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
|
onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gSync.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -312,13 +310,11 @@
|
||||||
oncommand="AddKeywordForSearchField();"/>
|
oncommand="AddKeywordForSearchField();"/>
|
||||||
<menuitem id="context-searchselect"
|
<menuitem id="context-searchselect"
|
||||||
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/>
|
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/>
|
||||||
<menuseparator id="context-sep-sendlinktodevice" class="sync-ui-item"
|
<menuseparator id="context-sep-sendlinktodevice" hidden="true"/>
|
||||||
hidden="true"/>
|
|
||||||
<menu id="context-sendlinktodevice"
|
<menu id="context-sendlinktodevice"
|
||||||
class="sync-ui-item"
|
label="&sendLinkToDevice.label;"
|
||||||
label="&sendLinkToDevice.label;"
|
accesskey="&sendLinkToDevice.accesskey;"
|
||||||
accesskey="&sendLinkToDevice.accesskey;"
|
hidden="true">
|
||||||
hidden="true">
|
|
||||||
<menupopup id="context-sendlinktodevice-popup"
|
<menupopup id="context-sendlinktodevice-popup"
|
||||||
onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
|
onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -486,25 +486,21 @@
|
||||||
|
|
||||||
<!-- only one of sync-setup, sync-unverifieditem, sync-syncnowitem or sync-reauthitem will be showing at once -->
|
<!-- only one of sync-setup, sync-unverifieditem, sync-syncnowitem or sync-reauthitem will be showing at once -->
|
||||||
<menuitem id="sync-setup"
|
<menuitem id="sync-setup"
|
||||||
class="sync-ui-item"
|
|
||||||
label="&syncSignIn.label;"
|
label="&syncSignIn.label;"
|
||||||
accesskey="&syncSignIn.accesskey;"
|
accesskey="&syncSignIn.accesskey;"
|
||||||
observes="sync-setup-state"
|
observes="sync-setup-state"
|
||||||
oncommand="gSync.openPrefs('menubar')"/>
|
oncommand="gSync.openPrefs('menubar')"/>
|
||||||
<menuitem id="sync-unverifieditem"
|
<menuitem id="sync-unverifieditem"
|
||||||
class="sync-ui-item"
|
|
||||||
label="&syncSignIn.label;"
|
label="&syncSignIn.label;"
|
||||||
accesskey="&syncSignIn.accesskey;"
|
accesskey="&syncSignIn.accesskey;"
|
||||||
observes="sync-unverified-state"
|
observes="sync-unverified-state"
|
||||||
oncommand="gSync.openPrefs('menubar')"/>
|
oncommand="gSync.openPrefs('menubar')"/>
|
||||||
<menuitem id="sync-syncnowitem"
|
<menuitem id="sync-syncnowitem"
|
||||||
class="sync-ui-item"
|
|
||||||
label="&syncSyncNowItem.label;"
|
label="&syncSyncNowItem.label;"
|
||||||
accesskey="&syncSyncNowItem.accesskey;"
|
accesskey="&syncSyncNowItem.accesskey;"
|
||||||
observes="sync-syncnow-state"
|
observes="sync-syncnow-state"
|
||||||
oncommand="gSync.doSync(event);"/>
|
oncommand="gSync.doSync(event);"/>
|
||||||
<menuitem id="sync-reauthitem"
|
<menuitem id="sync-reauthitem"
|
||||||
class="sync-ui-item"
|
|
||||||
label="&syncReAuthItem.label;"
|
label="&syncReAuthItem.label;"
|
||||||
accesskey="&syncReAuthItem.accesskey;"
|
accesskey="&syncReAuthItem.accesskey;"
|
||||||
observes="sync-reauth-state"
|
observes="sync-reauth-state"
|
||||||
|
|
|
@ -95,8 +95,6 @@ var gSync = {
|
||||||
});
|
});
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "PRODUCT_INFO_BASE_URL",
|
XPCOMUtils.defineLazyPreferenceGetter(this, "PRODUCT_INFO_BASE_URL",
|
||||||
"app.productInfo.baseURL");
|
"app.productInfo.baseURL");
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "SYNC_ENABLED",
|
|
||||||
"identity.fxaccounts.enabled");
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_maybeUpdateUIState() {
|
_maybeUpdateUIState() {
|
||||||
|
@ -116,13 +114,6 @@ var gSync = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._definePrefGetters();
|
|
||||||
|
|
||||||
if (!this.SYNC_ENABLED) {
|
|
||||||
this.onSyncDisabled();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initial label for the sync buttons.
|
// initial label for the sync buttons.
|
||||||
let statusBroadcaster = document.getElementById("sync-status");
|
let statusBroadcaster = document.getElementById("sync-status");
|
||||||
if (!statusBroadcaster) {
|
if (!statusBroadcaster) {
|
||||||
|
@ -141,6 +132,7 @@ var gSync = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._generateNodeGetters();
|
this._generateNodeGetters();
|
||||||
|
this._definePrefGetters();
|
||||||
|
|
||||||
this._maybeUpdateUIState();
|
this._maybeUpdateUIState();
|
||||||
|
|
||||||
|
@ -478,10 +470,6 @@ var gSync = {
|
||||||
|
|
||||||
// "Send Tab to Device" menu item
|
// "Send Tab to Device" menu item
|
||||||
updateTabContextMenu(aPopupMenu, aTargetTab) {
|
updateTabContextMenu(aPopupMenu, aTargetTab) {
|
||||||
if (!this.SYNC_ENABLED) {
|
|
||||||
// These items are hidden in onSyncDisabled(). No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const enabled = !this.syncConfiguredAndLoading &&
|
const enabled = !this.syncConfiguredAndLoading &&
|
||||||
this.isSendableURI(aTargetTab.linkedBrowser.currentURI.spec);
|
this.isSendableURI(aTargetTab.linkedBrowser.currentURI.spec);
|
||||||
|
|
||||||
|
@ -490,10 +478,6 @@ var gSync = {
|
||||||
|
|
||||||
// "Send Page to Device" and "Send Link to Device" menu items
|
// "Send Page to Device" and "Send Link to Device" menu items
|
||||||
updateContentContextMenu(contextMenu) {
|
updateContentContextMenu(contextMenu) {
|
||||||
if (!this.SYNC_ENABLED) {
|
|
||||||
// These items are hidden by default. No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// showSendLink and showSendPage are mutually exclusive
|
// showSendLink and showSendPage are mutually exclusive
|
||||||
const showSendLink = contextMenu.onSaveableLink || contextMenu.onPlainTextLink;
|
const showSendLink = contextMenu.onSaveableLink || contextMenu.onPlainTextLink;
|
||||||
const showSendPage = !showSendLink
|
const showSendPage = !showSendLink
|
||||||
|
@ -667,13 +651,6 @@ var gSync = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSyncDisabled() {
|
|
||||||
const toHide = [...document.querySelectorAll(".sync-ui-item")];
|
|
||||||
for (const item of toHide) {
|
|
||||||
item.hidden = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([
|
QueryInterface: XPCOMUtils.generateQI([
|
||||||
Ci.nsIObserver,
|
Ci.nsIObserver,
|
||||||
Ci.nsISupportsWeakReference
|
Ci.nsISupportsWeakReference
|
||||||
|
|
|
@ -97,9 +97,8 @@
|
||||||
accesskey="&moveToNewWindow.accesskey;"
|
accesskey="&moveToNewWindow.accesskey;"
|
||||||
tbattr="tabbrowser-multiple"
|
tbattr="tabbrowser-multiple"
|
||||||
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
|
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
|
||||||
<menuseparator id="context_sendTabToDevice_separator" class="sync-ui-item"/>
|
<menuseparator id="context_sendTabToDevice_separator"/>
|
||||||
<menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
|
<menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
|
||||||
class="sync-ui-item"
|
|
||||||
accesskey="&sendTabToDevice.accesskey;">
|
accesskey="&sendTabToDevice.accesskey;">
|
||||||
<menupopup id="context_sendTabToDevicePopupMenu"
|
<menupopup id="context_sendTabToDevicePopupMenu"
|
||||||
onpopupshowing="gSync.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);"/>
|
||||||
|
|
|
@ -7,8 +7,6 @@ const remoteClientsFixture = [ { id: 1, name: "Foo"}, { id: 2, name: "Bar"} ];
|
||||||
|
|
||||||
add_task(async function setup() {
|
add_task(async function setup() {
|
||||||
await promiseSyncReady();
|
await promiseSyncReady();
|
||||||
// gSync.init() is called in a requestIdleCallback. Force its initialization.
|
|
||||||
gSync.init();
|
|
||||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
|
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -30,7 +28,7 @@ add_task(async function test_page_contextmenu() {
|
||||||
sandbox.restore();
|
sandbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_page_contextmenu_no_remote_clients() {
|
add_task(async function test_page_contextmenu_sendtab_no_remote_clients() {
|
||||||
const sandbox = setupSendTabMocks({ syncReady: true, clientsSynced: true, remoteClients: [],
|
const sandbox = setupSendTabMocks({ syncReady: true, clientsSynced: true, remoteClients: [],
|
||||||
state: UIState.STATUS_SIGNED_IN, isSendableURI: true });
|
state: UIState.STATUS_SIGNED_IN, isSendableURI: true });
|
||||||
|
|
||||||
|
@ -48,7 +46,7 @@ add_task(async function test_page_contextmenu_no_remote_clients() {
|
||||||
sandbox.restore();
|
sandbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_page_contextmenu_one_remote_client() {
|
add_task(async function test_page_contextmenu_sendtab_one_remote_client() {
|
||||||
const sandbox = setupSendTabMocks({ syncReady: true, clientsSynced: true, remoteClients: [{ id: 1, name: "Foo"}],
|
const sandbox = setupSendTabMocks({ syncReady: true, clientsSynced: true, remoteClients: [{ id: 1, name: "Foo"}],
|
||||||
state: UIState.STATUS_SIGNED_IN, isSendableURI: true });
|
state: UIState.STATUS_SIGNED_IN, isSendableURI: true });
|
||||||
|
|
||||||
|
@ -177,16 +175,6 @@ add_task(async function test_page_contextmenu_login_failed() {
|
||||||
isSendableURI.restore();
|
isSendableURI.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_page_contextmenu_fxa_disabled() {
|
|
||||||
const getter = sinon.stub(gSync, "SYNC_ENABLED").get(() => false);
|
|
||||||
gSync.onSyncDisabled(); // Would have been called on gSync initialization if SYNC_ENABLED had been set.
|
|
||||||
await openContentContextMenu("#moztext");
|
|
||||||
is(document.getElementById("context-sendpagetodevice").hidden, true, "Send tab to device is hidden");
|
|
||||||
is(document.getElementById("context-sep-sendpagetodevice").hidden, true, "Separator is also hidden");
|
|
||||||
await hideContentContextMenu();
|
|
||||||
getter.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
// We are not going to bother testing the visibility of context-sendlinktodevice
|
// We are not going to bother testing the visibility of context-sendlinktodevice
|
||||||
// since it uses the exact same code.
|
// since it uses the exact same code.
|
||||||
// However, browser_contextmenu.js contains tests that verify its presence.
|
// However, browser_contextmenu.js contains tests that verify its presence.
|
||||||
|
|
|
@ -95,15 +95,3 @@ add_task(async function test_tab_contextmenu_sync_not_ready_other_state() {
|
||||||
|
|
||||||
sandbox.restore();
|
sandbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_tab_contextmenu_fxa_disabled() {
|
|
||||||
const getter = sinon.stub(gSync, "SYNC_ENABLED").get(() => false);
|
|
||||||
// Simulate onSyncDisabled() being called on window open.
|
|
||||||
gSync.onSyncDisabled();
|
|
||||||
|
|
||||||
updateTabContextMenu(testTab);
|
|
||||||
is(document.getElementById("context_sendTabToDevice").hidden, true, "Send tab to device is hidden");
|
|
||||||
is(document.getElementById("context_sendTabToDevice_separator").hidden, true, "Separator is also hidden");
|
|
||||||
|
|
||||||
getter.restore();
|
|
||||||
});
|
|
||||||
|
|
|
@ -238,6 +238,252 @@ const CustomizableWidgets = [
|
||||||
panelview.appendChild(body);
|
panelview.appendChild(body);
|
||||||
panelview.appendChild(footer);
|
panelview.appendChild(footer);
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
id: "sync-button",
|
||||||
|
label: "remotetabs-panelmenu.label",
|
||||||
|
tooltiptext: "remotetabs-panelmenu.tooltiptext2",
|
||||||
|
type: "view",
|
||||||
|
viewId: "PanelUI-remotetabs",
|
||||||
|
deckIndices: {
|
||||||
|
DECKINDEX_TABS: 0,
|
||||||
|
DECKINDEX_TABSDISABLED: 1,
|
||||||
|
DECKINDEX_FETCHING: 2,
|
||||||
|
DECKINDEX_NOCLIENTS: 3,
|
||||||
|
},
|
||||||
|
TABS_PER_PAGE: 25,
|
||||||
|
NEXT_PAGE_MIN_TABS: 5, // Minimum number of tabs displayed when we click "Show All"
|
||||||
|
onCreated(aNode) {
|
||||||
|
this._initialize(aNode);
|
||||||
|
},
|
||||||
|
_initialize(aNode) {
|
||||||
|
if (this._initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
this._initialized = true;
|
||||||
|
},
|
||||||
|
onViewShowing(aEvent) {
|
||||||
|
this._initialize(aEvent.target);
|
||||||
|
let doc = aEvent.target.ownerDocument;
|
||||||
|
this._tabsList = doc.getElementById("PanelUI-remotetabs-tabslist");
|
||||||
|
Services.obs.addObserver(this, SyncedTabs.TOPIC_TABS_CHANGED);
|
||||||
|
|
||||||
|
if (SyncedTabs.isConfiguredToSyncTabs) {
|
||||||
|
if (SyncedTabs.hasSyncedThisSession) {
|
||||||
|
this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
|
||||||
|
} else {
|
||||||
|
// Sync hasn't synced tabs yet, so show the "fetching" panel.
|
||||||
|
this.setDeckIndex(this.deckIndices.DECKINDEX_FETCHING);
|
||||||
|
}
|
||||||
|
// force a background sync.
|
||||||
|
SyncedTabs.syncTabs().catch(ex => {
|
||||||
|
Cu.reportError(ex);
|
||||||
|
});
|
||||||
|
// show the current list - it will be updated by our observer.
|
||||||
|
this._showTabs();
|
||||||
|
} else {
|
||||||
|
// not configured to sync tabs, so no point updating the list.
|
||||||
|
this.setDeckIndex(this.deckIndices.DECKINDEX_TABSDISABLED);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onViewHiding() {
|
||||||
|
Services.obs.removeObserver(this, SyncedTabs.TOPIC_TABS_CHANGED);
|
||||||
|
this._tabsList = null;
|
||||||
|
},
|
||||||
|
_tabsList: null,
|
||||||
|
observe(subject, topic, data) {
|
||||||
|
switch (topic) {
|
||||||
|
case SyncedTabs.TOPIC_TABS_CHANGED:
|
||||||
|
this._showTabs();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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(paginationInfo) {
|
||||||
|
this._showTabsPromise = this._showTabsPromise.then(() => {
|
||||||
|
return this.__showTabs(paginationInfo);
|
||||||
|
}, e => {
|
||||||
|
Cu.reportError(e);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Return a new promise to update the tab list.
|
||||||
|
__showTabs(paginationInfo) {
|
||||||
|
if (!this._tabsList) {
|
||||||
|
// Closed between the previous `this._showTabsPromise`
|
||||||
|
// resolving and now.
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (paginationInfo && paginationInfo.clientId == client.id) {
|
||||||
|
this._appendClient(client, fragment, paginationInfo.maxTabs);
|
||||||
|
} else {
|
||||||
|
this._appendClient(client, fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._tabsList.appendChild(fragment);
|
||||||
|
PanelView.forNode(this._tabsList.closest("panelview"))
|
||||||
|
.descriptionHeightWorkaround();
|
||||||
|
}).catch(err => {
|
||||||
|
Cu.reportError(err);
|
||||||
|
}).then(() => {
|
||||||
|
// an observer for tests.
|
||||||
|
Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_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(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.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 {
|
||||||
|
// If this page will display all tabs, show no additional buttons.
|
||||||
|
// If the next page will display all the remaining tabs, show a "Show All" button
|
||||||
|
// Otherwise, show a "Shore More" button
|
||||||
|
let hasNextPage = client.tabs.length > maxTabs;
|
||||||
|
let nextPageIsLastPage = hasNextPage && maxTabs + this.TABS_PER_PAGE >= client.tabs.length;
|
||||||
|
if (nextPageIsLastPage) {
|
||||||
|
// When the user clicks "Show All", try to have at least NEXT_PAGE_MIN_TABS more tabs
|
||||||
|
// to display in order to avoid user frustration
|
||||||
|
maxTabs = Math.min(client.tabs.length - this.NEXT_PAGE_MIN_TABS, maxTabs);
|
||||||
|
}
|
||||||
|
if (hasNextPage) {
|
||||||
|
client.tabs = client.tabs.slice(0, maxTabs);
|
||||||
|
}
|
||||||
|
for (let tab of client.tabs) {
|
||||||
|
let tabEnt = this._createTabElement(doc, tab);
|
||||||
|
attachFragment.appendChild(tabEnt);
|
||||||
|
}
|
||||||
|
if (hasNextPage) {
|
||||||
|
let showAllEnt = this._createShowMoreElement(doc, client.id,
|
||||||
|
nextPageIsLastPage ?
|
||||||
|
Infinity :
|
||||||
|
maxTabs + this.TABS_PER_PAGE);
|
||||||
|
attachFragment.appendChild(showAllEnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_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);
|
||||||
|
if (doc.defaultView.whereToOpenLink(e) != "current") {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
} else {
|
||||||
|
CustomizableUI.hidePanelForNode(item);
|
||||||
|
}
|
||||||
|
BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
|
||||||
|
});
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
_createShowMoreElement(doc, clientId, showCount) {
|
||||||
|
let labelAttr, tooltipAttr;
|
||||||
|
if (showCount === Infinity) {
|
||||||
|
labelAttr = "showAllLabel";
|
||||||
|
tooltipAttr = "showAllTooltipText";
|
||||||
|
} else {
|
||||||
|
labelAttr = "showMoreLabel";
|
||||||
|
tooltipAttr = "showMoreTooltipText";
|
||||||
|
}
|
||||||
|
let showAllItem = doc.createElementNS(kNSXUL, "toolbarbutton");
|
||||||
|
showAllItem.setAttribute("itemtype", "showmorebutton");
|
||||||
|
showAllItem.setAttribute("class", "subviewbutton");
|
||||||
|
let label = this._tabsList.getAttribute(labelAttr);
|
||||||
|
showAllItem.setAttribute("label", label);
|
||||||
|
let tooltipText = this._tabsList.getAttribute(tooltipAttr);
|
||||||
|
showAllItem.setAttribute("tooltiptext", tooltipText);
|
||||||
|
showAllItem.addEventListener("click", e => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this._showTabs({ clientId, maxTabs: showCount });
|
||||||
|
});
|
||||||
|
return showAllItem;
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
id: "privatebrowsing-button",
|
id: "privatebrowsing-button",
|
||||||
shortcutId: "key_privatebrowsing",
|
shortcutId: "key_privatebrowsing",
|
||||||
|
@ -628,256 +874,6 @@ const CustomizableWidgets = [
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
|
||||||
CustomizableWidgets.push({
|
|
||||||
id: "sync-button",
|
|
||||||
label: "remotetabs-panelmenu.label",
|
|
||||||
tooltiptext: "remotetabs-panelmenu.tooltiptext2",
|
|
||||||
type: "view",
|
|
||||||
viewId: "PanelUI-remotetabs",
|
|
||||||
deckIndices: {
|
|
||||||
DECKINDEX_TABS: 0,
|
|
||||||
DECKINDEX_TABSDISABLED: 1,
|
|
||||||
DECKINDEX_FETCHING: 2,
|
|
||||||
DECKINDEX_NOCLIENTS: 3,
|
|
||||||
},
|
|
||||||
TABS_PER_PAGE: 25,
|
|
||||||
NEXT_PAGE_MIN_TABS: 5, // Minimum number of tabs displayed when we click "Show All"
|
|
||||||
onCreated(aNode) {
|
|
||||||
this._initialize(aNode);
|
|
||||||
},
|
|
||||||
_initialize(aNode) {
|
|
||||||
if (this._initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 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);
|
|
||||||
this._initialized = true;
|
|
||||||
},
|
|
||||||
onViewShowing(aEvent) {
|
|
||||||
this._initialize(aEvent.target);
|
|
||||||
let doc = aEvent.target.ownerDocument;
|
|
||||||
this._tabsList = doc.getElementById("PanelUI-remotetabs-tabslist");
|
|
||||||
Services.obs.addObserver(this, SyncedTabs.TOPIC_TABS_CHANGED);
|
|
||||||
|
|
||||||
if (SyncedTabs.isConfiguredToSyncTabs) {
|
|
||||||
if (SyncedTabs.hasSyncedThisSession) {
|
|
||||||
this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
|
|
||||||
} else {
|
|
||||||
// Sync hasn't synced tabs yet, so show the "fetching" panel.
|
|
||||||
this.setDeckIndex(this.deckIndices.DECKINDEX_FETCHING);
|
|
||||||
}
|
|
||||||
// force a background sync.
|
|
||||||
SyncedTabs.syncTabs().catch(ex => {
|
|
||||||
Cu.reportError(ex);
|
|
||||||
});
|
|
||||||
// show the current list - it will be updated by our observer.
|
|
||||||
this._showTabs();
|
|
||||||
} else {
|
|
||||||
// not configured to sync tabs, so no point updating the list.
|
|
||||||
this.setDeckIndex(this.deckIndices.DECKINDEX_TABSDISABLED);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onViewHiding() {
|
|
||||||
Services.obs.removeObserver(this, SyncedTabs.TOPIC_TABS_CHANGED);
|
|
||||||
this._tabsList = null;
|
|
||||||
},
|
|
||||||
_tabsList: null,
|
|
||||||
observe(subject, topic, data) {
|
|
||||||
switch (topic) {
|
|
||||||
case SyncedTabs.TOPIC_TABS_CHANGED:
|
|
||||||
this._showTabs();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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(paginationInfo) {
|
|
||||||
this._showTabsPromise = this._showTabsPromise.then(() => {
|
|
||||||
return this.__showTabs(paginationInfo);
|
|
||||||
}, e => {
|
|
||||||
Cu.reportError(e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Return a new promise to update the tab list.
|
|
||||||
__showTabs(paginationInfo) {
|
|
||||||
if (!this._tabsList) {
|
|
||||||
// Closed between the previous `this._showTabsPromise`
|
|
||||||
// resolving and now.
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (paginationInfo && paginationInfo.clientId == client.id) {
|
|
||||||
this._appendClient(client, fragment, paginationInfo.maxTabs);
|
|
||||||
} else {
|
|
||||||
this._appendClient(client, fragment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._tabsList.appendChild(fragment);
|
|
||||||
PanelView.forNode(this._tabsList.closest("panelview"))
|
|
||||||
.descriptionHeightWorkaround();
|
|
||||||
}).catch(err => {
|
|
||||||
Cu.reportError(err);
|
|
||||||
}).then(() => {
|
|
||||||
// an observer for tests.
|
|
||||||
Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_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(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.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 {
|
|
||||||
// If this page will display all tabs, show no additional buttons.
|
|
||||||
// If the next page will display all the remaining tabs, show a "Show All" button
|
|
||||||
// Otherwise, show a "Shore More" button
|
|
||||||
let hasNextPage = client.tabs.length > maxTabs;
|
|
||||||
let nextPageIsLastPage = hasNextPage && maxTabs + this.TABS_PER_PAGE >= client.tabs.length;
|
|
||||||
if (nextPageIsLastPage) {
|
|
||||||
// When the user clicks "Show All", try to have at least NEXT_PAGE_MIN_TABS more tabs
|
|
||||||
// to display in order to avoid user frustration
|
|
||||||
maxTabs = Math.min(client.tabs.length - this.NEXT_PAGE_MIN_TABS, maxTabs);
|
|
||||||
}
|
|
||||||
if (hasNextPage) {
|
|
||||||
client.tabs = client.tabs.slice(0, maxTabs);
|
|
||||||
}
|
|
||||||
for (let tab of client.tabs) {
|
|
||||||
let tabEnt = this._createTabElement(doc, tab);
|
|
||||||
attachFragment.appendChild(tabEnt);
|
|
||||||
}
|
|
||||||
if (hasNextPage) {
|
|
||||||
let showAllEnt = this._createShowMoreElement(doc, client.id,
|
|
||||||
nextPageIsLastPage ?
|
|
||||||
Infinity :
|
|
||||||
maxTabs + this.TABS_PER_PAGE);
|
|
||||||
attachFragment.appendChild(showAllEnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_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);
|
|
||||||
if (doc.defaultView.whereToOpenLink(e) != "current") {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
} else {
|
|
||||||
CustomizableUI.hidePanelForNode(item);
|
|
||||||
}
|
|
||||||
BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
|
|
||||||
});
|
|
||||||
return item;
|
|
||||||
},
|
|
||||||
_createShowMoreElement(doc, clientId, showCount) {
|
|
||||||
let labelAttr, tooltipAttr;
|
|
||||||
if (showCount === Infinity) {
|
|
||||||
labelAttr = "showAllLabel";
|
|
||||||
tooltipAttr = "showAllTooltipText";
|
|
||||||
} else {
|
|
||||||
labelAttr = "showMoreLabel";
|
|
||||||
tooltipAttr = "showMoreTooltipText";
|
|
||||||
}
|
|
||||||
let showAllItem = doc.createElementNS(kNSXUL, "toolbarbutton");
|
|
||||||
showAllItem.setAttribute("itemtype", "showmorebutton");
|
|
||||||
showAllItem.setAttribute("class", "subviewbutton");
|
|
||||||
let label = this._tabsList.getAttribute(labelAttr);
|
|
||||||
showAllItem.setAttribute("label", label);
|
|
||||||
let tooltipText = this._tabsList.getAttribute(tooltipAttr);
|
|
||||||
showAllItem.setAttribute("tooltiptext", tooltipText);
|
|
||||||
showAllItem.addEventListener("click", e => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
this._showTabs({ clientId, maxTabs: showCount });
|
|
||||||
});
|
|
||||||
return showAllItem;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let preferencesButton = {
|
let preferencesButton = {
|
||||||
id: "preferences-button",
|
id: "preferences-button",
|
||||||
onCommand(aEvent) {
|
onCommand(aEvent) {
|
||||||
|
|
|
@ -177,7 +177,7 @@
|
||||||
oncommand="PanelUI._onBannerItemSelected(event)"
|
oncommand="PanelUI._onBannerItemSelected(event)"
|
||||||
wrap="true"
|
wrap="true"
|
||||||
hidden="true"/>
|
hidden="true"/>
|
||||||
<toolbaritem id="appMenu-fxa-container" class="toolbaritem-combined-buttons sync-ui-item">
|
<toolbaritem id="appMenu-fxa-container" class="toolbaritem-combined-buttons">
|
||||||
<hbox id="appMenu-fxa-status"
|
<hbox id="appMenu-fxa-status"
|
||||||
flex="1"
|
flex="1"
|
||||||
defaultlabel="&fxaSignIn.label;"
|
defaultlabel="&fxaSignIn.label;"
|
||||||
|
@ -201,7 +201,7 @@
|
||||||
<observes element="sync-status" attribute="tooltiptext"/>
|
<observes element="sync-status" attribute="tooltiptext"/>
|
||||||
</toolbarbutton>
|
</toolbarbutton>
|
||||||
</toolbaritem>
|
</toolbaritem>
|
||||||
<toolbarseparator class="sync-ui-item"/>
|
<toolbarseparator/>
|
||||||
<toolbarbutton id="appMenu-new-window-button"
|
<toolbarbutton id="appMenu-new-window-button"
|
||||||
class="subviewbutton subviewbutton-iconic"
|
class="subviewbutton subviewbutton-iconic"
|
||||||
label="&newNavigatorCmd.label;"
|
label="&newNavigatorCmd.label;"
|
||||||
|
@ -637,7 +637,7 @@
|
||||||
closemenu="none"
|
closemenu="none"
|
||||||
oncommand="DownloadsSubview.show(this);"/>
|
oncommand="DownloadsSubview.show(this);"/>
|
||||||
<toolbarbutton id="appMenu-library-remotetabs-button"
|
<toolbarbutton id="appMenu-library-remotetabs-button"
|
||||||
class="subviewbutton subviewbutton-iconic subviewbutton-nav sync-ui-item"
|
class="subviewbutton subviewbutton-iconic subviewbutton-nav"
|
||||||
label="&appMenuRemoteTabs.label;"
|
label="&appMenuRemoteTabs.label;"
|
||||||
closemenu="none"
|
closemenu="none"
|
||||||
oncommand="PanelUI.showSubView('PanelUI-remotetabs', this)"/>
|
oncommand="PanelUI.showSubView('PanelUI-remotetabs', this)"/>
|
||||||
|
|
|
@ -467,11 +467,6 @@ var gMainPane = {
|
||||||
OS.File.stat(ignoreSeparateProfile).then(() => separateProfileModeCheckbox.checked = false,
|
OS.File.stat(ignoreSeparateProfile).then(() => separateProfileModeCheckbox.checked = false,
|
||||||
() => separateProfileModeCheckbox.checked = true);
|
() => separateProfileModeCheckbox.checked = true);
|
||||||
|
|
||||||
if (!Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
|
||||||
document.getElementById("sync-dev-edition-root").hidden = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fxAccounts.getSignedInUser().then(data => {
|
fxAccounts.getSignedInUser().then(data => {
|
||||||
document.getElementById("getStarted").selectedIndex = data ? 1 : 0;
|
document.getElementById("getStarted").selectedIndex = data ? 1 : 0;
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<vbox id="separateProfileBox">
|
<vbox id="separateProfileBox">
|
||||||
<checkbox id="separateProfileMode"
|
<checkbox id="separateProfileMode"
|
||||||
label="&separateProfileMode.label;"/>
|
label="&separateProfileMode.label;"/>
|
||||||
<hbox id="sync-dev-edition-root" align="center" class="indent">
|
<hbox align="center" class="indent">
|
||||||
<label id="useFirefoxSync">&useFirefoxSync.label;</label>
|
<label id="useFirefoxSync">&useFirefoxSync.label;</label>
|
||||||
<deck id="getStarted">
|
<deck id="getStarted">
|
||||||
<label class="text-link">&getStarted.notloggedin.label;</label>
|
<label class="text-link">&getStarted.notloggedin.label;</label>
|
||||||
|
|
|
@ -55,10 +55,7 @@ function init_all() {
|
||||||
register_module("paneSearch", gSearchPane);
|
register_module("paneSearch", gSearchPane);
|
||||||
register_module("panePrivacy", gPrivacyPane);
|
register_module("panePrivacy", gPrivacyPane);
|
||||||
register_module("paneContainers", gContainersPane);
|
register_module("paneContainers", gContainersPane);
|
||||||
if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
register_module("paneSync", gSyncPane);
|
||||||
document.getElementById("category-sync").hidden = false;
|
|
||||||
register_module("paneSync", gSyncPane);
|
|
||||||
}
|
|
||||||
register_module("paneSearchResults", gSearchResultsPane);
|
register_module("paneSearchResults", gSearchResultsPane);
|
||||||
gSearchResultsPane.init();
|
gSearchResultsPane.init();
|
||||||
gMainPane.preInit();
|
gMainPane.preInit();
|
||||||
|
|
|
@ -172,7 +172,6 @@
|
||||||
|
|
||||||
<richlistitem id="category-sync"
|
<richlistitem id="category-sync"
|
||||||
class="category"
|
class="category"
|
||||||
hidden="true"
|
|
||||||
value="paneSync"
|
value="paneSync"
|
||||||
helpTopic="prefs-weave"
|
helpTopic="prefs-weave"
|
||||||
data-l10n-id="category-sync"
|
data-l10n-id="category-sync"
|
||||||
|
|
|
@ -98,9 +98,6 @@ let syncTourChecker = {
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (!Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check if we've already logged in at startup.
|
// Check if we've already logged in at startup.
|
||||||
const state = UIState.get();
|
const state = UIState.get();
|
||||||
if (state.status != UIState.STATUS_NOT_CONFIGURED) {
|
if (state.status != UIState.STATUS_NOT_CONFIGURED) {
|
||||||
|
|
|
@ -479,12 +479,7 @@ class Onboarding {
|
||||||
|
|
||||||
_getTourIDList() {
|
_getTourIDList() {
|
||||||
let tours = Services.prefs.getStringPref(`browser.onboarding.${this._tourType}tour`, "");
|
let tours = Services.prefs.getStringPref(`browser.onboarding.${this._tourType}tour`, "");
|
||||||
return tours.split(",").filter(tourId => {
|
return tours.split(",").filter(tourId => tourId !== "").map(tourId => tourId.trim());
|
||||||
if (tourId === "sync" && !Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return tourId !== "";
|
|
||||||
}).map(tourId => tourId.trim());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_initPrefObserver() {
|
_initPrefObserver() {
|
||||||
|
|
|
@ -1218,11 +1218,8 @@ var gBuiltInActions = [
|
||||||
onCommand(event, buttonNode) {
|
onCommand(event, buttonNode) {
|
||||||
browserPageActions(buttonNode).emailLink.onCommand(event, buttonNode);
|
browserPageActions(buttonNode).emailLink.onCommand(event, buttonNode);
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
];
|
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
|
||||||
gBuiltInActions.push(
|
|
||||||
// send to device
|
// send to device
|
||||||
{
|
{
|
||||||
id: "sendToDevice",
|
id: "sendToDevice",
|
||||||
|
@ -1250,8 +1247,8 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
|
||||||
.onShowingSubview(panelViewNode);
|
.onShowingSubview(panelViewNode);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
}
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -36,9 +36,6 @@ ChromeUtils.defineModuleGetter(this, "FxAccountsProfile",
|
||||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||||
"resource://services-sync/util.js");
|
"resource://services-sync/util.js");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "FXA_ENABLED",
|
|
||||||
"identity.fxaccounts.enabled", true);
|
|
||||||
|
|
||||||
// All properties exposed by the public FxAccounts API.
|
// All properties exposed by the public FxAccounts API.
|
||||||
var publicProperties = [
|
var publicProperties = [
|
||||||
"accountStatus",
|
"accountStatus",
|
||||||
|
@ -524,23 +521,20 @@ FxAccountsInternal.prototype = {
|
||||||
* }
|
* }
|
||||||
* or null if no user is signed in.
|
* or null if no user is signed in.
|
||||||
*/
|
*/
|
||||||
async getSignedInUser() {
|
getSignedInUser: function getSignedInUser() {
|
||||||
let currentState = this.currentAccountState;
|
let currentState = this.currentAccountState;
|
||||||
const data = await currentState.getUserAccountData();
|
return currentState.getUserAccountData().then(data => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return currentState.resolve(null);
|
return null;
|
||||||
}
|
}
|
||||||
if (!FXA_ENABLED) {
|
if (!this.isUserEmailVerified(data)) {
|
||||||
await this.signOut();
|
// If the email is not verified, start polling for verification,
|
||||||
return currentState.resolve(null);
|
// but return null right away. We don't want to return a promise
|
||||||
}
|
// that might not be fulfilled for a long time.
|
||||||
if (!this.isUserEmailVerified(data)) {
|
this.startVerifiedCheck(data);
|
||||||
// If the email is not verified, start polling for verification,
|
}
|
||||||
// but return null right away. We don't want to return a promise
|
return data;
|
||||||
// that might not be fulfilled for a long time.
|
}).then(result => currentState.resolve(result));
|
||||||
this.startVerifiedCheck(data);
|
|
||||||
}
|
|
||||||
return currentState.resolve(data);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -564,32 +558,37 @@ FxAccountsInternal.prototype = {
|
||||||
* The promise resolves to null when the data is saved
|
* The promise resolves to null when the data is saved
|
||||||
* successfully and is rejected on error.
|
* successfully and is rejected on error.
|
||||||
*/
|
*/
|
||||||
async setSignedInUser(credentials) {
|
setSignedInUser: function setSignedInUser(credentials) {
|
||||||
if (!FXA_ENABLED) {
|
|
||||||
throw new Error("Cannot call setSignedInUser when FxA is disabled.");
|
|
||||||
}
|
|
||||||
log.debug("setSignedInUser - aborting any existing flows");
|
log.debug("setSignedInUser - aborting any existing flows");
|
||||||
const signedInUser = await this.getSignedInUser();
|
return this.getSignedInUser().then(signedInUser => {
|
||||||
if (signedInUser) {
|
if (signedInUser) {
|
||||||
await this.deleteDeviceRegistration(signedInUser.sessionToken, signedInUser.deviceId);
|
return this.deleteDeviceRegistration(signedInUser.sessionToken, signedInUser.deviceId);
|
||||||
}
|
}
|
||||||
await this.abortExistingFlow();
|
return null;
|
||||||
let currentAccountState = this.currentAccountState = this.newAccountState(
|
}).then(() =>
|
||||||
Cu.cloneInto(credentials, {}) // Pass a clone of the credentials object.
|
this.abortExistingFlow()
|
||||||
);
|
).then(() => {
|
||||||
// This promise waits for storage, but not for verification.
|
let currentAccountState = this.currentAccountState = this.newAccountState(
|
||||||
// We're telling the caller that this is durable now (although is that
|
Cu.cloneInto(credentials, {}) // Pass a clone of the credentials object.
|
||||||
// really something we should commit to? Why not let the write happen in
|
);
|
||||||
// the background? Already does for updateAccountData ;)
|
// This promise waits for storage, but not for verification.
|
||||||
await currentAccountState.promiseInitialized;
|
// We're telling the caller that this is durable now (although is that
|
||||||
// Starting point for polling if new user
|
// really something we should commit to? Why not let the write happen in
|
||||||
if (!this.isUserEmailVerified(credentials)) {
|
// the background? Already does for updateAccountData ;)
|
||||||
this.startVerifiedCheck(credentials);
|
return currentAccountState.promiseInitialized.then(() => {
|
||||||
}
|
// Starting point for polling if new user
|
||||||
await this.updateDeviceRegistration();
|
if (!this.isUserEmailVerified(credentials)) {
|
||||||
Services.telemetry.getHistogramById("FXA_CONFIGURED").add(1);
|
this.startVerifiedCheck(credentials);
|
||||||
await this.notifyObservers(ONLOGIN_NOTIFICATION);
|
}
|
||||||
return currentAccountState.resolve();
|
|
||||||
|
return this.updateDeviceRegistration();
|
||||||
|
}).then(() => {
|
||||||
|
Services.telemetry.getHistogramById("FXA_CONFIGURED").add(1);
|
||||||
|
return this.notifyObservers(ONLOGIN_NOTIFICATION);
|
||||||
|
}).then(() => {
|
||||||
|
return currentAccountState.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -117,13 +117,13 @@ WeaveService.prototype = {
|
||||||
/**
|
/**
|
||||||
* Whether Sync appears to be enabled.
|
* Whether Sync appears to be enabled.
|
||||||
*
|
*
|
||||||
* This returns true if we have an associated FxA account and Sync is enabled.
|
* This returns true if we have an associated FxA account
|
||||||
*
|
*
|
||||||
* It does *not* perform a robust check to see if the client is working.
|
* It does *not* perform a robust check to see if the client is working.
|
||||||
* For that, you'll want to check Weave.Status.checkSetup().
|
* For that, you'll want to check Weave.Status.checkSetup().
|
||||||
*/
|
*/
|
||||||
get enabled() {
|
get enabled() {
|
||||||
return !!syncUsername && Services.prefs.getBoolPref("identity.fxaccounts.enabled");
|
return !!syncUsername;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче