Bug 1201335 - Display notification on sync device connected. r?markh draft
authorEdouard Oger <eoger@fastmail.com>
Fri, 20 May 2016 16:52:30 -0700
changeset 369260 77f317094ace7e6a6d6fb852613293851bd043b0
parent 369022 c67dc1f9fab86d4f2cf3224307809c44fe3ce820
child 521530 e26dce05d71ccc0b186fb3ffe14de31f040a59ef
push id18814
push userbmo:edouard.oger@gmail.com
push dateFri, 20 May 2016 23:56:43 +0000
reviewersmarkh
bugs1201335
milestone49.0a1
Bug 1201335 - Display notification on sync device connected. r?markh MozReview-Commit-ID: CM0c7d3PLXa
browser/base/content/browser-fxaccounts.js
browser/locales/en-US/chrome/browser/accounts.properties
services/fxaccounts/FxAccountsCommon.js
services/fxaccounts/FxAccountsPush.js
services/fxaccounts/tests/xpcshell/test_push_service.js
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -27,16 +27,17 @@ var gFxAccounts = {
       "weave:service:login:error",
       "weave:service:setup-complete",
       "weave:ui:login:error",
       "fxa-migration:state-changed",
       this.FxAccountsCommon.ONLOGIN_NOTIFICATION,
       this.FxAccountsCommon.ONVERIFIED_NOTIFICATION,
       this.FxAccountsCommon.ONLOGOUT_NOTIFICATION,
       this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
+      this.FxAccountsCommon.ON_DEVICE_CONNECTED_NOTIFICATION,
     ];
   },
 
   get panelUIFooter() {
     delete this.panelUIFooter;
     return this.panelUIFooter = document.getElementById("PanelUI-footer-fxa");
   },
 
@@ -125,16 +126,19 @@ var gFxAccounts = {
         Services.prefs.setBoolPref(this.PREF_SYNC_START_DOORHANGER, true);
         break;
       case "weave:service:sync:start":
         this.onSyncStart();
         break;
       case "fxa-migration:state-changed":
         this.onMigrationStateChanged(data, subject);
         break;
+      case this.FxAccountsCommon.ON_DEVICE_CONNECTED_NOTIFICATION:
+        this.onDeviceConnected(data);
+        break;
       case this.FxAccountsCommon.ONPROFILE_IMAGE_CHANGE_NOTIFICATION:
         this.updateUI();
         break;
       default:
         this.updateUI();
         break;
     }
   },
@@ -223,16 +227,22 @@ var gFxAccounts = {
     panel.hidden = false;
     panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
   },
 
   showSyncStartedDoorhanger: function () {
     this.showDoorhanger("sync-start-panel");
   },
 
