Bug 766499 - Show error message about multiple Firefox installations when Android Sync fails on Account creation. r=nalexander
authorChenxia Liu <liuche@mozilla.com>
Tue, 26 Jun 2012 10:43:56 -0700
changeset 97708 829abeedcde45efb8235b043255d348616c13c88
parent 97707 2efe5f77b9522f894cc2f1494db0dd93ccaa7f0e
child 97709 6fb15015d104de891fbb59c772702bb7512f311b
push id22993
push useremorley@mozilla.com
push dateWed, 27 Jun 2012 10:31:27 +0000
treeherdermozilla-central@1a56f1f011c9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs766499
milestone16.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 766499 - Show error message about multiple Firefox installations when Android Sync fails on Account creation. r=nalexander
mobile/android/base/locales/en-US/sync_strings.dtd
mobile/android/base/resources/layout/sync_setup_failure.xml
mobile/android/base/sync/setup/Constants.java
mobile/android/base/sync/setup/activities/AccountActivity.java
mobile/android/base/sync/setup/activities/SetupFailureActivity.java
mobile/android/base/sync/setup/activities/SetupSyncActivity.java
mobile/android/base/sync/setup/auth/AuthenticationResult.java
mobile/android/sync/strings.xml.in
--- a/mobile/android/base/locales/en-US/sync_strings.dtd
+++ b/mobile/android/base/locales/en-US/sync_strings.dtd
@@ -36,16 +36,18 @@
 <!ENTITY sync.input.server.label 'Server URL'>
   
 <!-- Setup Fail -->
 <!ENTITY sync.title.fail.label 'Cannot Set Up &syncBrand.shortName.label;'>
 <!ENTITY sync.subtitle.fail.label '&syncBrand.fullName.label; could not connect to the server. Would you like to try again?'>
 <!ENTITY sync.button.tryagain.label 'Try again'>
 <!ENTITY sync.button.manual.label 'Manual Setup'>
 <!ENTITY sync.subtitle.nointernet.label 'No internet connection available.'>
+<!ENTITY sync.subtitle.failaccount.label 'Account creation on your device failed.'>
+<!ENTITY sync.subtitle.failmultiple.label 'Do you have more than one Firefox installed? Currently, &syncBrand.fullName.label; only supports one Firefox installation at a time. Please uninstall other instances to use &syncBrand.shortName.label;.'>
   
 <!-- Setup Success -->
 <!ENTITY sync.title.success.label 'Setup Complete'>
 <!ENTITY sync.subtitle.success.label1 'Your data is now being downloaded in the background. You can go to Settings to manage your account, or start browsing with &brandShortName;.'>
 <!ENTITY sync.settings.label 'Settings'>
 <!ENTITY sync.subtitle.manage.label1 'Your &syncBrand.fullName.label; account is already set up. You can go to Settings to manage your account, or launch &brandShortName;.'>
 
 <!-- Pair Device -->
--- a/mobile/android/base/resources/layout/sync_setup_failure.xml
+++ b/mobile/android/base/resources/layout/sync_setup_failure.xml
@@ -11,23 +11,32 @@
   <ImageView
     style="@style/SyncTopIcon" />
   <TextView
     style="@style/SyncTextTitle"
     android:text="@string/sync_title_fail" />
   </LinearLayout>
 
   <TextView
+    android:id="@+id/failure_subtitle1"
     style="@style/SyncTextItem"
     android:layout_below="@id/failure_top"
-    android:layout_above="@+id/failure_bottom"
     android:padding="20dp"
     android:text="@string/sync_subtitle_fail" />
+
+  <TextView
+    android:id="@+id/failure_subtitle2"
+    style="@style/SyncTextItem"
+    android:layout_below="@id/failure_subtitle1"
+    android:paddingLeft="20dp"
+    android:paddingRight="20dp"
+    android:text="@string/sync_subtitle_failmultiple" />
+
   <LinearLayout
-    android:id="@id/failure_bottom"
+    android:id="@+id/failure_bottom"
     style="@style/SyncBottom"
     android:orientation="horizontal" >
 
     <Button
       style="@style/SyncButton"
       android:onClick="tryAgainClickHandler"
       android:text="@string/sync_button_tryagain" />
 
