Bug 1178378 - Register for web channel notications and update account profile on callback. r=nalexander, a=lizzard
authorvivek <vivekb.balakrishnan@gmail.com>
Tue, 22 Sep 2015 19:06:48 +0300
changeset 296193 02ccd14131b7d7a3a53ef1a8a4b748bd28c71b6e
parent 296192 d790b9a84515f61063a07fbf1c7e1fd02f573a6d
child 296194 c55a615814341cd023034f52f8b6f761d677ccfe
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander, lizzard
bugs1178378
milestone43.0a2
Bug 1178378 - Register for web channel notications and update account profile on callback. r=nalexander, a=lizzard
mobile/android/base/AccountsHelper.java
mobile/android/base/fxa/activities/FxAccountStatusFragment.java
mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
mobile/android/chrome/content/aboutAccounts.js
mobile/android/modules/Accounts.jsm
mobile/android/modules/FxAccountsWebChannel.jsm
--- a/mobile/android/base/AccountsHelper.java
+++ b/mobile/android/base/AccountsHelper.java
@@ -51,31 +51,33 @@ public class AccountsHelper implements N
             Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException());
             return;
         }
         dispatcher.registerGeckoThreadListener(this,
                 "Accounts:CreateFirefoxAccountFromJSON",
                 "Accounts:UpdateFirefoxAccountFromJSON",
                 "Accounts:Create",
                 "Accounts:DeleteFirefoxAccount",
-                "Accounts:Exist");
+                "Accounts:Exist",
+                "Accounts:ProfileUpdated");
     }
 
     public synchronized void uninit() {
         EventDispatcher dispatcher = EventDispatcher.getInstance();
         if (dispatcher == null) {
             Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException());
             return;
         }
         dispatcher.unregisterGeckoThreadListener(this,
                 "Accounts:CreateFirefoxAccountFromJSON",
                 "Accounts:UpdateFirefoxAccountFromJSON",
                 "Accounts:Create",
                 "Accounts:DeleteFirefoxAccount",
-                "Accounts:Exist");
+                "Accounts:Exist",
+                "Accounts:ProfileUpdated");
     }
 
     @Override
     public void handleMessage(String event, NativeJSObject message, final EventCallback callback) {
         if (!RestrictedProfiles.isAllowed(mContext, Restriction.DISALLOW_MODIFY_ACCOUNTS)) {
             // We register for messages in all contexts; we drop, with a log and an error to JavaScript,
             // when the profile is restricted.  It's better to return errors than silently ignore messages.
             Log.e(LOGTAG, "Profile is not allowed to modify accounts!  Ignoring event: " + event);
@@ -255,11 +257,19 @@ public class AccountsHelper implements N
                 } else {
                     callback.sendError("Could not query account existence: unknown kind.");
                 }
             } catch (JSONException e) {
                 Log.w(LOGTAG, "Got exception querying account existence; ignoring.", e);
                 callback.sendError("Could not query account existence: " + e.toString());
                 return;
             }
+        } else if ("Accounts:ProfileUpdated".equals(event)) {
+            final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
+            if (account == null) {
+                Log.w(LOGTAG, "Can't change profile of non-existent Firefox Account!; ignored");
+                return;
+            }
+            final AndroidFxAccount androidFxAccount = new AndroidFxAccount(mContext, account);
+            androidFxAccount.fetchProfileJSON();
         }
     }
 }
--- a/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
+++ b/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
@@ -6,16 +6,17 @@ package org.mozilla.gecko.fxa.activities
 
 import android.accounts.Account;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.preference.CheckBoxPreference;
 import android.preference.EditTextPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceCategory;
