зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1147473 - Expose Firefox Account debug information from Settings activity. r=rnewman
========afcbbba32c
Author: Nick Alexander <nalexander@mozilla.com> Date: Tue Mar 24 23:24:27 2015 -0700 Bug 1147473 - Part 2: Make it possible to toggle Firefox Accounts debug / PII logging at runtime. Tap the email address in the Firefox Account settings activity 5 times. Only available when: !defined(MOZILLA_OFFICIAL) || defined(NIGHTLY_BUILD) || defined(MOZ_DEBUG) ========261f912d12
Author: Nick Alexander <nalexander@mozilla.com> Date: Tue Mar 24 22:10:05 2015 -0700 Bug 1147473 - Part 1: Add additional (dangerous!) debug commands. These make it easier to test oauth token authorization, especially using stage servers. ========c1509baa77
Author: Nick Alexander <nalexander@mozilla.com> Date: Tue Mar 24 22:06:43 2015 -0700 Bug 1142596 - Pre: Move constants around. ========2c676500c3
Author: Nick Alexander <nalexander@mozilla.com> Date: Thu Mar 26 11:28:22 2015 -0700 Bug 1142596 - Pre: Make it easier to construct intermediate states.
This commit is contained in:
Родитель
06a2824f83
Коммит
5020089701
|
@ -10,11 +10,16 @@ public class FxAccountConstants {
|
|||
public static final String GLOBAL_LOG_TAG = "FxAccounts";
|
||||
public static final String ACCOUNT_TYPE = AppConstants.MOZ_ANDROID_SHARED_FXACCOUNT_TYPE;
|
||||
|
||||
// Must be a client ID allocated with "canGrant" privileges!
|
||||
public static final String OAUTH_CLIENT_ID_FENNEC = "3332a18d142636cb";
|
||||
|
||||
public static final String DEFAULT_AUTH_SERVER_ENDPOINT = "https://api.accounts.firefox.com/v1";
|
||||
public static final String DEFAULT_TOKEN_SERVER_ENDPOINT = "https://token.services.mozilla.com/1.0/sync/1.5";
|
||||
public static final String DEFAULT_OAUTH_SERVER_ENDPOINT = "https://oauth.accounts.firefox.com/v1";
|
||||
|
||||
public static final String STAGE_AUTH_SERVER_ENDPOINT = "https://api-accounts.stage.mozaws.net/v1";
|
||||
public static final String STAGE_TOKEN_SERVER_ENDPOINT = "https://token.stage.mozaws.net/1.0/sync/1.5";
|
||||
public static final String STAGE_AUTH_SERVER_ENDPOINT = "https://stable.dev.lcip.org/auth/v1";
|
||||
public static final String STAGE_TOKEN_SERVER_ENDPOINT = "https://stable.dev.lcip.org/syncserver/token/1.0/sync/1.5";
|
||||
public static final String STAGE_OAUTH_SERVER_ENDPOINT = "https://oauth-stable.dev.lcip.org/v1";
|
||||
|
||||
// You must be at least 13 years old, on the day of creation, to create a Firefox Account.
|
||||
public static final int MINIMUM_AGE_TO_CREATE_AN_ACCOUNT = 13;
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
|
@ -17,12 +24,14 @@ import org.mozilla.gecko.fxa.login.Married;
|
|||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.reading.ReadingListConstants;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
|
||||
import org.mozilla.gecko.sync.SyncConfiguration;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -38,13 +47,7 @@ import android.preference.PreferenceCategory;
|
|||
import android.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -67,6 +70,7 @@ public class FxAccountStatusFragment
|
|||
c.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
|
||||
EARLIEST_VALID_SYNCED_DATE = c.getTime();
|
||||
}
|
||||
|
||||
// When a checkbox is toggled, wait 5 seconds (for other checkbox actions)
|
||||
// before trying to sync. Should we kill off the fragment before the sync
|
||||
// request happens, that's okay: the runnable will run if the UI thread is
|
||||
|
@ -84,6 +88,15 @@ public class FxAccountStatusFragment
|
|||
// configured to use a custom Sync server. In debug mode, this is set.
|
||||
private static boolean ALWAYS_SHOW_SYNC_SERVER = false;
|
||||
|
||||
// If the user clicks the email field this many times, the debug / personal
|
||||
// information logging setting will toggle. The setting is not permanent: it
|
||||
// lasts until this process is killed. We don't want to dump PII to the log
|
||||
// for a long time!
|
||||
private final int NUMBER_OF_CLICKS_TO_TOGGLE_DEBUG =
|
||||
// !defined(MOZILLA_OFFICIAL) || defined(NIGHTLY_BUILD) || defined(MOZ_DEBUG)
|
||||
(!AppConstants.MOZILLA_OFFICIAL || AppConstants.NIGHTLY_BUILD || AppConstants.DEBUG_BUILD) ? 5 : -1 /* infinite */;
|
||||
private int debugClickCount = 0;
|
||||
|
||||
protected PreferenceCategory accountCategory;
|
||||
protected Preference emailPreference;
|
||||
protected Preference authServerPreference;
|
||||
|
@ -177,6 +190,8 @@ public class FxAccountStatusFragment
|
|||
ALWAYS_SHOW_SYNC_SERVER = true;
|
||||
}
|
||||
|
||||
emailPreference.setOnPreferenceClickListener(this);
|
||||
|
||||
needsPasswordPreference.setOnPreferenceClickListener(this);
|
||||
needsVerificationPreference.setOnPreferenceClickListener(this);
|
||||
needsFinishMigratingPreference.setOnPreferenceClickListener(this);
|
||||
|
@ -214,6 +229,17 @@ public class FxAccountStatusFragment
|
|||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (preference == emailPreference) {
|
||||
debugClickCount += 1;
|
||||
if (NUMBER_OF_CLICKS_TO_TOGGLE_DEBUG > 0 && debugClickCount >= NUMBER_OF_CLICKS_TO_TOGGLE_DEBUG) {
|
||||
debugClickCount = 0;
|
||||
FxAccountUtils.LOG_PERSONAL_INFORMATION = !FxAccountUtils.LOG_PERSONAL_INFORMATION;
|
||||
Toast.makeText(getActivity(), "Toggled logging Firefox Account personal information!", Toast.LENGTH_LONG).show();
|
||||
hardRefresh(); // Display or hide debug options.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preference == needsPasswordPreference) {
|
||||
Intent intent = new Intent(getActivity(), FxAccountUpdateCredentialsActivity.class);
|
||||
final Bundle extras = getExtrasForAccount();
|
||||
|
@ -764,6 +790,16 @@ public class FxAccountStatusFragment
|
|||
Logger.info(LOG_TAG, "Force syncing.");
|
||||
fxAccount.requestSync(FirefoxAccounts.FORCE);
|
||||
// No sense refreshing, since the sync will complete in the future.
|
||||
} else if ("debug_forget_reading_list_oauth_token".equals(key)) {
|
||||
final Account account = fxAccount.getAndroidAccount();
|
||||
final AccountManager accountManager = AccountManager.get(getActivity());
|
||||
final String authToken = accountManager.peekAuthToken(account, ReadingListConstants.AUTH_TOKEN_TYPE);
|
||||
if (authToken != null) {
|
||||
Logger.info(LOG_TAG, "Forgetting reading list oauth token: " + authToken);
|
||||
accountManager.invalidateAuthToken(account.type, authToken);
|
||||
} else {
|
||||
Logger.warn(LOG_TAG, "No reading list oauth token to forget!");
|
||||
}
|
||||
} else if ("debug_forget_certificate".equals(key)) {
|
||||
State state = fxAccount.getState();
|
||||
try {
|
||||
|
@ -775,6 +811,17 @@ public class FxAccountStatusFragment
|
|||
Logger.info(LOG_TAG, "Not in Married state; can't forget certificate.");
|
||||
// Ignore.
|
||||
}
|
||||
} else if ("debug_invalidate_certificate".equals(key)) {
|
||||
State state = fxAccount.getState();
|
||||
try {
|
||||
Married married = (Married) state;
|
||||
Logger.info(LOG_TAG, "Invalidating certificate.");
|
||||
fxAccount.setState(married.makeCohabitingState().withCertificate("INVALID CERTIFICATE"));
|
||||
refresh();
|
||||
} catch (ClassCastException e) {
|
||||
Logger.info(LOG_TAG, "Not in Married state; can't invalidate certificate.");
|
||||
// Ignore.
|
||||
}
|
||||
} else if ("debug_require_password".equals(key)) {
|
||||
Logger.info(LOG_TAG, "Moving to Separated state: Forgetting password.");
|
||||
State state = fxAccount.getState();
|
||||
|
@ -790,6 +837,14 @@ public class FxAccountStatusFragment
|
|||
State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeMigratedFromSync11State(null));
|
||||
refresh();
|
||||
} else if ("debug_make_account_stage".equals(key)) {
|
||||
Logger.info(LOG_TAG, "Moving Account endpoints, in place, to stage. Deleting Sync and RL prefs and requiring password.");
|
||||
fxAccount.unsafeTransitionToStageEndpoints();
|
||||
refresh();
|
||||
} else if ("debug_make_account_default".equals(key)) {
|
||||
Logger.info(LOG_TAG, "Moving Account endpoints, in place, to default (production). Deleting Sync and RL prefs and requiring password.");
|
||||
fxAccount.unsafeTransitionToDefaultEndpoints();
|
||||
refresh();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -807,20 +862,12 @@ public class FxAccountStatusFragment
|
|||
|
||||
// We don't want to use Android resource strings for debug UI, so we just
|
||||
// use the keys throughout.
|
||||
final Preference debugCategory = ensureFindPreference("debug_category");
|
||||
final PreferenceCategory debugCategory = (PreferenceCategory) ensureFindPreference("debug_category");
|
||||
debugCategory.setTitle(debugCategory.getKey());
|
||||
|
||||
String[] debugKeys = new String[] {
|
||||
"debug_refresh",
|
||||
"debug_dump",
|
||||
"debug_force_sync",
|
||||
"debug_forget_certificate",
|
||||
"debug_require_password",
|
||||
"debug_require_upgrade",
|
||||
"debug_migrated_from_sync11" };
|
||||
for (String debugKey : debugKeys) {
|
||||
final Preference button = ensureFindPreference(debugKey);
|
||||
button.setTitle(debugKey); // Not very friendly, but this is for debugging only!
|
||||
for (int i = 0; i < debugCategory.getPreferenceCount(); i++) {
|
||||
final Preference button = debugCategory.getPreference(i);
|
||||
button.setTitle(button.getKey()); // Not very friendly, but this is for debugging only!
|
||||
button.setOnPreferenceClickListener(listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -620,4 +620,35 @@ public class AndroidFxAccount {
|
|||
return neverSynced;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug only! This is dangerous!
|
||||
public void unsafeTransitionToDefaultEndpoints() {
|
||||
unsafeTransitionToStageEndpoints(
|
||||
FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT,
|
||||
FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT);
|
||||
}
|
||||
|
||||
// Debug only! This is dangerous!
|
||||
public void unsafeTransitionToStageEndpoints() {
|
||||
unsafeTransitionToStageEndpoints(
|
||||
FxAccountConstants.STAGE_AUTH_SERVER_ENDPOINT,
|
||||
FxAccountConstants.STAGE_TOKEN_SERVER_ENDPOINT);
|
||||
}
|
||||
|
||||
protected void unsafeTransitionToStageEndpoints(String authServerEndpoint, String tokenServerEndpoint) {
|
||||
try {
|
||||
getReadingListPrefs().edit().clear().commit();
|
||||
} catch (UnsupportedEncodingException | GeneralSecurityException e) {
|
||||
// Ignore.
|
||||
}
|
||||
try {
|
||||
getSyncPrefs().edit().clear().commit();
|
||||
} catch (UnsupportedEncodingException | GeneralSecurityException e) {
|
||||
// Ignore.
|
||||
}
|
||||
State state = getState();
|
||||
setState(state.makeSeparatedState());
|
||||
accountManager.setUserData(account, ACCOUNT_KEY_IDP_SERVER, authServerEndpoint);
|
||||
accountManager.setUserData(account, ACCOUNT_KEY_TOKEN_SERVER, tokenServerEndpoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ public class Cohabiting extends TokensAndKeysState {
|
|||
super(StateLabel.Cohabiting, email, uid, sessionToken, kA, kB, keyPair);
|
||||
}
|
||||
|
||||
public Married withCertificate(String certificate) {
|
||||
return new Married(email, uid, sessionToken, kA, kB, keyPair, certificate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final ExecuteDelegate delegate) {
|
||||
delegate.getClient().sign(sessionToken, keyPair.getPublic().toJSONObject(), delegate.getCertificateDurationInMilliseconds(),
|
||||
|
@ -39,7 +43,7 @@ public class Cohabiting extends TokensAndKeysState {
|
|||
FxAccountUtils.pii(LOG_TAG, "Could not parse certificate!");
|
||||
}
|
||||
}
|
||||
delegate.handleTransition(new LogMessage("sign succeeded"), new Married(email, uid, sessionToken, kA, kB, keyPair, certificate));
|
||||
delegate.handleTransition(new LogMessage("sign succeeded"), withCertificate(certificate));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public class Married extends TokensAndKeysState {
|
|||
return this.clientState;
|
||||
}
|
||||
|
||||
public State makeCohabitingState() {
|
||||
public Cohabiting makeCohabitingState() {
|
||||
return new Cohabiting(email, uid, sessionToken, kA, kB, keyPair);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ public class ReadingListConstants {
|
|||
public static final String DEFAULT_DEV_ENDPOINT = "https://readinglist.dev.mozaws.net/v1/";
|
||||
public static final String DEFAULT_PROD_ENDPOINT = "https://readinglist.services.mozilla.com/v1/";
|
||||
|
||||
public static final String OAUTH_ENDPOINT_PROD = "https://oauth.accounts.firefox.com/v1";
|
||||
public static final String OAUTH_SCOPE_READINGLIST = "readinglist";
|
||||
public static final String AUTH_TOKEN_TYPE = "oauth::" + OAUTH_SCOPE_READINGLIST;
|
||||
|
||||
public static boolean DEBUG = false;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.mozilla.gecko.background.fxa.oauth.FxAccountOAuthClient10.Authorizati
|
|||
import org.mozilla.gecko.browserid.BrowserIDKeyPair;
|
||||
import org.mozilla.gecko.browserid.JSONWebTokenUtils;
|
||||
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.LoginStateMachineDelegate;
|
||||
|
@ -48,8 +49,6 @@ import android.os.Bundle;
|
|||
|
||||
public class ReadingListSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
public static final String PREF_LOCAL_NAME = "device.localname";
|
||||
public static final String OAUTH_CLIENT_ID_FENNEC = "3332a18d142636cb";
|
||||
public static final String OAUTH_SCOPE_READINGLIST = "readinglist";
|
||||
|
||||
private static final String LOG_TAG = ReadingListSyncAdapter.class.getSimpleName();
|
||||
private static final long TIMEOUT_SECONDS = 60;
|
||||
|
@ -145,7 +144,7 @@ public class ReadingListSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
return;
|
||||
}
|
||||
|
||||
final String oauthServerUri = ReadingListConstants.OAUTH_ENDPOINT_PROD;
|
||||
final String oauthServerUri = FxAccountConstants.STAGE_OAUTH_SERVER_ENDPOINT;
|
||||
final String authServerEndpoint = fxAccount.getAccountServerURI();
|
||||
final String audience = FxAccountUtils.getAudienceForURL(oauthServerUri); // The assertion gets traded in for an oauth bearer token.
|
||||
|
||||
|
@ -195,8 +194,8 @@ public class ReadingListSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
final String assertion = married.generateAssertion(audience, JSONWebTokenUtils.DEFAULT_ASSERTION_ISSUER);
|
||||
JSONWebTokenUtils.dumpAssertion(assertion);
|
||||
|
||||
final String clientID = OAUTH_CLIENT_ID_FENNEC;
|
||||
final String scope = OAUTH_SCOPE_READINGLIST;
|
||||
final String clientID = FxAccountConstants.OAUTH_CLIENT_ID_FENNEC;
|
||||
final String scope = ReadingListConstants.OAUTH_SCOPE_READINGLIST;
|
||||
syncWithAssertion(clientID, scope, assertion, sharedPrefs, extras);
|
||||
} catch (Exception e) {
|
||||
syncDelegate.handleError(e);
|
||||
|
|
|
@ -126,10 +126,14 @@
|
|||
<Preference android:key="debug_refresh" />
|
||||
<Preference android:key="debug_dump" />
|
||||
<Preference android:key="debug_force_sync" />
|
||||
<Preference android:key="debug_invalidate_certificate" />
|
||||
<Preference android:key="debug_forget_reading_list_oauth_token" />
|
||||
<Preference android:key="debug_forget_certificate" />
|
||||
<Preference android:key="debug_require_password" />
|
||||
<Preference android:key="debug_require_upgrade" />
|
||||
<Preference android:key="debug_migrated_from_sync11" />
|
||||
<Preference android:key="debug_make_account_stage" />
|
||||
<Preference android:key="debug_make_account_default" />
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
Загрузка…
Ссылка в новой задаче