Bug 965811 - Support Firefox Account-based Sync in SendTabActivity. r=nalexander, a=lsblakk
authorRichard Newman <rnewman@mozilla.com>
Fri, 28 Mar 2014 15:11:09 -0700
changeset 185191 c3cef613d28b3d1f838873e9f04eb72dd3723193
parent 185190 27349a7974257ce92e37ab4764b1b5e61c0dd747
child 185192 c4a49783aa222c13b2c8fa8ccf56d252be85cfc3
push id5551
push usernalexander@mozilla.com
push dateFri, 28 Mar 2014 22:13:27 +0000
treeherdermozilla-aurora@c3cef613d28b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander, lsblakk
bugs965811
milestone30.0a2
Bug 965811 - Support Firefox Account-based Sync in SendTabActivity. r=nalexander, a=lsblakk
mobile/android/base/sync/setup/activities/SendTabActivity.java
--- a/mobile/android/base/sync/setup/activities/SendTabActivity.java
+++ b/mobile/android/base/sync/setup/activities/SendTabActivity.java
@@ -7,46 +7,120 @@ package org.mozilla.gecko.sync.setup.act
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.fxa.FxAccountConstants;
+import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
+import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.sync.CommandProcessor;
 import org.mozilla.gecko.sync.CommandRunner;
 import org.mozilla.gecko.sync.GlobalSession;
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.sync.SyncConstants;
+import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.repositories.NullCursorException;
 import org.mozilla.gecko.sync.repositories.android.ClientsDatabaseAccessor;
 import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
-import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.setup.SyncAccounts;
 import org.mozilla.gecko.sync.stage.SyncClientsEngineStage;
 import org.mozilla.gecko.sync.syncadapter.SyncAdapter;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
 
 public class SendTabActivity extends Activity {
+  private interface TabSender {
+    static final String[] CLIENTS_STAGE = new String[] { SyncClientsEngineStage.COLLECTION_NAME };
+
+    /**
+     * @return Return null if the account isn't correctly initialized. Return
+     *         the account GUID otherwise.
+     */
+    String getAccountGUID();
+
+    /**
+     * Sync this account, specifying only clients as the engine to sync.
+     */
+    void syncClientsStage();
+  }
+
+  public class FxAccountTabSender implements TabSender {
+    private final AndroidFxAccount account;
+
+    public FxAccountTabSender(Context context, Account account) {
+      this.account = new AndroidFxAccount(context, account);
+    }
+
+    @Override
+    public String getAccountGUID() {
+      try {
+        final SharedPreferences prefs = this.account.getSyncPrefs();
+        return prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null);
+      } catch (Exception e) {
+        Logger.warn(LOG_TAG, "Could not get Firefox Account parameters or preferences; aborting.");
+        return null;
+      }
+    }
+
+    @Override
+    public void syncClientsStage() {
+      final Bundle extras = new Bundle();
+      Utils.putStageNamesToSync(extras, CLIENTS_STAGE, null);
+      extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+      this.account.requestSync(extras);
+    }
+  }
+
+  private static class Sync11TabSender implements TabSender {
+    private final Account account;
+    private final AccountManager accountManager;
+    private final Context context;
+    private Sync11TabSender(Context context, Account syncAccount, AccountManager accountManager) {
+      this.context = context;
+      this.account = syncAccount;
+      this.accountManager = accountManager;
+    }
+
+    @Override
+    public String getAccountGUID() {
+      try {
+        final SharedPreferences prefs = SyncAccounts.blockingPrefsFromDefaultProfileV0(this.context, this.accountManager, this.account);
+        return prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null);
+      } catch (Exception e) {
+        Logger.warn(LOG_TAG, "Could not get Sync account parameters or preferences; aborting.");
+        return null;
+      }
+    }
+
+    @Override
+    public void syncClientsStage() {
+      SyncAdapter.requestImmediateSync(this.account, CLIENTS_STAGE);
+    }
+  }
+
   public static final String LOG_TAG = "SendTabActivity";
   private ClientRecordArrayAdapter arrayAdapter;