--- a/mobile/android/base/sync/setup/Constants.java
+++ b/mobile/android/base/sync/setup/Constants.java
@@ -32,18 +32,19 @@ public class Constants {
    * <p>
    * Corresponding value should be a String JSON-encoding an object, the keys of
    * which are the stage names to skip. For example:
    * <code>"{ \"stageToSkip\": 0 }"</code>.
    */
   public static final String EXTRAS_KEY_STAGES_TO_SKIP = "skip";
 
   // Constants for Activities.
-  public static final String INTENT_EXTRA_IS_SETUP = "isSetup";
-  public static final String INTENT_EXTRA_IS_PAIR  = "isPair";
+  public static final String INTENT_EXTRA_IS_SETUP        = "isSetup";
+  public static final String INTENT_EXTRA_IS_PAIR         = "isPair";
+  public static final String INTENT_EXTRA_IS_ACCOUNTERROR = "isAccountError";
 
   public static final int FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION =
     Intent.FLAG_ACTIVITY_REORDER_TO_FRONT |
     Intent.FLAG_ACTIVITY_NO_ANIMATION;
 
   // Constants for Account Authentication.
   public static final String AUTH_NODE_DEFAULT    = "https://auth.services.mozilla.com/";
   public static final String AUTH_NODE_PATHNAME   = "user/";
--- a/mobile/android/base/sync/setup/activities/AccountActivity.java
+++ b/mobile/android/base/sync/setup/activities/AccountActivity.java
@@ -248,20 +248,17 @@ public class AccountActivity extends Acc
       public void run() {
         Account account = SyncAccounts.createSyncAccount(syncAccount);
         boolean isSuccess = (account != null);
         if (!isSuccess) {
           setResult(RESULT_CANCELED);
           runOnUiThread(new Runnable() {
             @Override
             public void run() {
-              // Use default error.
-              // TODO: Bug 766499: Show specific error message when Android fails on Account creation.
-              Logger.debug(LOG_TAG, "displayFailure()");
-              displayFailure(AuthenticationResult.FAILURE_OTHER);
+              displayFailure(AuthenticationResult.FAILURE_ACCOUNT);
             }
           });
           return;
         }
 
         // Account created successfully.
         clearErrors();
 
@@ -289,32 +286,39 @@ public class AccountActivity extends Acc
       progressDialog.dismiss();
     }
   }
 
   private void displayFailure(final AuthenticationResult result) {
     runOnUiThread(new Runnable() {
       @Override
       public void run() {
+        Intent intent;
         switch (result) {
         case FAILURE_USERNAME:
           // No such username. Don't leak whether the username exists.
         case FAILURE_PASSWORD:
           findViewById(R.id.cred_error).setVisibility(View.VISIBLE);
           usernameInput.requestFocus();
           break;
         case FAILURE_SERVER:
           findViewById(R.id.server_error).setVisibility(View.VISIBLE);
           serverInput.requestFocus();
           break;
+        case FAILURE_ACCOUNT:
+          intent = new Intent(mContext, SetupFailureActivity.class);
+          intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
+          intent.putExtra(Constants.INTENT_EXTRA_IS_ACCOUNTERROR, true);
+          startActivity(intent);
+          break;
         case FAILURE_OTHER:
         default:
           // Display default error screen.
           Logger.debug(LOG_TAG, "displaying default failure.");
-          Intent intent = new Intent(mContext, SetupFailureActivity.class);
+          intent = new Intent(mContext, SetupFailureActivity.class);
           intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
           startActivity(intent);
         }
       }
     });
     return;
   }
 
--- a/mobile/android/base/sync/setup/activities/SetupFailureActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupFailureActivity.java
@@ -1,35 +1,53 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup.activities;
 
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.sync.setup.Constants;
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
+import android.widget.TextView;
 
 public class SetupFailureActivity extends Activity {
   private Context mContext;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
     setTheme(R.style.SyncTheme);
     super.onCreate(savedInstanceState);
     setContentView(R.layout.sync_setup_failure);
     mContext = this.getApplicationContext();
+
+    // Modify general error message if necessary.
+    Bundle extras = this.getIntent().getExtras();
+    if (extras != null) {
+      boolean isAccountError = extras.getBoolean(Constants.INTENT_EXTRA_IS_ACCOUNTERROR);
+      if (isAccountError) {
+        TextView subtitle1 = (TextView) findViewById(R.id.failure_subtitle1);
+        // Display error for multiple accounts.
+        // TODO: Remove when Bug 761206 is resolved (support for multiple versions).
+        TextView subtitle2 = (TextView) findViewById(R.id.failure_subtitle2);
+        subtitle1.setText(getString(R.string.sync_subtitle_failaccount));
+        subtitle2.setVisibility(View.VISIBLE);
+        subtitle2.setText(getString(R.string.sync_subtitle_failmultiple));
+      }
+    }
   }
 
   public void manualClickHandler(View target) {
     Intent intent = new Intent(mContext, AccountActivity.class);
+    intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
     startActivity(intent);
     overridePendingTransition(0, 0);
     finish();
   }
 
   public void tryAgainClickHandler(View target) {
     finish();
   }
--- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
@@ -74,16 +74,23 @@ public class SetupSyncActivity extends A
     setTheme(R.style.SyncTheme);
     Logger.info(LOG_TAG, "Called SetupSyncActivity.onCreate.");
     super.onCreate(savedInstanceState);
 
     // Set Activity variables.
     mContext = getApplicationContext();
     Logger.debug(LOG_TAG, "AccountManager.get(" + mContext + ")");
     mAccountManager = AccountManager.get(mContext);
