Bug 965811 - Support Firefox Account-based Sync in SendTabActivity. r=nalexander
authorRichard Newman <rnewman@mozilla.com>
Wed, 26 Mar 2014 22:21:19 -0700
changeset 175617 35088bd669be469b42dd356205cf0f082387a7c0
parent 175616 998abc07871169ac8e23d22f2fb264739b78d6f0
child 175618 bb4dd9872236bfd9a2238b731f7e98081811ebbd
child 175744 017e2bfa1550752b8ae53b673f27131917e9ae9c
push id26495
push usercbook@mozilla.com
push dateThu, 27 Mar 2014 13:14:49 +0000
treeherdermozilla-central@bb4dd9872236 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs965811
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 965811 - Support Firefox Account-based Sync in SendTabActivity. r=nalexander
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;