-  private AccountManager accountManager;
-  private Account localAccount;
+
+  private TabSender tabSender;
   private SendTabData sendTabData;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
 
     try {
       sendTabData = getSendTabData(getIntent());
@@ -137,96 +211,96 @@ public class SendTabActivity extends Act
   }
 
   @Override
   public void onResume() {
     ActivityUtils.prepareLogging();
     Logger.info(LOG_TAG, "Called SendTabActivity.onResume.");
     super.onResume();
 
-    redirectIfNoSyncAccount();
-    registerDisplayURICommand();
+    /*
+     * First, decide if we are able to send anything.
+     */
+    final Context applicationContext = getApplicationContext();
+    final AccountManager accountManager = AccountManager.get(applicationContext);
+
+    final Account[] fxAccounts = accountManager.getAccountsByType(FxAccountConstants.ACCOUNT_TYPE);
+    if (fxAccounts.length > 0) {
+      this.tabSender = new FxAccountTabSender(applicationContext, fxAccounts[0]);
+
+      Logger.info(LOG_TAG, "Allowing tab send for Firefox Account.");
+      registerDisplayURICommand();
+      return;
+    }
+
+    final Account[] syncAccounts = accountManager.getAccountsByType(SyncConstants.ACCOUNTTYPE_SYNC);
+    if (syncAccounts.length > 0) {
+      this.tabSender = new Sync11TabSender(applicationContext, syncAccounts[0], accountManager);
+
+      Logger.info(LOG_TAG, "Allowing tab send for Sync account.");
+      registerDisplayURICommand();
+      return;
+    }
+
+    // Offer to set up a Firefox Account, and finish this activity.
+    final Intent intent = new Intent(applicationContext, FxAccountGetStartedActivity.class);
+    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    startActivity(intent);
+    finish();
   }
 
   private static void registerDisplayURICommand() {
     final CommandProcessor processor = CommandProcessor.getProcessor();
     processor.registerCommand("displayURI", new CommandRunner(3) {
       @Override
       public void executeCommand(final GlobalSession session, List<String> args) {
         CommandProcessor.displayURI(args, session.getContext());
       }
     });
   }
 
-  private void redirectIfNoSyncAccount() {
-    accountManager = AccountManager.get(getApplicationContext());
-    Account[] accts = accountManager.getAccountsByType(SyncConstants.ACCOUNTTYPE_SYNC);
-
-    // A Sync account exists.
-    if (accts.length > 0) {
-      localAccount = accts[0];
-      return;
-    }
-
-    Intent intent = new Intent(this, RedirectToSetupActivity.class);
-    intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
-    startActivity(intent);
-    finish();
-  }
-
-  /**
-   * @return Return null if there is no account set up. Return the account GUID otherwise.
-   */
-  private String getAccountGUID() {
-    if (localAccount == null) {
-      Logger.warn(LOG_TAG, "Null local account; aborting.");
-      return null;
-    }
-
-    SharedPreferences prefs;
-    try {
-      prefs = SyncAccounts.blockingPrefsFromDefaultProfileV0(this, accountManager, localAccount);
-      return prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null);
-    } catch (Exception e) {
-      Logger.warn(LOG_TAG, "Could not get Sync account parameters or preferences; aborting.");
-      return null;
-    }
-  }
-
   public void sendClickHandler(View view) {
     Logger.info(LOG_TAG, "Send was clicked.");
     final List<String> remoteClientGuids = arrayAdapter.getCheckedGUIDs();
 
     if (remoteClientGuids == null) {
       // Should never happen.
       Logger.warn(LOG_TAG, "guids was null; aborting without sending tab.");
       notifyAndFinish(false);
       return;
     }
 
+    final TabSender sender = this.tabSender;
+    if (sender == null) {
+      // This should never happen.
+      Logger.warn(LOG_TAG, "tabSender was null; aborting without sending tab.");
+      notifyAndFinish(false);
+      return;
+    }
+
     // Fetching local client GUID hits the DB, and we want to update the UI
     // afterward, so we perform the tab sending on another thread.
     new AsyncTask<Void, Void, Boolean>() {
 
       @Override
       protected Boolean doInBackground(Void... params) {
         final CommandProcessor processor = CommandProcessor.getProcessor();
 
-        final String accountGUID = getAccountGUID();
+        final String accountGUID = sender.getAccountGUID();
         Logger.debug(LOG_TAG, "Retrieved local account GUID '" + accountGUID + "'.");
         if (accountGUID == null) {
           return false;
         }
 
         for (String remoteClientGuid : remoteClientGuids) {
           processor.sendURIToClientForDisplay(sendTabData.uri, remoteClientGuid, sendTabData.title, accountGUID, getApplicationContext());
         }
 
         Logger.info(LOG_TAG, "Requesting immediate clients stage sync.");
-        SyncAdapter.requestImmediateSync(localAccount, new String[] { SyncClientsEngineStage.COLLECTION_NAME });
+        sender.syncClientsStage();
 
         return true;
       }
 
       @Override
       protected void onPostExecute(final Boolean success) {
         // We're allowed to update the UI from here.
         notifyAndFinish(success.booleanValue());
@@ -281,17 +355,22 @@ public class SendTabActivity extends Act
    * @return a collection of client records, excluding our own.
    */
   protected Collection<ClientRecord> getOtherClients() {
     final Map<String, ClientRecord> all = getAllClients();
     if (all == null) {
       return new ArrayList<ClientRecord>(0);
     }
 
-    final String ourGUID = getAccountGUID();
+    if (this.tabSender == null) {
+      Logger.warn(LOG_TAG, "No tab sender when fetching other client IDs.");
+      return new ArrayList<ClientRecord>(0);
+    }
+
+    final String ourGUID = this.tabSender.getAccountGUID();
     if (ourGUID == null) {
       return all.values();
     }
 
     final ArrayList<ClientRecord> out = new ArrayList<ClientRecord>(all.size());
     for (Entry<String, ClientRecord> entry : all.entrySet()) {
       if (ourGUID.equals(entry.getKey())) {
         continue;