Bug 963336 - Extract SyncConfiguration computation from GlobalSession. r=nalexander

This commit is contained in:
Richard Newman 2014-01-23 16:48:53 -08:00
parent 4e0458b5c9
commit 0085f18d1b
10 changed files with 102 additions and 67 deletions

View File

@ -14,11 +14,10 @@ import org.json.simple.parser.ParseException;
import org.mozilla.gecko.fxa.FxAccountConstants;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.BaseGlobalSessionCallback;
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.stage.CheckPreconditionsStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
@ -29,14 +28,11 @@ import android.os.Bundle;
public class FxAccountGlobalSession extends GlobalSession {
private static final String LOG_TAG = FxAccountGlobalSession.class.getSimpleName();
public FxAccountGlobalSession(String storageEndpoint, String username,
AuthHeaderProvider authHeaderProvider, String prefsPath,
KeyBundle syncKeyBundle, BaseGlobalSessionCallback callback,
public FxAccountGlobalSession(String storageEndpoint, SyncConfiguration config, BaseGlobalSessionCallback callback,
Context context, Bundle extras, ClientsDataDelegate clientsDelegate)
throws SyncConfigurationException, IllegalArgumentException, IOException,
ParseException, NonObjectJSONException, URISyntaxException {
super(username, authHeaderProvider, prefsPath, syncKeyBundle,
callback, context, extras, clientsDelegate, null);
super(config, callback, context, extras, clientsDelegate, null);
URI uri = new URI(storageEndpoint);
this.config.clusterURL = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), "/", null, null);
FxAccountConstants.pii(LOG_TAG, "storageEndpoint is " + uri + " and clusterURL is " + config.clusterURL);

View File

@ -31,6 +31,7 @@ import org.mozilla.gecko.fxa.login.State.StateLabel;
import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.BaseGlobalSessionCallback;
@ -181,8 +182,12 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
final long tokenServerSkew = tokenServerSkewHandler.getSkewInSeconds();
AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes("UTF-8"), false, tokenServerSkew);
final Context context = getContext();
SyncConfiguration syncConfig = new SyncConfiguration(token.uid, authHeaderProvider, sharedPrefs, syncKeyBundle);
// EXTRAS
globalSession = new FxAccountGlobalSession(token.endpoint, token.uid, authHeaderProvider, prefsPath, syncKeyBundle, callback, getContext(), Bundle.EMPTY, clientsDataDelegate);
final Bundle extras = Bundle.EMPTY;
globalSession = new FxAccountGlobalSession(token.endpoint, syncConfig, callback, context, extras, clientsDataDelegate);
globalSession.start();
} catch (Exception e) {
callback.handleError(globalSession, e);

View File

@ -100,39 +100,25 @@ public class GlobalSession implements PrefsSource, HttpResponseObserver {
return config.wboURI(collection, id);
}
public GlobalSession(String username,
AuthHeaderProvider authHeaderProvider,
String prefsPath,
KeyBundle syncKeyBundle,
public GlobalSession(SyncConfiguration config,
BaseGlobalSessionCallback callback,
Context context,
Bundle extras,
ClientsDataDelegate clientsDelegate,
NodeAssignmentCallback nodeAssignmentCallback)
throws SyncConfigurationException, IllegalArgumentException, IOException, ParseException, NonObjectJSONException {
if (username == null) {
throw new IllegalArgumentException("username must not be null.");
}
ClientsDataDelegate clientsDelegate, NodeAssignmentCallback nodeAssignmentCallback)
throws SyncConfigurationException, IllegalArgumentException, IOException, ParseException, NonObjectJSONException {
if (callback == null) {
throw new IllegalArgumentException("Must provide a callback to GlobalSession constructor.");
}
Logger.debug(LOG_TAG, "GlobalSession initialized with bundle " + extras);
if (syncKeyBundle == null ||
syncKeyBundle.getEncryptionKey() == null ||
syncKeyBundle.getHMACKey() == null) {
throw new SyncConfigurationException();
}
this.callback = callback;
this.context = context;
this.clientsDelegate = clientsDelegate;
this.nodeAssignmentCallback = nodeAssignmentCallback;
config = new SyncConfiguration(username, authHeaderProvider, prefsPath, this);
config.syncKeyBundle = syncKeyBundle;
this.config = config;
registerCommands();
prepareStages();

View File

@ -234,11 +234,7 @@ public class SyncConfiguration {
public Map<String, Boolean> userSelectedEngines;
public long userSelectedEnginesTimestamp;
// Fields that maintain a reference to a SharedPreferences instance, used for
// persistence.
// Behavior is undefined if the PrefsSource is switched out in flight.
public String prefsPath;
public PrefsSource prefsSource;
public SharedPreferences prefs;
protected final AuthHeaderProvider authHeaderProvider;
@ -267,16 +263,23 @@ public class SyncConfiguration {
* provide access to preferences.
*/
public SyncConfiguration(String username, AuthHeaderProvider authHeaderProvider, String prefsPath, PrefsSource prefsSource) {
this(username, authHeaderProvider, prefsSource.getPrefs(prefsPath, Utils.SHARED_PREFERENCES_MODE));
}
public SyncConfiguration(String username, AuthHeaderProvider authHeaderProvider, SharedPreferences prefs) {
this.username = username;
this.authHeaderProvider = authHeaderProvider;
this.prefsPath = prefsPath;
this.prefsSource = prefsSource;
this.loadFromPrefs(getPrefs());
this.prefs = prefs;
this.loadFromPrefs(prefs);
}
public SyncConfiguration(String username, AuthHeaderProvider authHeaderProvider, SharedPreferences prefs, KeyBundle syncKeyBundle) {
this(username, authHeaderProvider, prefs);
this.syncKeyBundle = syncKeyBundle;
}
public SharedPreferences getPrefs() {
Logger.trace(LOG_TAG, "Returning prefs for " + prefsPath);
return prefsSource.getPrefs(prefsPath, Utils.SHARED_PREFERENCES_MODE);
return this.prefs;
}
/**

View File

@ -509,10 +509,27 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements BaseGlob
// Do nothing.
}
if (username == null) {
throw new IllegalArgumentException("username must not be null.");
}
if (syncKey == null) {
throw new SyncConfigurationException();
}
final KeyBundle keyBundle = new KeyBundle(username, syncKey);
if (keyBundle == null ||
keyBundle.getEncryptionKey() == null ||
keyBundle.getHMACKey() == null) {
throw new SyncConfigurationException();
}
final AuthHeaderProvider authHeaderProvider = new BasicAuthHeaderProvider(username, password);
GlobalSession globalSession = new GlobalSession(username, authHeaderProvider, prefsPath,
keyBundle, this, this.mContext, extras, clientsDataDelegate, nodeAssignmentDelegate);
final SharedPreferences prefs = getContext().getSharedPreferences(prefsPath, Utils.SHARED_PREFERENCES_MODE);
final SyncConfiguration config = new SyncConfiguration(username, authHeaderProvider, prefs);
config.syncKeyBundle = keyBundle;
GlobalSession globalSession = new GlobalSession(config, this, this.mContext, extras, clientsDataDelegate, nodeAssignmentDelegate);
globalSession.start();
}
@ -540,7 +557,6 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements BaseGlob
@Override
public void handleSuccess(GlobalSession globalSession) {
Logger.info(LOG_TAG, "GlobalSession indicated success.");
Logger.debug(LOG_TAG, "Prefs target: " + globalSession.config.prefsPath);
globalSession.config.persistToPrefs();
notifyMonitor();
}

View File

@ -7,16 +7,22 @@ import org.json.simple.JSONArray;
import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
import org.mozilla.gecko.background.testhelpers.DefaultGlobalSessionCallback;
import org.mozilla.gecko.background.testhelpers.MockClientsDataDelegate;
import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
import org.mozilla.gecko.sync.repositories.android.ClientsDatabaseAccessor;
import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
import org.mozilla.gecko.sync.stage.SyncClientsEngineStage;
import android.content.Context;
import android.content.SharedPreferences;
public class TestClientsStage extends AndroidSyncTestCase {
private static final String TEST_USERNAME = "johndoe";
@ -40,10 +46,12 @@ public class TestClientsStage extends AndroidSyncTestCase {
final GlobalSessionCallback callback = new DefaultGlobalSessionCallback();
final ClientsDataDelegate delegate = new MockClientsDataDelegate();
final GlobalSession session = new GlobalSession(
TEST_USERNAME, new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD), null,
new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY),
callback, context, null, delegate, callback);
final KeyBundle keyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
final AuthHeaderProvider authHeaderProvider = new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD);
final SharedPreferences prefs = new MockSharedPreferences();
final SyncConfiguration config = new SyncConfiguration(TEST_USERNAME, authHeaderProvider, prefs);
config.syncKeyBundle = keyBundle;
GlobalSession session = new GlobalSession(config, callback, context, null, delegate, callback);
SyncClientsEngineStage stage = new SyncClientsEngineStage() {

View File

@ -10,22 +10,27 @@ import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
import org.mozilla.gecko.background.testhelpers.BaseMockServerSyncStage;
import org.mozilla.gecko.background.testhelpers.DefaultGlobalSessionCallback;
import org.mozilla.gecko.background.testhelpers.MockRecord;
import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
import org.mozilla.gecko.background.testhelpers.WBORepository;
import org.mozilla.gecko.background.testhelpers.WaitHelper;
import org.mozilla.gecko.sync.EngineSettings;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.MetaGlobalException;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.SynchronizerConfiguration;
import org.mozilla.gecko.sync.crypto.CryptoException;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
import org.mozilla.gecko.sync.repositories.domain.Record;
import org.mozilla.gecko.sync.stage.NoSuchStageException;
import org.mozilla.gecko.sync.synchronizer.Synchronizer;
import android.content.SharedPreferences;
/**
* Test the on-device side effects of reset operations on a stage.
*
@ -152,11 +157,13 @@ public class TestResetting extends AndroidSyncTestCase {
}
private GlobalSession createDefaultGlobalSession(final GlobalSessionCallback callback) throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException, IOException, ParseException, CryptoException {
return new GlobalSession(
TEST_USERNAME, new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD), null,
new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY),
callback, getApplicationContext(), null, null, callback) {
final KeyBundle keyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
final AuthHeaderProvider authHeaderProvider = new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD);
final SharedPreferences prefs = new MockSharedPreferences();
final SyncConfiguration config = new SyncConfiguration(TEST_USERNAME, authHeaderProvider, prefs);
config.syncKeyBundle = keyBundle;
return new GlobalSession(config, callback, getApplicationContext(), null, null, callback) {
@Override
public boolean engineIsEnabled(String engineName,
EngineSettings engineSettings)

View File

@ -10,14 +10,17 @@ import org.json.simple.parser.ParseException;
import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
import org.mozilla.gecko.background.testhelpers.DefaultGlobalSessionCallback;
import org.mozilla.gecko.background.testhelpers.MockGlobalSession;
import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.SyncConstants;
import org.mozilla.gecko.sync.crypto.CryptoException;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
import org.mozilla.gecko.sync.setup.Constants;
import org.mozilla.gecko.sync.setup.SyncAccounts;
import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
@ -169,9 +172,10 @@ public class TestUpgradeRequired extends AndroidSyncTestCase {
}
};
final GlobalSession session = new MockGlobalSession(
TEST_USERNAME, TEST_PASSWORD,
new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY), callback);
MockSharedPreferences prefs = new MockSharedPreferences();
SyncConfiguration config = new SyncConfiguration(TEST_USERNAME, new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD), prefs);
config.syncKeyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
final GlobalSession session = new MockGlobalSession(config, callback);
session.interpretHTTPFailure(simulate400());
assertTrue(calledUpgradeRequired.called);

View File

@ -9,9 +9,11 @@ import java.util.HashMap;
import org.json.simple.parser.ParseException;
import org.mozilla.gecko.sync.EngineSettings;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
import org.mozilla.gecko.sync.stage.CompletedStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
@ -19,10 +21,13 @@ import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
public class MockGlobalSession extends MockPrefsGlobalSession {
public MockGlobalSession(String username, String password,
KeyBundle syncKeyBundle, GlobalSessionCallback callback)
public MockGlobalSession(String username, String password, KeyBundle keyBundle, GlobalSessionCallback callback) throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException, IOException, ParseException {
this(new SyncConfiguration(username, new BasicAuthHeaderProvider(username, password), new MockSharedPreferences(), keyBundle), callback);
}
public MockGlobalSession(SyncConfiguration config, GlobalSessionCallback callback)
throws SyncConfigurationException, IllegalArgumentException, IOException, ParseException, NonObjectJSONException {
super(username, password, null, syncKeyBundle, callback, /* context */ null, null, null);
super(config, callback, null, null, null);
}
@Override

View File

@ -8,7 +8,9 @@ import java.io.IOException;
import org.json.simple.parser.ParseException;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
@ -27,35 +29,38 @@ public class MockPrefsGlobalSession extends GlobalSession {
public MockSharedPreferences prefs;
public MockPrefsGlobalSession(
String username, String password, String prefsPath,
SyncConfiguration config, GlobalSessionCallback callback, Context context,
Bundle extras, ClientsDataDelegate clientsDelegate)
throws SyncConfigurationException, IllegalArgumentException, IOException,
ParseException, NonObjectJSONException {
super(config, callback, context, extras, clientsDelegate, callback);
}
public static MockPrefsGlobalSession getSession(
String username, String password,
KeyBundle syncKeyBundle, GlobalSessionCallback callback, Context context,
Bundle extras, ClientsDataDelegate clientsDelegate)
throws SyncConfigurationException, IllegalArgumentException, IOException,
ParseException, NonObjectJSONException {
this(username, new BasicAuthHeaderProvider(username, password), prefsPath, syncKeyBundle, callback, context, extras, clientsDelegate);
return getSession(username, new BasicAuthHeaderProvider(username, password), null,
syncKeyBundle, callback, context, extras, clientsDelegate);
}
public MockPrefsGlobalSession(
public static MockPrefsGlobalSession getSession(
String username, AuthHeaderProvider authHeaderProvider, String prefsPath,
KeyBundle syncKeyBundle, GlobalSessionCallback callback, Context context,
Bundle extras, ClientsDataDelegate clientsDelegate)
throws SyncConfigurationException, IllegalArgumentException, IOException,
ParseException, NonObjectJSONException {
super(username, authHeaderProvider, prefsPath, syncKeyBundle,
callback, context, extras, clientsDelegate, callback);
}
@Override
public SharedPreferences getPrefs(String name, int mode) {
if (prefs == null) {
prefs = new MockSharedPreferences();
}
return prefs;
final SharedPreferences prefs = new MockSharedPreferences();
final SyncConfiguration config = new SyncConfiguration(username, authHeaderProvider, prefs);
config.syncKeyBundle = syncKeyBundle;
return new MockPrefsGlobalSession(config, callback, context, extras, clientsDelegate);
}
@Override
public Context getContext() {
return null;
}
}