+  onDeviceConnected: function (deviceName) {
+    let title = this.strings.GetStringFromName("deviceConnectedTitle");
+    let body = this.strings.formatStringFromName("deviceConnectedBody", [deviceName], 1);
+    new Notification(title, { body })
+  },
+
   updateUI: function () {
     // It's possible someone signed in to FxA after seeing our notification
     // about "Legacy Sync migration" (which now is actually "Legacy Sync
     // auto-disconnect") so kill that notification if it still exists.
     let nb = window.document.getElementById("global-notificationbox");
     let n = nb.getNotificationWithValue(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
     if (n) {
       nb.removeNotification(n, true);
--- a/browser/locales/en-US/chrome/browser/accounts.properties
+++ b/browser/locales/en-US/chrome/browser/accounts.properties
@@ -18,8 +18,11 @@ verifyDescription = Verify %S
 
 # These strings are shown in a flyout in the Sync preference panel after the
 # user requests we resend a verification email.
 verificationSentTitle = Verification Sent
 # LOCALIZATION NOTE (verificationSentFull) - %S = Email address of user's Firefox Account
 verificationSentFull = A verification link has been sent to %S. Please check your email and click the link to begin syncing.
 verificationNotSentTitle = Unable to Send Verification
 verificationNotSentFull = We are unable to send a verification mail at this time, please try again later.
+
+deviceConnectedTitle = Firefox Sync
+deviceConnectedBody = You are now syncing with %S.
--- a/services/fxaccounts/FxAccountsCommon.js
+++ b/services/fxaccounts/FxAccountsCommon.js
@@ -84,16 +84,17 @@ exports.KEY_LIFETIME       = 1000 * 3600
 exports.POLL_SESSION       = 1000 * 60 * 20;   // 20 minutes
 
 // Observer notifications.
 exports.ONLOGIN_NOTIFICATION = "fxaccounts:onlogin";
 exports.ONVERIFIED_NOTIFICATION = "fxaccounts:onverified";
 exports.ONLOGOUT_NOTIFICATION = "fxaccounts:onlogout";
 // Internal to services/fxaccounts only
 exports.ON_FXA_UPDATE_NOTIFICATION = "fxaccounts:update";
+exports.ON_DEVICE_CONNECTED_NOTIFICATION = "fxaccounts:device_connected";
 
 exports.FXA_PUSH_SCOPE_ACCOUNT_UPDATE = "chrome://fxa-device-update";
 
 exports.ON_PROFILE_CHANGE_NOTIFICATION = "fxaccounts:profilechange";
 
 // UI Requests.
 exports.UI_REQUEST_SIGN_IN_FLOW = "signInFlow";
 exports.UI_REQUEST_REFRESH_AUTH = "refreshAuthentication";
--- a/services/fxaccounts/FxAccountsPush.js
+++ b/services/fxaccounts/FxAccountsPush.js
@@ -114,17 +114,17 @@ FxAccountsPushService.prototype = {
    * @param topic
    * @param data
    */
   observe(subject, topic, data) {
    this.log.trace(`observed topic=${topic}, data=${data}, subject=${subject}`);
    switch (topic) {
      case this.pushService.pushTopic:
        if (data === FXA_PUSH_SCOPE_ACCOUNT_UPDATE) {
-         this._onPushMessage();
+         this._onPushMessage(subject);
        }
        break;
      case this.pushService.subscriptionChangeTopic:
        if (data === FXA_PUSH_SCOPE_ACCOUNT_UPDATE) {
          this._onPushSubscriptionChange();
        }
        break;
      case ONLOGOUT_NOTIFICATION:
@@ -137,20 +137,29 @@ FxAccountsPushService.prototype = {
        break;
    }
   },
   /**
    * Fired when the Push server sends a notification.
    *
    * @private
    */
-  _onPushMessage() {
+  _onPushMessage(maybeMessage) {
     this.log.trace("FxAccountsPushService _onPushMessage");
-    // Use this signal to check the verification state of the account right away
-    this.fxAccounts.checkVerificationStatus();
+    let message;
+    if (maybeMessage) {
+      message = maybeMessage.QueryInterface(Ci.nsIPushMessage).json();
+    }
+
+    if (message && message.command === ON_DEVICE_CONNECTED_NOTIFICATION) {
+      Services.obs.notifyObservers(null, ON_DEVICE_CONNECTED_NOTIFICATION, message.data.deviceName);
+    } else {
+      // Use the empty signal to check the verification state of the account right away
+      this.fxAccounts.checkVerificationStatus();
+    }
   },
   /**
    * Fired when the Push server drops a subscription, or the subscription identifier changes.
    *
    * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIPushService#Receiving_Push_Messages
    *
    * @private
    */
--- a/services/fxaccounts/tests/xpcshell/test_push_service.js
+++ b/services/fxaccounts/tests/xpcshell/test_push_service.js
@@ -41,17 +41,16 @@ let mockFxAccounts = {
 
 let mockLog = {
   trace() {},
   debug() {},
   warn() {},
   error() {}
 };
 
-
 add_task(function* initialize() {
   let pushService = new FxAccountsPushService();
   do_check_eq(pushService.initialize(), false);
 });
 
 add_task(function* registerPushEndpointSuccess() {
   let pushService = new FxAccountsPushService({
     pushService: mockPushService,
@@ -117,32 +116,58 @@ add_test(function observeLogout() {
   let pushService = new FxAccountsPushService({
     pushService: mockPushService,
     log: customLog
   });
 
   pushService.observe(null, ONLOGOUT_NOTIFICATION);
 });
 
-add_test(function observePushTopic() {
+add_test(function observePushTopicVerify() {
   let customAccounts = Object.assign(mockFxAccounts, {
     checkVerificationStatus: function () {
-      // checking verification status on push messages
+      // checking verification status on push messages without data
       run_next_test();
     }
   });
 
   let pushService = new FxAccountsPushService({
     pushService: mockPushService,
     fxAccounts: customAccounts,
   });
 
   pushService.observe(null, mockPushService.pushTopic, FXA_PUSH_SCOPE_ACCOUNT_UPDATE);
 });
 
+add_test(function observePushTopicNewDevice() {
+  let msg = {
+    json: () => ({
+      action: ON_DEVICE_CONNECTED_NOTIFICATION,
+      data: {
+        deviceName: "My Phone"
+      }
+    }),
+    QueryInterface: function() {
+      return this;
+    }
+  };
+  let obs = (subject, topic, data) => {
+    Services.obs.removeObserver(obs, topic);
+    run_next_test();
+  };
+  Services.obs.addObserver(obs, ON_DEVICE_CONNECTED_NOTIFICATION, false);
+
+  let pushService = new FxAccountsPushService({
+    pushService: mockPushService,
+    fxAccounts: mockFxAccounts,
+  });
+
+  pushService.observe(msg, mockPushService.pushTopic, FXA_PUSH_SCOPE_ACCOUNT_UPDATE);
+});
+
 add_test(function observeSubscriptionChangeTopic() {
   let customAccounts = Object.assign(mockFxAccounts, {
     updateDeviceRegistration: function () {
       // subscription change means updating the device registration
       run_next_test();
     }
   });