From 00ed51f5125908291ecdc9ecfd3db9d2f1f9278c Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Fri, 16 Jan 2015 17:37:20 -0800 Subject: [PATCH 1/6] Bug 1116912 - Don't hide the dynamic toolbar when it was originally shown but a tab was selected. r=wesj Additionally, rename mShowActionModeEndAnimation to make it more intuitive and clean up it's initialization. --- mobile/android/base/BrowserApp.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index bb382eaeba6..e648ac2ca30 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -187,7 +187,7 @@ public class BrowserApp extends GeckoApp private ViewGroup mHomePagerContainer; protected Telemetry.Timer mAboutHomeStartupTimer; private ActionModeCompat mActionMode; - private boolean mShowActionModeEndAnimation; + private boolean mHideDynamicToolbarOnActionModeEnd; private TabHistoryController tabHistoryController; private static final int GECKO_TOOLS_MENU = -1; @@ -294,6 +294,8 @@ public class BrowserApp extends GeckoApp if (Tabs.getInstance().isSelectedTab(tab)) { updateHomePagerForTab(tab); } + + mHideDynamicToolbarOnActionModeEnd = false; break; case START: if (Tabs.getInstance().isSelectedTab(tab)) { @@ -3322,10 +3324,11 @@ public class BrowserApp extends GeckoApp if (mDynamicToolbar.isEnabled() && !margins.areMarginsShown()) { margins.setMaxMargins(0, mBrowserChrome.getHeight(), 0, 0); mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE); - mShowActionModeEndAnimation = true; + mHideDynamicToolbarOnActionModeEnd = true; } else { // Otherwise, we animate the actionbar itself mActionBar.animateIn(); + mHideDynamicToolbarOnActionModeEnd = false; } mDynamicToolbar.setPinned(true, PinReason.ACTION_MODE); @@ -3355,9 +3358,8 @@ public class BrowserApp extends GeckoApp // Only slide the urlbar out if it was hidden when the action mode started // Don't animate hiding it so that there's no flash as we switch back to url mode - if (mShowActionModeEndAnimation) { + if (mHideDynamicToolbarOnActionModeEnd) { mDynamicToolbar.setVisible(false, VisibilityTransition.IMMEDIATE); - mShowActionModeEndAnimation = false; } } From c1b9f4a6e5067cf7a5eb7a18275393cdc41e4860 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Sat, 17 Jan 2015 00:21:21 +0000 Subject: [PATCH 2/6] Bug 1120236 - fix autocomplete in case search bar doesn't exist, r=florian --- browser/base/content/urlbarBindings.xml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 0e9caeafc1c..eb6226f5654 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -924,13 +924,16 @@ var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController); - // Check for unmodified left-click, and use default behavior var searchBar = BrowserSearch.searchBar; - searchBar.telemetrySearchDetails = { - index: controller.selection.currentIndex, - kind: "mouse" - }; + var popupForSearchBar = searchBar && searchBar.textbox == this.mInput; + if (popupForSearchBar) { + searchBar.telemetrySearchDetails = { + index: controller.selection.currentIndex, + kind: "mouse" + }; + } + // Check for unmodified left-click, and use default behavior if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey && !aEvent.altKey && !aEvent.metaKey) { controller.handleEnter(true); @@ -938,7 +941,7 @@ } // Check for middle-click or modified clicks on the search bar - if (searchBar && searchBar.textbox == this.mInput) { + if (popupForSearchBar) { // Handle search bar popup clicks var search = controller.getValueAt(this.selectedIndex); From 69ac0831c489060517acc3ca46259f0c1b505547 Mon Sep 17 00:00:00 2001 From: Archaeopteryx Date: Thu, 15 Jan 2015 10:53:17 -0800 Subject: [PATCH 3/6] Bug 1121610 - Change WiFi -> Wi-Fi. r=nalexander ======== https://github.com/mozilla-services/android-sync/commit/5e9476fa2a3e278024c4f036ca8f71362683ac55 Author: Archaeopteryx Bug 1121610 - WiFi -> Wi-Fi --- mobile/android/base/locales/en-US/sync_strings.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/locales/en-US/sync_strings.dtd b/mobile/android/base/locales/en-US/sync_strings.dtd index 07a00d07510..cca0b7ece3a 100644 --- a/mobile/android/base/locales/en-US/sync_strings.dtd +++ b/mobile/android/base/locales/en-US/sync_strings.dtd @@ -191,7 +191,7 @@ - + From 134c94d133b18c34ab24098e0b7aaa2d7d9ae369 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Fri, 16 Jan 2015 17:42:29 -0800 Subject: [PATCH 4/6] Bug 1119070 - Add migration=sync11 query parameter to post-migration /account/login. r=rnewman ======== https://github.com/mozilla-services/android-sync/commit/fb5159ea46d59164e21b0a21dbb953c4386dfcb4 Author: Nick Alexander Date: Mon Jan 12 15:01:22 2015 -0800 Bug 1119070 - Part 3: Re-instate service=sync; add migration=sync11. ======== https://github.com/mozilla-services/android-sync/commit/00ab8e45e0261799ee35fad1a7a3486ecceecb5c Author: Nick Alexander Date: Mon Jan 12 14:23:32 2015 -0800 Bug 1119070 - Part 2: Thread query parameters through to relevant API calls. ======== https://github.com/mozilla-services/android-sync/commit/b4029585aac5cc07f17027b804295258f8390c78 Author: Nick Alexander Date: Mon Jan 12 12:46:22 2015 -0800 Bug 1119070 - Part 1: Extract uniform getBaseResource. --- .../base/background/fxa/FxAccountClient.java | 6 +- .../background/fxa/FxAccountClient10.java | 84 ++++++++++++++----- .../background/fxa/FxAccountClient20.java | 68 +++++++-------- .../FxAccountAbstractSetupActivity.java | 7 ++ ...ountAbstractUpdateCredentialsActivity.java | 2 +- .../FxAccountCreateAccountActivity.java | 2 +- .../FxAccountFinishMigratingActivity.java | 9 ++ .../activities/FxAccountSignInActivity.java | 2 +- .../base/fxa/tasks/FxAccountCodeResender.java | 3 +- .../fxa/tasks/FxAccountCreateAccountTask.java | 7 +- .../base/fxa/tasks/FxAccountSetupTask.java | 6 +- .../base/fxa/tasks/FxAccountSignInTask.java | 7 +- .../tasks/FxAccountUnlockCodeResender.java | 2 +- 13 files changed, 135 insertions(+), 70 deletions(-) diff --git a/mobile/android/base/background/fxa/FxAccountClient.java b/mobile/android/base/background/fxa/FxAccountClient.java index 0d71369a7a8..6d16f073f12 100644 --- a/mobile/android/base/background/fxa/FxAccountClient.java +++ b/mobile/android/base/background/fxa/FxAccountClient.java @@ -4,6 +4,8 @@ package org.mozilla.gecko.background.fxa; +import java.util.Map; + import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate; import org.mozilla.gecko.background.fxa.FxAccountClient10.StatusResponse; import org.mozilla.gecko.background.fxa.FxAccountClient10.TwoKeys; @@ -11,8 +13,8 @@ import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse; import org.mozilla.gecko.sync.ExtendedJSONObject; public interface FxAccountClient { - public void createAccountAndGetKeys(final byte[] emailUTF8, final PasswordStretcher passwordStretcher, final RequestDelegate delegate); - public void loginAndGetKeys(final byte[] emailUTF8, final PasswordStretcher passwordStretcher, final RequestDelegate requestDelegate); + public void createAccountAndGetKeys(final byte[] emailUTF8, final PasswordStretcher passwordStretcher, final Map queryParameters, final RequestDelegate delegate); + public void loginAndGetKeys(final byte[] emailUTF8, final PasswordStretcher passwordStretcher, final Map queryParameters, final RequestDelegate requestDelegate); public void status(byte[] sessionToken, RequestDelegate requestDelegate); public void keys(byte[] keyFetchToken, RequestDelegate requestDelegate); public void sign(byte[] sessionToken, ExtendedJSONObject publicKey, long certificateDurationInMilliseconds, RequestDelegate requestDelegate); diff --git a/mobile/android/base/background/fxa/FxAccountClient10.java b/mobile/android/base/background/fxa/FxAccountClient10.java index ccf5279168e..5ed1ffcc0c4 100644 --- a/mobile/android/base/background/fxa/FxAccountClient10.java +++ b/mobile/android/base/background/fxa/FxAccountClient10.java @@ -8,11 +8,14 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.Executor; import javax.crypto.Mac; @@ -71,7 +74,6 @@ public class FxAccountClient10 { public static final String JSON_KEY_CODE = "code"; public static final String JSON_KEY_ERRNO = "errno"; - protected static final String[] requiredErrorStringFields = { JSON_KEY_ERROR, JSON_KEY_MESSAGE, JSON_KEY_INFO }; protected static final String[] requiredErrorLongFields = { JSON_KEY_CODE, JSON_KEY_ERRNO }; @@ -99,6 +101,48 @@ public class FxAccountClient10 { this.executor = executor; } + protected BaseResource getBaseResource(String path, Map queryParameters) throws UnsupportedEncodingException, URISyntaxException { + if (queryParameters == null || queryParameters.isEmpty()) { + return getBaseResource(path); + } + final String[] array = new String[2 * queryParameters.size()]; + int i = 0; + for (Entry entry : queryParameters.entrySet()) { + array[i++] = entry.getKey(); + array[i++] = entry.getValue(); + } + return getBaseResource(path, array); + } + + /** + * Create BaseResource, encoding query parameters carefully. + *

+ * This is equivalent to android.net.Uri.Builder, which is not + * present in our JUnit 4 tests. + * + * @param path fragment. + * @param queryParameters list of key/value query parameter pairs. Must be even length! + * @return BaseResource + * @throws URISyntaxException + * @throws UnsupportedEncodingException + */ + protected BaseResource getBaseResource(String path, String... queryParameters) throws URISyntaxException, UnsupportedEncodingException { + final StringBuilder sb = new StringBuilder(serverURI); + sb.append(path); + if (queryParameters != null) { + int i = 0; + while (i < queryParameters.length) { + sb.append(i > 0 ? "&" : "?"); + final String key = queryParameters[i++]; + final String val = queryParameters[i++]; + sb.append(URLEncoder.encode(key, "UTF-8")); + sb.append("="); + sb.append(URLEncoder.encode(val, "UTF-8")); + } + } + return new BaseResource(new URI(sb.toString())); + } + /** * Process a typed value extracted from a successful response (in an * endpoint-dependent way). @@ -353,8 +397,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "account/create")); - } catch (URISyntaxException e) { + resource = getBaseResource("account/create"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -384,8 +428,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "auth/start")); - } catch (URISyntaxException e) { + resource = getBaseResource("auth/start"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -416,8 +460,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "auth/finish")); - } catch (URISyntaxException e) { + resource = getBaseResource("auth/finish"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -480,8 +524,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "session/create")); - } catch (URISyntaxException e) { + resource = getBaseResource("session/create"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -516,8 +560,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "session/destroy")); - } catch (URISyntaxException e) { + resource = getBaseResource("session/destroy"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -605,8 +649,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "account/keys")); - } catch (URISyntaxException e) { + resource = getBaseResource("account/keys"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -667,8 +711,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "recovery_email/status")); - } catch (URISyntaxException e) { + resource = getBaseResource("recovery_email/status"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -709,8 +753,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "certificate/sign")); - } catch (URISyntaxException e) { + resource = getBaseResource("certificate/sign"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -750,8 +794,8 @@ public class FxAccountClient10 { BaseResource resource; try { - resource = new BaseResource(new URI(serverURI + "recovery_email/resend_code")); - } catch (URISyntaxException e) { + resource = getBaseResource("recovery_email/resend_code"); + } catch (URISyntaxException | UnsupportedEncodingException e) { invokeHandleError(delegate, e); return; } @@ -788,7 +832,7 @@ public class FxAccountClient10 { final BaseResource resource; final JSONObject body = new JSONObject(); try { - resource = new BaseResource(new URI(serverURI + "account/unlock/resend_code")); + resource = getBaseResource("account/unlock/resend_code"); body.put("email", new String(emailUTF8, "UTF-8")); } catch (URISyntaxException e) { invokeHandleError(delegate, e); diff --git a/mobile/android/base/background/fxa/FxAccountClient20.java b/mobile/android/base/background/fxa/FxAccountClient20.java index e8524d9727f..52b6e42c955 100644 --- a/mobile/android/base/background/fxa/FxAccountClient20.java +++ b/mobile/android/base/background/fxa/FxAccountClient20.java @@ -4,10 +4,8 @@ package org.mozilla.gecko.background.fxa; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Executor; import org.json.simple.JSONObject; @@ -53,12 +51,20 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli // Public for testing only; prefer login and loginAndGetKeys (without boolean parameter). public void login(final byte[] emailUTF8, final byte[] quickStretchedPW, final boolean getKeys, + final Map queryParameters, final RequestDelegate delegate) { - BaseResource resource; - JSONObject body; - final String path = getKeys ? "account/login?keys=true" : "account/login"; + final BaseResource resource; + final JSONObject body; try { - resource = new BaseResource(new URI(serverURI + path)); + final String path = "account/login"; + final Map modifiedParameters = new HashMap<>(); + if (queryParameters != null) { + modifiedParameters.putAll(queryParameters); + } + if (getKeys) { + modifiedParameters.put("keys", "true"); + } + resource = getBaseResource(path, modifiedParameters); body = new FxAccount20LoginDelegate(emailUTF8, quickStretchedPW).getCreateBody(); } catch (Exception e) { invokeHandleError(delegate, e); @@ -96,35 +102,23 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli post(resource, body, delegate); } - /** - * Create account/create URI, encoding query parameters carefully. - *

- * This is equivalent to android.net.Uri.Builder, which is not - * present in our JUnit 4 tests. - */ - protected URI getCreateAccountURI(final boolean getKeys, final String service) throws UnsupportedEncodingException, URISyntaxException { - if (service == null) { - throw new IllegalArgumentException("service must not be null"); - } - final StringBuilder sb = new StringBuilder(serverURI); // serverURI always has a trailing slash. - sb.append("account/create?service="); - // Be very careful that query parameters are encoded correctly! - sb.append(URLEncoder.encode(service, "UTF-8")); - if (getKeys) { - sb.append("&keys=true"); - } - return new URI(sb.toString()); - } - public void createAccount(final byte[] emailUTF8, final byte[] quickStretchedPW, final boolean getKeys, final boolean preVerified, - final String service, + final Map queryParameters, final RequestDelegate delegate) { final BaseResource resource; final JSONObject body; try { - resource = new BaseResource(getCreateAccountURI(getKeys, service)); + final String path = "account/create"; + final Map modifiedParameters = new HashMap<>(); + if (queryParameters != null) { + modifiedParameters.putAll(queryParameters); + } + if (getKeys) { + modifiedParameters.put("keys", "true"); + } + resource = getBaseResource(path, modifiedParameters); body = new FxAccount20CreateDelegate(emailUTF8, quickStretchedPW, preVerified).getCreateBody(); } catch (Exception e) { invokeHandleError(delegate, e); @@ -163,18 +157,18 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli } @Override - public void createAccountAndGetKeys(byte[] emailUTF8, PasswordStretcher passwordStretcher, RequestDelegate delegate) { + public void createAccountAndGetKeys(byte[] emailUTF8, PasswordStretcher passwordStretcher, final Map queryParameters, RequestDelegate delegate) { try { byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(emailUTF8); - createAccount(emailUTF8, quickStretchedPW, true, false, "sync", delegate); + createAccount(emailUTF8, quickStretchedPW, true, false, queryParameters, delegate); } catch (Exception e) { invokeHandleError(delegate, e); } } @Override - public void loginAndGetKeys(byte[] emailUTF8, PasswordStretcher passwordStretcher, RequestDelegate delegate) { - login(emailUTF8, passwordStretcher, true, delegate); + public void loginAndGetKeys(byte[] emailUTF8, PasswordStretcher passwordStretcher, final Map queryParameters, RequestDelegate delegate) { + login(emailUTF8, passwordStretcher, true, queryParameters, delegate); } /** @@ -198,10 +192,12 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli * @param getKeys * true if a keyFetchToken should be returned (in * addition to the standard sessionToken). + * @param queryParameters * @param delegate * to invoke callbacks. */ public void login(final byte[] emailUTF8, final PasswordStretcher stretcher, final boolean getKeys, + final Map queryParameters, final RequestDelegate delegate) { byte[] quickStretchedPW; try { @@ -212,7 +208,7 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli return; } - this.login(emailUTF8, quickStretchedPW, getKeys, new RequestDelegate() { + this.login(emailUTF8, quickStretchedPW, getKeys, queryParameters, new RequestDelegate() { @Override public void handleSuccess(LoginResponse result) { delegate.handleSuccess(result); @@ -239,7 +235,7 @@ public class FxAccountClient20 extends FxAccountClient10 implements FxAccountCli // signature here, which invokes a non-retrying version. byte[] alternateEmailUTF8 = alternateEmail.getBytes("UTF-8"); byte[] alternateQuickStretchedPW = stretcher.getQuickStretchedPW(alternateEmailUTF8); - login(alternateEmailUTF8, alternateQuickStretchedPW, getKeys, delegate); + login(alternateEmailUTF8, alternateQuickStretchedPW, getKeys, queryParameters, delegate); } catch (Exception innerException) { delegate.handleError(innerException); return; diff --git a/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java b/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java index 24c87764586..b878b4673e7 100644 --- a/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java @@ -7,6 +7,7 @@ package org.mozilla.gecko.fxa.activities; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -565,4 +566,10 @@ abstract public class FxAccountAbstractSetupActivity extends FxAccountAbstractAc ensureFindViewById(null, R.id.account_server_layout, "account server layout").setVisibility(visibility); ensureFindViewById(null, R.id.sync_server_layout, "sync server layout").setVisibility(visibility); } + + protected Map getQueryParameters() { + final Map queryParameters = new HashMap<>(); + queryParameters.put("service", "sync"); + return queryParameters; + } } diff --git a/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java b/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java index 2283d089b6b..a97675b46c1 100644 --- a/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java @@ -161,7 +161,7 @@ public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccou try { hideRemoteError(); RequestDelegate delegate = new UpdateCredentialsDelegate(email, passwordStretcher, serverURI); - new FxAccountSignInTask(this, this, email, passwordStretcher, client, delegate).execute(); + new FxAccountSignInTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute(); } catch (Exception e) { Logger.warn(LOG_TAG, "Got exception updating credentials for account.", e); showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error); diff --git a/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java b/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java index e82c92fdc84..10416368043 100644 --- a/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java @@ -221,7 +221,7 @@ public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivi FxAccountClient client = new FxAccountClient20(serverURI, executor); try { hideRemoteError(); - new FxAccountCreateAccountTask(this, this, email, passwordStretcher, client, delegate).execute(); + new FxAccountCreateAccountTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute(); } catch (Exception e) { showRemoteError(e, R.string.fxaccount_create_account_unknown_error); } diff --git a/mobile/android/base/fxa/activities/FxAccountFinishMigratingActivity.java b/mobile/android/base/fxa/activities/FxAccountFinishMigratingActivity.java index aee43d6bd6e..4dd0f03370b 100644 --- a/mobile/android/base/fxa/activities/FxAccountFinishMigratingActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountFinishMigratingActivity.java @@ -4,6 +4,8 @@ package org.mozilla.gecko.fxa.activities; +import java.util.Map; + import org.mozilla.gecko.R; import org.mozilla.gecko.background.common.log.Logger; import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse; @@ -51,4 +53,11 @@ public class FxAccountFinishMigratingActivity extends FxAccountAbstractUpdateCre successIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); return successIntent; } + + @Override + protected Map getQueryParameters() { + final Map queryParameters = super.getQueryParameters(); + queryParameters.put("migration", "sync11"); + return queryParameters; + } } diff --git a/mobile/android/base/fxa/activities/FxAccountSignInActivity.java b/mobile/android/base/fxa/activities/FxAccountSignInActivity.java index 24404efc6f2..f9a419668ef 100644 --- a/mobile/android/base/fxa/activities/FxAccountSignInActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountSignInActivity.java @@ -111,7 +111,7 @@ public class FxAccountSignInActivity extends FxAccountAbstractSetupActivity { FxAccountClient client = new FxAccountClient20(serverURI, executor); try { hideRemoteError(); - new FxAccountSignInTask(this, this, email, passwordStretcher, client, delegate).execute(); + new FxAccountSignInTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute(); } catch (Exception e) { showRemoteError(e, R.string.fxaccount_sign_in_unknown_error); } diff --git a/mobile/android/base/fxa/tasks/FxAccountCodeResender.java b/mobile/android/base/fxa/tasks/FxAccountCodeResender.java index 538513398b5..d98e97f0804 100644 --- a/mobile/android/base/fxa/tasks/FxAccountCodeResender.java +++ b/mobile/android/base/fxa/tasks/FxAccountCodeResender.java @@ -17,6 +17,7 @@ import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount; import org.mozilla.gecko.fxa.login.Engaged; import android.content.Context; +import android.os.AsyncTask; import android.widget.Toast; /** @@ -32,7 +33,7 @@ public class FxAccountCodeResender { protected final byte[] sessionToken; public FxAccountResendCodeTask(Context context, byte[] sessionToken, FxAccountClient client, RequestDelegate delegate) { - super(context, null, client, delegate); + super(context, null, client, null, delegate); this.sessionToken = sessionToken; } diff --git a/mobile/android/base/fxa/tasks/FxAccountCreateAccountTask.java b/mobile/android/base/fxa/tasks/FxAccountCreateAccountTask.java index 7441f233d97..cf1c74e9490 100644 --- a/mobile/android/base/fxa/tasks/FxAccountCreateAccountTask.java +++ b/mobile/android/base/fxa/tasks/FxAccountCreateAccountTask.java @@ -5,6 +5,7 @@ package org.mozilla.gecko.fxa.tasks; import java.io.UnsupportedEncodingException; +import java.util.Map; import org.mozilla.gecko.background.common.log.Logger; import org.mozilla.gecko.background.fxa.FxAccountClient; @@ -20,8 +21,8 @@ public class FxAccountCreateAccountTask extends FxAccountSetupTask delegate) throws UnsupportedEncodingException { - super(context, progressDisplay, client, delegate); + public FxAccountCreateAccountTask(Context context, ProgressDisplay progressDisplay, String email, PasswordStretcher passwordStretcher, FxAccountClient client, Map queryParameters, RequestDelegate delegate) throws UnsupportedEncodingException { + super(context, progressDisplay, client, queryParameters, delegate); this.emailUTF8 = email.getBytes("UTF-8"); this.passwordStretcher = passwordStretcher; } @@ -29,7 +30,7 @@ public class FxAccountCreateAccountTask extends FxAccountSetupTask doInBackground(Void... arg0) { try { - client.createAccountAndGetKeys(emailUTF8, passwordStretcher, innerDelegate); + client.createAccountAndGetKeys(emailUTF8, passwordStretcher, queryParameters, innerDelegate); latch.await(); return innerDelegate; } catch (Exception e) { diff --git a/mobile/android/base/fxa/tasks/FxAccountSetupTask.java b/mobile/android/base/fxa/tasks/FxAccountSetupTask.java index aa2b5324dab..c5c9c429c28 100644 --- a/mobile/android/base/fxa/tasks/FxAccountSetupTask.java +++ b/mobile/android/base/fxa/tasks/FxAccountSetupTask.java @@ -4,6 +4,7 @@ package org.mozilla.gecko.fxa.tasks; +import java.util.Map; import java.util.concurrent.CountDownLatch; import org.mozilla.gecko.background.common.log.Logger; @@ -43,13 +44,16 @@ public abstract class FxAccountSetupTask extends AsyncTask innerDelegate = new InnerRequestDelegate(latch); + protected final Map queryParameters; + protected final RequestDelegate delegate; - public FxAccountSetupTask(Context context, ProgressDisplay progressDisplay, FxAccountClient client, RequestDelegate delegate) { + public FxAccountSetupTask(Context context, ProgressDisplay progressDisplay, FxAccountClient client, Map queryParameters, RequestDelegate delegate) { this.context = context; this.client = client; this.delegate = delegate; this.progressDisplay = progressDisplay; + this.queryParameters = queryParameters; } @Override diff --git a/mobile/android/base/fxa/tasks/FxAccountSignInTask.java b/mobile/android/base/fxa/tasks/FxAccountSignInTask.java index e683989c7a8..dd5ae0d5e93 100644 --- a/mobile/android/base/fxa/tasks/FxAccountSignInTask.java +++ b/mobile/android/base/fxa/tasks/FxAccountSignInTask.java @@ -5,6 +5,7 @@ package org.mozilla.gecko.fxa.tasks; import java.io.UnsupportedEncodingException; +import java.util.Map; import org.mozilla.gecko.background.common.log.Logger; import org.mozilla.gecko.background.fxa.FxAccountClient; @@ -20,8 +21,8 @@ public class FxAccountSignInTask extends FxAccountSetupTask { protected final byte[] emailUTF8; protected final PasswordStretcher passwordStretcher; - public FxAccountSignInTask(Context context, ProgressDisplay progressDisplay, String email, PasswordStretcher passwordStretcher, FxAccountClient client, RequestDelegate delegate) throws UnsupportedEncodingException { - super(context, progressDisplay, client, delegate); + public FxAccountSignInTask(Context context, ProgressDisplay progressDisplay, String email, PasswordStretcher passwordStretcher, FxAccountClient client, Map queryParameters, RequestDelegate delegate) throws UnsupportedEncodingException { + super(context, progressDisplay, client, queryParameters, delegate); this.emailUTF8 = email.getBytes("UTF-8"); this.passwordStretcher = passwordStretcher; } @@ -29,7 +30,7 @@ public class FxAccountSignInTask extends FxAccountSetupTask { @Override protected InnerRequestDelegate doInBackground(Void... arg0) { try { - client.loginAndGetKeys(emailUTF8, passwordStretcher, innerDelegate); + client.loginAndGetKeys(emailUTF8, passwordStretcher, queryParameters, innerDelegate); latch.await(); return innerDelegate; } catch (Exception e) { diff --git a/mobile/android/base/fxa/tasks/FxAccountUnlockCodeResender.java b/mobile/android/base/fxa/tasks/FxAccountUnlockCodeResender.java index b10ab81b05d..0f32f3e2227 100644 --- a/mobile/android/base/fxa/tasks/FxAccountUnlockCodeResender.java +++ b/mobile/android/base/fxa/tasks/FxAccountUnlockCodeResender.java @@ -31,7 +31,7 @@ public class FxAccountUnlockCodeResender { protected final byte[] emailUTF8; public FxAccountUnlockCodeTask(Context context, byte[] emailUTF8, FxAccountClient client, RequestDelegate delegate) { - super(context, null, client, delegate); + super(context, null, client, null, delegate); this.emailUTF8 = emailUTF8; } From 9a59a3ea44b85de4e2ace1756866a1254ddc0ab9 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Fri, 16 Jan 2015 17:38:28 -0800 Subject: [PATCH 5/6] Bug 1119061 - Part 1: Add Fennec-specific Sync 1.1 -> Sync 1.5 migration telemetry histograms. r=rnewman The exponential histogram FENNEC_SYNC11_MIGRATION_NOTIFICATIONS_OFFERED is triggered every time the Android device tries to sync from the Sync11Migrated state. Therefore, the notification offered may be (transparently) replacing an existing notification; it doesn't necessarily mean we're nagging the user after dismissal. --- toolkit/components/telemetry/Histograms.json | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index a231115ff62..449afd05475 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -7157,5 +7157,32 @@ "n_buckets" : 50, "extended_statistics_ok": true, "description": "The number of saved signons in storage" + }, + "FENNEC_SYNC11_MIGRATION_SENTINELS_SEEN": { + "expires_in_version": "45", + "kind": "count", + "description": "The number of Sync 1.1 -> Sync 1.5 migration sentinels seen by Android Sync." + }, + "FENNEC_SYNC11_MIGRATIONS_FAILED": { + "expires_in_version": "45", + "kind": "count", + "description": "The number of Sync 1.1 -> Sync 1.5 migrations that failed during Android Sync." + }, + "FENNEC_SYNC11_MIGRATIONS_SUCCEEDED": { + "expires_in_version": "45", + "kind": "count", + "description": "The number of Sync 1.1 -> Sync 1.5 migrations that succeeded during Android Sync." + }, + "FENNEC_SYNC11_MIGRATION_NOTIFICATIONS_OFFERED": { + "expires_in_version": "45", + "kind": "exponential", + "high": 500, + "n_buckets": 5, + "description": "The number of Sync 1.5 'complete upgrade/migration' notifications offered by Android Sync." + }, + "FENNEC_SYNC11_MIGRATIONS_COMPLETED": { + "expires_in_version": "45", + "kind": "count", + "description": "The number of Sync 1.5 migrations completed by Android Sync." } } From e32ad2f1ac1c753f3145f2cae873a8a5623be8f4 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Fri, 16 Jan 2015 17:42:34 -0800 Subject: [PATCH 6/6] Bug 1119061 - Part 2: Add Sync 1.1 -> Sync 1.5 migration telemetry. r=rnewman ======== https://github.com/mozilla-services/android-sync/commit/f7eaef78c18b75f4e03b1f2d897de8de72474399 Author: Nick Alexander Date: Wed Jan 14 17:36:29 2015 -0800 Bug 1119061 - Part 2: Add Sync 1.1 to Sync 1.5 migration telemetry. ======== https://github.com/mozilla-services/android-sync/commit/e64f9687038a9198a0c67d80d328f08be235311c Author: Nick Alexander Date: Mon Jan 12 16:30:09 2015 -0800 Bug 1119061 - Part 1: Add TelemetryWrapper. This is cribbed, more or less directly, from the stumbler. ======== https://github.com/mozilla-services/android-sync/commit/51299e74e4e7b9f3228ff163ed2566cca9efcd3a Author: Nick Alexander Date: Mon Jan 12 17:26:41 2015 -0800 Bug 1119061 - Pre: Clear Firefox Account notifications when Android Account is removed. --- mobile/android/base/android-services.mozbuild | 2 + .../common/telemetry/TelemetryWrapper.java | 56 +++++++++++++++++++ ...ountAbstractUpdateCredentialsActivity.java | 4 ++ .../receivers/FxAccountDeletedService.java | 5 ++ .../sync/FxAccountNotificationManager.java | 15 +++++ .../base/fxa/sync/FxAccountSyncAdapter.java | 2 +- .../base/sync/MigrationSentinelSyncStage.java | 7 +++ .../sync/telemetry/TelemetryContract.java | 48 ++++++++++++++++ 8 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 mobile/android/base/background/common/telemetry/TelemetryWrapper.java create mode 100644 mobile/android/base/sync/telemetry/TelemetryContract.java diff --git a/mobile/android/base/android-services.mozbuild b/mobile/android/base/android-services.mozbuild index dbb1454ec59..f6eb74a4a18 100644 --- a/mobile/android/base/android-services.mozbuild +++ b/mobile/android/base/android-services.mozbuild @@ -780,6 +780,7 @@ sync_java_files = [ 'background/common/log/writers/StringLogWriter.java', 'background/common/log/writers/TagLogWriter.java', 'background/common/log/writers/ThreadLocalTagLogWriter.java', + 'background/common/telemetry/TelemetryWrapper.java', 'background/datareporting/TelemetryRecorder.java', 'background/db/CursorDumper.java', 'background/db/Tab.java', @@ -1132,6 +1133,7 @@ sync_java_files = [ 'sync/synchronizer/UnbundleError.java', 'sync/synchronizer/UnexpectedSessionException.java', 'sync/SynchronizerConfiguration.java', + 'sync/telemetry/TelemetryContract.java', 'sync/ThreadPool.java', 'sync/UnexpectedJSONException.java', 'sync/UnknownSynchronizerConfigurationVersionException.java', diff --git a/mobile/android/base/background/common/telemetry/TelemetryWrapper.java b/mobile/android/base/background/common/telemetry/TelemetryWrapper.java new file mode 100644 index 00000000000..6639b817d51 --- /dev/null +++ b/mobile/android/base/background/common/telemetry/TelemetryWrapper.java @@ -0,0 +1,56 @@ +/* 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.background.common.telemetry; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.mozilla.gecko.background.common.log.Logger; + +/** + * Android Background Services are normally built into Fennec, but can also be + * built as a stand-alone APK for rapid local development. The current Telemetry + * implementation is coupled to Gecko, and Background Services should not + * interact with Gecko directly. To maintain this independence, Background + * Services lazily introspects the relevant Telemetry class from the enclosing + * package, warning but otherwise ignoring failures during introspection or + * invocation. + *

+ * It is possible that Background Services will introspect and invoke the + * Telemetry implementation while Gecko is not running. In this case, the Fennec + * process itself buffers Telemetry events until such time as they can be + * flushed to disk and uploaded. There is no guarantee that all Telemetry + * events will be uploaded! Depending on the volume of data and the + * application lifecycle, Telemetry events may be dropped. + */ +public class TelemetryWrapper { + private static final String LOG_TAG = TelemetryWrapper.class.getSimpleName(); + + // Marking this volatile maintains thread safety cheaply. + private static volatile Method mAddToHistogram; + + public static void addToHistogram(String key, int value) { + if (mAddToHistogram == null) { + try { + final Class telemetry = Class.forName("org.mozilla.gecko.Telemetry"); + mAddToHistogram = telemetry.getMethod("addToHistogram", String.class, int.class); + } catch (ClassNotFoundException e) { + Logger.warn(LOG_TAG, "org.mozilla.gecko.Telemetry class found!"); + return; + } catch (NoSuchMethodException e) { + Logger.warn(LOG_TAG, "org.mozilla.gecko.Telemetry.addToHistogram(String, int) method not found!"); + return; + } + } + + if (mAddToHistogram != null) { + try { + mAddToHistogram.invoke(null, key, value); + } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { + Logger.warn(LOG_TAG, "Got exception invoking telemetry!"); + } + } + } +} diff --git a/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java b/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java index a97675b46c1..c0a8e6d6781 100644 --- a/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java +++ b/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java @@ -9,6 +9,7 @@ import java.util.concurrent.Executors; import org.mozilla.gecko.R; import org.mozilla.gecko.background.common.log.Logger; +import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper; import org.mozilla.gecko.background.fxa.FxAccountClient; import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate; import org.mozilla.gecko.background.fxa.FxAccountClient20; @@ -22,6 +23,7 @@ import org.mozilla.gecko.fxa.login.Engaged; import org.mozilla.gecko.fxa.login.State; import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask; import org.mozilla.gecko.sync.setup.activities.ActivityUtils; +import org.mozilla.gecko.sync.telemetry.TelemetryContract; import android.content.Intent; import android.os.Bundle; @@ -150,6 +152,8 @@ public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccou startActivity(successIntent); } finish(); + + TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_COMPLETED, 1); } } diff --git a/mobile/android/base/fxa/receivers/FxAccountDeletedService.java b/mobile/android/base/fxa/receivers/FxAccountDeletedService.java index c9ef08a94ac..14768cfb1e7 100644 --- a/mobile/android/base/fxa/receivers/FxAccountDeletedService.java +++ b/mobile/android/base/fxa/receivers/FxAccountDeletedService.java @@ -6,6 +6,8 @@ package org.mozilla.gecko.fxa.receivers; import org.mozilla.gecko.background.common.log.Logger; import org.mozilla.gecko.fxa.FxAccountConstants; +import org.mozilla.gecko.fxa.sync.FxAccountNotificationManager; +import org.mozilla.gecko.fxa.sync.FxAccountSyncAdapter; import org.mozilla.gecko.sync.config.AccountPickler; import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository; @@ -63,6 +65,9 @@ public class FxAccountDeletedService extends IntentService { // Delete client database and non-local tabs. Logger.info(LOG_TAG, "Deleting the entire clients database and non-local tabs"); FennecTabsRepository.deleteNonLocalClientsAndTabs(context); + + // Remove any displayed notifications. + new FxAccountNotificationManager(FxAccountSyncAdapter.NOTIFICATION_ID).clear(context); } public static void deletePickle(final Context context) { diff --git a/mobile/android/base/fxa/sync/FxAccountNotificationManager.java b/mobile/android/base/fxa/sync/FxAccountNotificationManager.java index 8044ba44a28..f467df8f9ed 100644 --- a/mobile/android/base/fxa/sync/FxAccountNotificationManager.java +++ b/mobile/android/base/fxa/sync/FxAccountNotificationManager.java @@ -7,12 +7,14 @@ package org.mozilla.gecko.fxa.sync; import org.mozilla.gecko.BrowserLocaleManager; import org.mozilla.gecko.R; import org.mozilla.gecko.background.common.log.Logger; +import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper; import org.mozilla.gecko.background.fxa.FxAccountUtils; import org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity; import org.mozilla.gecko.fxa.activities.FxAccountStatusActivity; import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount; import org.mozilla.gecko.fxa.login.State; import org.mozilla.gecko.fxa.login.State.Action; +import org.mozilla.gecko.sync.telemetry.TelemetryContract; import android.app.NotificationManager; import android.app.PendingIntent; @@ -43,6 +45,17 @@ public class FxAccountNotificationManager { this.notificationId = notificationId; } + /** + * Remove all Firefox Account related notifications from the notification manager. + * + * @param context + * Android context. + */ + public void clear(Context context) { + final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(notificationId); + } + /** * Reflect new Firefox Account state to the notification manager: show or hide * notifications reflecting the state of a Firefox Account. @@ -72,6 +85,8 @@ public class FxAccountNotificationManager { final String text; final Intent notificationIntent; if (action == Action.NeedsFinishMigrating) { + TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATION_NOTIFICATIONS_OFFERED, 1); + title = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_title); text = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_text, state.email); notificationIntent = new Intent(context, FxAccountFinishMigratingActivity.class); diff --git a/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java b/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java index 43ac65c0791..e1dc7190e10 100644 --- a/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java +++ b/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java @@ -67,7 +67,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter { public static final String SYNC_EXTRAS_RESPECT_LOCAL_RATE_LIMIT = "respect_local_rate_limit"; public static final String SYNC_EXTRAS_RESPECT_REMOTE_SERVER_BACKOFF = "respect_remote_server_backoff"; - protected static final int NOTIFICATION_ID = LOG_TAG.hashCode(); + public static final int NOTIFICATION_ID = LOG_TAG.hashCode(); // Tracks the last seen storage hostname for backoff purposes. private static final String PREF_BACKOFF_STORAGE_HOST = "backoffStorageHost"; diff --git a/mobile/android/base/sync/MigrationSentinelSyncStage.java b/mobile/android/base/sync/MigrationSentinelSyncStage.java index 1e5f8e9a819..a035b5b2c75 100644 --- a/mobile/android/base/sync/MigrationSentinelSyncStage.java +++ b/mobile/android/base/sync/MigrationSentinelSyncStage.java @@ -7,6 +7,7 @@ package org.mozilla.gecko.sync; import java.net.URISyntaxException; import org.mozilla.gecko.background.common.log.Logger; +import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper; import org.mozilla.gecko.background.fxa.FxAccountUtils; import org.mozilla.gecko.fxa.FxAccountConstants; import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount; @@ -18,6 +19,7 @@ import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate; import org.mozilla.gecko.sync.net.SyncStorageResponse; import org.mozilla.gecko.sync.stage.AbstractNonRepositorySyncStage; import org.mozilla.gecko.sync.stage.NoSuchStageException; +import org.mozilla.gecko.sync.telemetry.TelemetryContract; /** * The purpose of this class is to talk to a Sync 1.1 server and check @@ -152,6 +154,7 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage { private void onMigrated() { Logger.info(LOG_TAG, "Account migrated!"); + TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_SUCCEEDED, 1); session.config.persistLastMigrationSentinelCheckTimestamp(fetchTimestamp); session.abort(null, "Account migrated."); } @@ -163,6 +166,7 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage { private void onError(Exception ex, String reason) { Logger.info(LOG_TAG, "Could not migrate: " + reason, ex); + TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_FAILED, 1); session.abort(ex, reason); } @@ -181,6 +185,9 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage { public void handleRequestSuccess(SyncStorageResponse response) { Logger.info(LOG_TAG, "Found " + META_FXA_CREDENTIALS + " record; attempting migration."); setTimestamp(response.normalizedWeaveTimestamp()); + + TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATION_SENTINELS_SEEN, 1); + try { final ExtendedJSONObject body = response.jsonObjectBody(); final CryptoRecord cryptoRecord = CryptoRecord.fromJSONRecord(body); diff --git a/mobile/android/base/sync/telemetry/TelemetryContract.java b/mobile/android/base/sync/telemetry/TelemetryContract.java new file mode 100644 index 00000000000..c35ada5f53d --- /dev/null +++ b/mobile/android/base/sync/telemetry/TelemetryContract.java @@ -0,0 +1,48 @@ +/* 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.telemetry; + +public class TelemetryContract { + /** + * We are a Sync 1.1 (legacy) client, and we downloaded a migration sentinel. + */ + public static final String SYNC11_MIGRATION_SENTINELS_SEEN = "FENNEC_SYNC11_MIGRATION_SENTINELS_SEEN"; + + /** + * We are a Sync 1.1 (legacy) client and we have downloaded a migration + * sentinel, but there was an error creating a Firefox Account from that + * sentinel. + *

+ * We have logged the error and are ignoring that sentinel. + */ + public static final String SYNC11_MIGRATIONS_FAILED = "FENNEC_SYNC11_MIGRATIONS_FAILED"; + + /** + * We are a Sync 1.1 (legacy) client and we have downloaded a migration + * sentinel, and there was no reported error creating a Firefox Account from + * that sentinel. + *

+ * We have created a Firefox Account corresponding to the sentinel and have + * queued the existing Old Sync account for removal. + */ + public static final String SYNC11_MIGRATIONS_SUCCEEDED = "FENNEC_SYNC11_MIGRATIONS_SUCCEEDED"; + + /** + * We are (now) a Sync 1.5 (Firefox Accounts-based) client that migrated from + * Sync 1.1. We have presented the user the "complete upgrade" notification. + *

+ * We will offer every time a sync is triggered, including when a notification + * is already pending. + */ + public static final String SYNC11_MIGRATION_NOTIFICATIONS_OFFERED = "FENNEC_SYNC11_MIGRATION_NOTIFICATIONS_OFFERED"; + + /** + * We are (now) a Sync 1.5 (Firefox Accounts-based) client that migrated from + * Sync 1.1. We have presented the user the "complete upgrade" notification + * and they have successfully completed the upgrade process by entering their + * Firefox Account credentials. + */ + public static final String SYNC11_MIGRATIONS_COMPLETED = "FENNEC_SYNC11_MIGRATIONS_COMPLETED"; +}