+
+    // Set "screen on" flag for this activity. Screen will not automatically dim as long as this
+    // activity is at the top of the stack.
+    // Attempting to set this flag more than once causes hanging, so we set it here, not in onResume().
+    Window w = getWindow();
+    w.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    Logger.debug(LOG_TAG, "Successfully set screen-on flag.");
   }
 
   @Override
   public void onResume() {
     Logger.info(LOG_TAG, "Called SetupSyncActivity.onResume.");
     super.onResume();
 
     if (!hasInternet()) {
@@ -100,21 +107,16 @@ public class SetupSyncActivity extends A
         finishResume(accts);
       }
     });
   }
 
   public void finishResume(Account[] accts) {
     Logger.debug(LOG_TAG, "Finishing Resume after fetching accounts.");
 
-    // Set "screen on" flag.
-    Logger.debug(LOG_TAG, "Setting screen-on flag.");
-    Window w = getWindow();
-    w.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
     if (accts.length == 0) { // Start J-PAKE for pairing if no accounts present.
       Logger.debug(LOG_TAG, "No accounts; starting J-PAKE receiver.");
       displayReceiveNoPin();
       if (jClient != null) {
         // Mark previous J-PAKE as finished. Don't bother propagating back up to this Activity.
         jClient.finished = true;
       }
       jClient = new JPakeClient(this);
@@ -426,48 +428,53 @@ public class SetupSyncActivity extends A
           resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
           resultBundle.putString(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
           setAccountAuthenticatorResult(resultBundle);
         }
         displayResultAndFinish(isSuccess);
       }
     });
   }
+
   /*
    * Helper functions
    */
-
   private void activateButton(Button button, boolean toActivate) {
     button.setEnabled(toActivate);
     button.setClickable(toActivate);
   }
 
   private void enablePinEntry(boolean toEnable) {
     row1.setEnabled(toEnable);
     row2.setEnabled(toEnable);
     row3.setEnabled(toEnable);
   }
 
   /**
    * Displays Sync account setup result to user.
    *
    * @param isSetup
-   *          true is account was set up successfully, false otherwise.
+   *          true if account was set up successfully, false otherwise.
    */
   private void displayResult(boolean isSuccess) {
     Intent intent = null;
     if (isSuccess) {
       intent = new Intent(mContext, SetupSuccessActivity.class);
-    }  else {
+      intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
+      intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, !pairWithPin);
+      startActivity(intent);
+      finish();
+    } else {
       intent = new Intent(mContext, SetupFailureActivity.class);
+      intent.putExtra(Constants.INTENT_EXTRA_IS_ACCOUNTERROR, true);
+      intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
+      intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, !pairWithPin);
+      startActivity(intent);
+      // Do not finish, so user can retry setup by hitting "back."
     }
-    intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
-    intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, !pairWithPin);
-    startActivity(intent);
-    finish();
   }
 
   /**
    * Validate PIN entry fields to check if the three PIN entry fields are all
    * filled in.
    *
    * @return true, if all PIN fields have 4 characters, false otherwise
    */
--- a/mobile/android/base/sync/setup/auth/AuthenticationResult.java
+++ b/mobile/android/base/sync/setup/auth/AuthenticationResult.java
@@ -1,9 +1,9 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup.auth;
 
 public enum AuthenticationResult {
-  SUCCESS, FAILURE_USERNAME, FAILURE_PASSWORD, FAILURE_SERVER, FAILURE_OTHER
+  SUCCESS, FAILURE_USERNAME, FAILURE_PASSWORD, FAILURE_SERVER, FAILURE_ACCOUNT, FAILURE_OTHER
 }
--- a/mobile/android/sync/strings.xml.in
+++ b/mobile/android/sync/strings.xml.in
@@ -30,16 +30,18 @@
   <string name="sync_input_server">&sync.input.server.label;</string>
   
   <!-- Setup Fail -->
   <string name="sync_title_fail">&sync.title.fail.label;</string>
   <string name="sync_subtitle_fail">&sync.subtitle.fail.label;</string>
   <string name="sync_button_tryagain">&sync.button.tryagain.label;</string>
   <string name="sync_button_manual">&sync.button.manual.label;</string>
   <string name="sync_subtitle_nointernet">&sync.subtitle.nointernet.label;</string>
+  <string name="sync_subtitle_failaccount">&sync.subtitle.failaccount.label;</string>
+  <string name="sync_subtitle_failmultiple">&sync.subtitle.failmultiple.label;</string>
   
   <!-- Setup Success -->
   <string name="sync_title_success">&sync.title.success.label;</string>
   <string name="sync_subtitle_success">&sync.subtitle.success.label1;</string>
   <string name="sync_settings">&sync.settings.label;</string>
   <string name="sync_subtitle_manage">&sync.subtitle.manage.label1;</string>
   
   <!-- Pair Device -->