@@ -483,16 +484,17 @@ public class FxAccountStatusFragment
     // onResume/onPause calls, but because the Fragment gets onResume during the
     // Activity's super.onResume, it hasn't yet been told its Firefox Account.
     // So we register the observer here (and remove it in onPause), and open
     // ourselves to the possibility that we don't have properly paired
     // register/unregister calls.
     FxAccountSyncStatusHelper.getInstance().startObserving(syncStatusDelegate);
 
     if (AppConstants.MOZ_ANDROID_FIREFOX_ACCOUNT_PROFILES) {
+      profilePreference.getIntent().setData(Uri.parse("about:accounts?action=avatar"));
       // Register a local broadcast receiver to get profile cached notification.
       final IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(FxAccountConstants.ACCOUNT_PROFILE_JSON_UPDATED_ACTION);
       accountProfileInformationReceiver = new FxAccountProfileInformationReceiver();
       LocalBroadcastManager.getInstance(getActivity()).registerReceiver(accountProfileInformationReceiver, intentFilter);
 
       // profilePreference is set during onCreate, so it's definitely not null here.
       final float cornerRadius = getResources().getDimension(R.dimen.fxaccount_profile_image_width) / 2;
--- a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
+++ b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
@@ -5,17 +5,22 @@
     <PreferenceCategory
         android:key="signed_in_as_category"
         android:title="@string/fxaccount_status_signed_in_as" >
         <Preference
             android:editable="false"
             android:key="profile"
             android:icon="@drawable/sync_avatar_default"
             android:persistent="false"
-            android:title="" />
+            android:title="" >
+            <intent
+                android:action="android.intent.action.VIEW"
+                android:targetClass="@string/browser_intent_class"
+                android:targetPackage="@string/browser_intent_package" />
+        </Preference>
         <Preference
             android:editable="false"
             android:key="email"
             android:persistent="false"
             android:title="@string/fxaccount_email_hint" />
         <Preference
             android:editable="false"
             android:key="manage_account"
--- a/mobile/android/chrome/content/aboutAccounts.js
+++ b/mobile/android/chrome/content/aboutAccounts.js
@@ -251,16 +251,26 @@ function init() {
         show("spinner");
         urlParams.set("email", user.email); // In future, pin using the UID.
         wrapper.init(getURLForAction("settings", urlParams));
       } else {
         show("spinner");
         wrapper.init(getURLForAction("signup", urlParams));
       }
       break;
+    case "avatar":
+      if (user) {
+        show("spinner");
+        urlParams.set("email", user.email); // In future, pin using the UID.
+        wrapper.init(getURLForAction("settings/avatar/change", urlParams));
+      } else {
+        show("spinner");
+        wrapper.init(getURLForAction("signup", urlParams));
+      }
+      break;
     default:
       // Unrecognized or no action specified.
       if (action) {
         log.w("Ignoring unrecognized action: " + action);
       }
       if (user) {
         show("prefs");
       } else {
--- a/mobile/android/modules/Accounts.jsm
+++ b/mobile/android/modules/Accounts.jsm
@@ -110,16 +110,30 @@ var Accounts = Object.freeze({
   updateFirefoxAccountFromJSON: function (json) {
     return Messaging.sendRequestForResult({
       type: "Accounts:UpdateFirefoxAccountFromJSON",
       json: this._addDefaultEndpoints(json)
     });
   },
 
   /**
+   * Notify that profile for Android Account has updated.
+   * The account will re-fetch the profile image.
+   *
+   * It is an error if no Android Account exists.
+   *
+   * There is no return value from this method.
+   */
+  notifyFirefoxAccountProfileChanged: function () {
+    Messaging.sendRequest({
+      type: "Accounts:ProfileUpdated",
+    });
+  },
+
+  /**
    * Fetch information about an existing Android Firefox Account.
    *
    * Returns a Promise that resolves to null if no Android Firefox Account
    * exists, or an object including at least a string-valued 'email' key.
    */
   getFirefoxAccount: function () {
     return Messaging.sendRequestForResult({
       type: "Accounts:Exist",
--- a/mobile/android/modules/FxAccountsWebChannel.jsm
+++ b/mobile/android/modules/FxAccountsWebChannel.jsm
@@ -24,16 +24,17 @@ const log = Cu.import("resource://gre/mo
 
 const WEBCHANNEL_ID = "account_updates";
 
 const COMMAND_LOADED               = "fxaccounts:loaded";
 const COMMAND_CAN_LINK_ACCOUNT     = "fxaccounts:can_link_account";
 const COMMAND_LOGIN                = "fxaccounts:login";
 const COMMAND_CHANGE_PASSWORD      = "fxaccounts:change_password";
 const COMMAND_DELETE_ACCOUNT       = "fxaccounts:delete_account";
+const COMMAND_PROFILE_CHANGE       = "profile:change";
 
 const PREF_LAST_FXA_USER           = "identity.fxaccounts.lastSignedInUserHash";
 
 XPCOMUtils.defineLazyGetter(this, "strings",
                             () => Services.strings.createBundle("chrome://browser/locale/aboutAccounts.properties")); /*global strings */
 
 Object.defineProperty(this, "NativeWindow",
                       { get: () => Services.wm.getMostRecentWindow("navigator:browser").NativeWindow }); /*global NativeWindow */
@@ -331,16 +332,29 @@ this.FxAccountsWebChannel.prototype = {
                 }
                 log.i("Firefox Account deleted.");
               });
             }).catch(e => {
               log.e(e.toString());
             });
             break;
 
+          case COMMAND_PROFILE_CHANGE:
+            // Only update an existing Android Account.
+            Accounts.getFirefoxAccount().then(account => {
+              if (!account) {
+                throw new Error("Can't change profile of non-existent Firefox Account!");
+              }
+              return Accounts.notifyFirefoxAccountProfileChanged();
+            })
+            .catch(e => {
+              log.e(e.toString());
+            });
+            break;
+
           default:
             log.w("Ignoring unrecognized FxAccountsWebChannel command: " + JSON.stringify(command));
             break;
         }
       }
     };
 
     this._channelCallback = listener;