1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/browser-fxaccounts.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,233 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () { 1.9 + return Cu.import("resource://gre/modules/FxAccountsCommon.js", {}); 1.10 +}); 1.11 + 1.12 +const PREF_SYNC_START_DOORHANGER = "services.sync.ui.showSyncStartDoorhanger"; 1.13 +const DOORHANGER_ACTIVATE_DELAY_MS = 5000; 1.14 + 1.15 +let gFxAccounts = { 1.16 + 1.17 + _initialized: false, 1.18 + _inCustomizationMode: false, 1.19 + 1.20 + get weave() { 1.21 + delete this.weave; 1.22 + return this.weave = Cc["@mozilla.org/weave/service;1"] 1.23 + .getService(Ci.nsISupports) 1.24 + .wrappedJSObject; 1.25 + }, 1.26 + 1.27 + get topics() { 1.28 + // Do all this dance to lazy-load FxAccountsCommon. 1.29 + delete this.topics; 1.30 + return this.topics = [ 1.31 + "weave:service:ready", 1.32 + "weave:service:sync:start", 1.33 + "weave:service:login:error", 1.34 + "weave:service:setup-complete", 1.35 + FxAccountsCommon.ONVERIFIED_NOTIFICATION, 1.36 + FxAccountsCommon.ONLOGOUT_NOTIFICATION 1.37 + ]; 1.38 + }, 1.39 + 1.40 + get button() { 1.41 + delete this.button; 1.42 + return this.button = document.getElementById("PanelUI-fxa-status"); 1.43 + }, 1.44 + 1.45 + get loginFailed() { 1.46 + // Referencing Weave.Service will implicitly initialize sync, and we don't 1.47 + // want to force that - so first check if it is ready. 1.48 + let service = Cc["@mozilla.org/weave/service;1"] 1.49 + .getService(Components.interfaces.nsISupports) 1.50 + .wrappedJSObject; 1.51 + if (!service.ready) { 1.52 + return false; 1.53 + } 1.54 + // LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in". 1.55 + // All other login failures are assumed to be transient and should go 1.56 + // away by themselves, so aren't reflected here. 1.57 + return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED; 1.58 + }, 1.59 + 1.60 + get isActiveWindow() { 1.61 + let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); 1.62 + return fm.activeWindow == window; 1.63 + }, 1.64 + 1.65 + init: function () { 1.66 + // Bail out if we're already initialized and for pop-up windows. 1.67 + if (this._initialized || !window.toolbar.visible) { 1.68 + return; 1.69 + } 1.70 + 1.71 + for (let topic of this.topics) { 1.72 + Services.obs.addObserver(this, topic, false); 1.73 + } 1.74 + 1.75 + addEventListener("activate", this); 1.76 + gNavToolbox.addEventListener("customizationstarting", this); 1.77 + gNavToolbox.addEventListener("customizationending", this); 1.78 + 1.79 + this._initialized = true; 1.80 + 1.81 + this.updateUI(); 1.82 + }, 1.83 + 1.84 + uninit: function () { 1.85 + if (!this._initialized) { 1.86 + return; 1.87 + } 1.88 + 1.89 + for (let topic of this.topics) { 1.90 + Services.obs.removeObserver(this, topic); 1.91 + } 1.92 + 1.93 + this._initialized = false; 1.94 + }, 1.95 + 1.96 + observe: function (subject, topic) { 1.97 + switch (topic) { 1.98 + case FxAccountsCommon.ONVERIFIED_NOTIFICATION: 1.99 + Services.prefs.setBoolPref(PREF_SYNC_START_DOORHANGER, true); 1.100 + break; 1.101 + case "weave:service:sync:start": 1.102 + this.onSyncStart(); 1.103 + break; 1.104 + default: 1.105 + this.updateUI(); 1.106 + break; 1.107 + } 1.108 + }, 1.109 + 1.110 + onSyncStart: function () { 1.111 + if (!this.isActiveWindow) { 1.112 + return; 1.113 + } 1.114 + 1.115 + let showDoorhanger = false; 1.116 + 1.117 + try { 1.118 + showDoorhanger = Services.prefs.getBoolPref(PREF_SYNC_START_DOORHANGER); 1.119 + } catch (e) { /* The pref might not exist. */ } 1.120 + 1.121 + if (showDoorhanger) { 1.122 + Services.prefs.clearUserPref(PREF_SYNC_START_DOORHANGER); 1.123 + this.showSyncStartedDoorhanger(); 1.124 + } 1.125 + }, 1.126 + 1.127 + handleEvent: function (event) { 1.128 + if (event.type == "activate") { 1.129 + // Our window might have been in the background while we received the 1.130 + // sync:start notification. If still needed, show the doorhanger after 1.131 + // a short delay. Without this delay the doorhanger would not show up 1.132 + // or with a too small delay show up while we're still animating the 1.133 + // window. 1.134 + setTimeout(() => this.onSyncStart(), DOORHANGER_ACTIVATE_DELAY_MS); 1.135 + } else { 1.136 + this._inCustomizationMode = event.type == "customizationstarting"; 1.137 + this.updateUI(); 1.138 + } 1.139 + }, 1.140 + 1.141 + showDoorhanger: function (id) { 1.142 + let panel = document.getElementById(id); 1.143 + let anchor = document.getElementById("PanelUI-menu-button"); 1.144 + 1.145 + let iconAnchor = 1.146 + document.getAnonymousElementByAttribute(anchor, "class", 1.147 + "toolbarbutton-icon"); 1.148 + 1.149 + panel.hidden = false; 1.150 + panel.openPopup(iconAnchor || anchor, "bottomcenter topright"); 1.151 + }, 1.152 + 1.153 + showSyncStartedDoorhanger: function () { 1.154 + this.showDoorhanger("sync-start-panel"); 1.155 + }, 1.156 + 1.157 + showSyncFailedDoorhanger: function () { 1.158 + this.showDoorhanger("sync-error-panel"); 1.159 + }, 1.160 + 1.161 + updateUI: function () { 1.162 + // Bail out if FxA is disabled. 1.163 + if (!this.weave.fxAccountsEnabled) { 1.164 + return; 1.165 + } 1.166 + 1.167 + // FxA is enabled, show the widget. 1.168 + this.button.removeAttribute("hidden"); 1.169 + 1.170 + // Make sure the button is disabled in customization mode. 1.171 + if (this._inCustomizationMode) { 1.172 + this.button.setAttribute("disabled", "true"); 1.173 + } else { 1.174 + this.button.removeAttribute("disabled"); 1.175 + } 1.176 + 1.177 + let defaultLabel = this.button.getAttribute("defaultlabel"); 1.178 + let errorLabel = this.button.getAttribute("errorlabel"); 1.179 + 1.180 + // If the user is signed into their Firefox account and we are not 1.181 + // currently in customization mode, show their email address. 1.182 + let doUpdate = userData => { 1.183 + // Reset the button to its original state. 1.184 + this.button.setAttribute("label", defaultLabel); 1.185 + this.button.removeAttribute("tooltiptext"); 1.186 + this.button.removeAttribute("signedin"); 1.187 + this.button.removeAttribute("failed"); 1.188 + 1.189 + if (!this._inCustomizationMode) { 1.190 + if (this.loginFailed) { 1.191 + this.button.setAttribute("failed", "true"); 1.192 + this.button.setAttribute("label", errorLabel); 1.193 + } else if (userData) { 1.194 + this.button.setAttribute("signedin", "true"); 1.195 + this.button.setAttribute("label", userData.email); 1.196 + this.button.setAttribute("tooltiptext", userData.email); 1.197 + } 1.198 + } 1.199 + } 1.200 + fxAccounts.getSignedInUser().then(userData => { 1.201 + doUpdate(userData); 1.202 + }).then(null, error => { 1.203 + // This is most likely in tests, were we quickly log users in and out. 1.204 + // The most likely scenario is a user logged out, so reflect that. 1.205 + // Bug 995134 calls for better errors so we could retry if we were 1.206 + // sure this was the failure reason. 1.207 + doUpdate(null); 1.208 + }); 1.209 + }, 1.210 + 1.211 + onMenuPanelCommand: function (event) { 1.212 + let button = event.originalTarget; 1.213 + 1.214 + if (button.hasAttribute("signedin")) { 1.215 + this.openPreferences(); 1.216 + } else if (button.hasAttribute("failed")) { 1.217 + this.openSignInAgainPage(); 1.218 + } else { 1.219 + this.openAccountsPage(); 1.220 + } 1.221 + 1.222 + PanelUI.hide(); 1.223 + }, 1.224 + 1.225 + openPreferences: function () { 1.226 + openPreferences("paneSync"); 1.227 + }, 1.228 + 1.229 + openAccountsPage: function () { 1.230 + switchToTabHavingURI("about:accounts", true); 1.231 + }, 1.232 + 1.233 + openSignInAgainPage: function () { 1.234 + switchToTabHavingURI("about:accounts?action=reauth", true); 1.235 + } 1.236 +};