diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 10b50aa4d..6901075a3 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -29,7 +29,7 @@
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
diff --git a/briar-android/proguard-rules.txt b/briar-android/proguard-rules.txt
index 48d785a43..3f11de5e3 100644
--- a/briar-android/proguard-rules.txt
+++ b/briar-android/proguard-rules.txt
@@ -3,6 +3,7 @@
-dontpreverify
-dontobfuscate
-verbose
+-useuniqueclassmembernames
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# For comfortability in case we do obfuscate
# -renamesourcefileattribute SourceFile
diff --git a/briar-android/res/layout/fragment_dashboard.xml b/briar-android/res/layout/fragment_dashboard.xml
deleted file mode 100644
index 1d73431f5..000000000
--- a/briar-android/res/layout/fragment_dashboard.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
new file mode 100644
index 000000000..529bbf7ba
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -0,0 +1,107 @@
+package org.briarproject.android;
+
+import android.app.Activity;
+
+import org.briarproject.android.contact.ConversationActivity;
+import org.briarproject.android.forum.AvailableForumsActivity;
+import org.briarproject.android.forum.ContactSelectorFragment;
+import org.briarproject.android.forum.CreateForumActivity;
+import org.briarproject.android.forum.ForumActivity;
+import org.briarproject.android.forum.ReadForumPostActivity;
+import org.briarproject.android.forum.ShareForumActivity;
+import org.briarproject.android.forum.ShareForumMessageFragment;
+import org.briarproject.android.forum.WriteForumPostActivity;
+import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.identity.CreateIdentityActivity;
+import org.briarproject.android.introduction.IntroductionActivity;
+import org.briarproject.android.introduction.IntroductionMessageFragment;
+import org.briarproject.android.invitation.AddContactActivity;
+import org.briarproject.android.keyagreement.KeyAgreementActivity;
+import org.briarproject.android.panic.PanicPreferencesActivity;
+import org.briarproject.android.panic.PanicResponderActivity;
+
+import javax.inject.Named;
+
+import dagger.Component;
+
+@ActivityScope
+@Component(modules = ActivityModule.class,
+ dependencies = AndroidComponent.class)
+public interface ActivityComponent {
+ Activity activity();
+
+ void inject(SplashScreenActivity activity);
+
+ void inject(SetupActivity activity);
+
+ void inject(NavDrawerActivity activity);
+
+ void inject(PasswordActivity activity);
+
+ void inject(PanicResponderActivity activity);
+
+ void inject(PanicPreferencesActivity activity);
+
+ void inject(AddContactActivity activity);
+
+ void inject(KeyAgreementActivity activity);
+
+ void inject(ConversationActivity activity);
+
+ void inject(CreateIdentityActivity activity);
+
+ void inject(AvailableForumsActivity activity);
+
+ void inject(WriteForumPostActivity activity);
+
+ void inject(CreateForumActivity activity);
+
+ void inject(ShareForumActivity activity);
+
+ void inject(ReadForumPostActivity activity);
+
+ void inject(ForumActivity activity);
+
+ void inject(SettingsActivity activity);
+
+ /*
+ void inject(ContactListFragment fragment);
+
+ void inject(ForumListFragment fragment);
+
+ void inject(ShowQrCodeFragment fragment);
+ */
+
+ void inject(IntroductionActivity activity);
+
+ /*
+ void inject(ContactChooserFragment fragment);
+
+ void inject(introductionmessagefragment fragment);
+
+ */
+
+ @Named("ContactListFragment")
+ BaseFragment newContactListFragment();
+
+ @Named("ForumListFragment")
+ BaseFragment newForumListFragment();
+
+ @Named("ChooseIdentityFragment")
+ BaseFragment newChooseIdentityFragment();
+
+ @Named("ShowQrCodeFragment")
+ BaseFragment newShowQrCodeFragment();
+
+ @Named("ContactChooserFragment")
+ BaseFragment newContactChooserFragment();
+
+ @Named("ContactSelectorFragment")
+ ContactSelectorFragment newContactSelectorFragment();
+
+ @Named("ShareForumMessageFragment")
+ ShareForumMessageFragment newShareForumMessageFragment();
+
+ @Named("IntroductionMessageFragment")
+ IntroductionMessageFragment newIntroductionMessageFragment();
+}
diff --git a/briar-android/src/org/briarproject/android/ActivityModule.java b/briar-android/src/org/briarproject/android/ActivityModule.java
new file mode 100644
index 000000000..1ed65e9be
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/ActivityModule.java
@@ -0,0 +1,175 @@
+package org.briarproject.android;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import org.briarproject.android.contact.ContactListFragment;
+import org.briarproject.android.controller.BriarController;
+import org.briarproject.android.controller.BriarControllerImpl;
+import org.briarproject.android.controller.ConfigController;
+import org.briarproject.android.controller.ConfigControllerImpl;
+import org.briarproject.android.controller.NavDrawerController;
+import org.briarproject.android.controller.NavDrawerControllerImpl;
+import org.briarproject.android.controller.PasswordController;
+import org.briarproject.android.controller.PasswordControllerImpl;
+import org.briarproject.android.controller.SetupController;
+import org.briarproject.android.controller.SetupControllerImpl;
+import org.briarproject.android.controller.TransportStateListener;
+import org.briarproject.android.forum.ContactSelectorFragment;
+import org.briarproject.android.forum.ForumListFragment;
+import org.briarproject.android.forum.ShareForumMessageFragment;
+import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.introduction.ContactChooserFragment;
+import org.briarproject.android.introduction.IntroductionMessageFragment;
+import org.briarproject.android.keyagreement.ChooseIdentityFragment;
+import org.briarproject.android.keyagreement.ShowQrCodeFragment;
+
+import javax.inject.Named;
+
+import dagger.Module;
+import dagger.Provides;
+
+import static org.briarproject.android.BriarService.BriarServiceConnection;
+
+@Module
+public class ActivityModule {
+
+ private final BaseActivity activity;
+
+ public ActivityModule(BaseActivity activity) {
+ this.activity = activity;
+ }
+
+ @ActivityScope
+ @Provides
+ BaseActivity providesBaseActivity() {
+ return activity;
+ }
+
+ @ActivityScope
+ @Provides
+ Activity providesActivity() {
+ return activity;
+ }
+
+ @ActivityScope
+ @Provides
+ protected SetupController provideSetupController(
+ SetupControllerImpl setupControllerImpl) {
+ return setupControllerImpl;
+ }
+
+ @ActivityScope
+ @Provides
+ protected ConfigController provideConfigController(
+ ConfigControllerImpl configControllerImpl) {
+ return configControllerImpl;
+ }
+
+ @ActivityScope
+ @Provides
+ protected SharedPreferences provideSharedPreferences(Activity activity) {
+ return activity.getSharedPreferences("db", Context.MODE_PRIVATE);
+ }
+
+ @ActivityScope
+ @Provides
+ protected PasswordController providePasswordController(
+ PasswordControllerImpl passwordControllerImp) {
+ return passwordControllerImp;
+ }
+
+ @ActivityScope
+ @Provides
+ protected BriarController provideBriarController(
+ BriarControllerImpl briarControllerImpl) {
+ activity.addLifecycleController(briarControllerImpl);
+ return briarControllerImpl;
+ }
+
+ @ActivityScope
+ @Provides
+ protected NavDrawerController provideNavDrawerController(
+ NavDrawerControllerImpl navDrawerControllerImp) {
+ activity.addLifecycleController(navDrawerControllerImp);
+ if (activity instanceof TransportStateListener) {
+ navDrawerControllerImp
+ .setTransportListener((TransportStateListener) activity);
+ }
+ return navDrawerControllerImp;
+ }
+
+ @ActivityScope
+ @Provides
+ protected BriarServiceConnection provideBriarServiceConnection() {
+ return new BriarServiceConnection();
+ }
+
+ @Provides
+ @Named("ForumListFragment")
+ BaseFragment provideForumListFragment(
+ ForumListFragment forumListFragment) {
+ forumListFragment.setArguments(new Bundle());
+ return forumListFragment;
+ }
+
+ @Provides
+ @Named("ContactListFragment")
+ BaseFragment provideContactListFragment(
+ ContactListFragment contactListFragment) {
+ contactListFragment.setArguments(new Bundle());
+ return contactListFragment;
+ }
+
+ @Provides
+ @Named("ChooseIdentityFragment")
+ BaseFragment provideChooseIdendityFragment() {
+ ChooseIdentityFragment fragment = new ChooseIdentityFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+ @Provides
+ @Named("ShowQrCodeFragment")
+ BaseFragment provideShowQrCodeFragment() {
+ ShowQrCodeFragment fragment = new ShowQrCodeFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+ @Provides
+ @Named("ContactChooserFragment")
+ BaseFragment provideContactChooserFragment() {
+ ContactChooserFragment fragment = new ContactChooserFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+ @Provides
+ @Named("ContactSelectorFragment")
+ ContactSelectorFragment provideContactSelectorFragment() {
+ ContactSelectorFragment fragment = new ContactSelectorFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+ @Provides
+ @Named("ShareForumMessageFragment")
+ ShareForumMessageFragment provideShareForumMessageFragment() {
+ ShareForumMessageFragment fragment = new ShareForumMessageFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+ @Provides
+ @Named("IntroductionMessageFragment")
+ IntroductionMessageFragment provideIntroductionMessageFragment() {
+ IntroductionMessageFragment fragment =
+ new IntroductionMessageFragment();
+ fragment.setArguments(new Bundle());
+ return fragment;
+ }
+
+}
diff --git a/briar-android/src/org/briarproject/android/ActivityScope.java b/briar-android/src/org/briarproject/android/ActivityScope.java
new file mode 100644
index 000000000..a6ceb30ab
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/ActivityScope.java
@@ -0,0 +1,11 @@
+package org.briarproject.android;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.inject.Scope;
+
+@Scope
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ActivityScope {
+}
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index 8b2ac951a..ba2578add 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -2,31 +2,41 @@ package org.briarproject.android;
import org.briarproject.CoreEagerSingletons;
import org.briarproject.CoreModule;
-import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.contact.ConversationActivity;
-import org.briarproject.android.forum.AvailableForumsActivity;
-import org.briarproject.android.forum.ContactSelectorFragment;
-import org.briarproject.android.forum.CreateForumActivity;
-import org.briarproject.android.forum.ForumActivity;
-import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.forum.ReadForumPostActivity;
-import org.briarproject.android.forum.ShareForumActivity;
-import org.briarproject.android.forum.ShareForumMessageFragment;
-import org.briarproject.android.forum.WriteForumPostActivity;
-import org.briarproject.android.identity.CreateIdentityActivity;
-import org.briarproject.android.introduction.ContactChooserFragment;
-import org.briarproject.android.introduction.IntroductionActivity;
-import org.briarproject.android.introduction.IntroductionMessageFragment;
-import org.briarproject.android.invitation.AddContactActivity;
-import org.briarproject.android.keyagreement.ChooseIdentityFragment;
-import org.briarproject.android.keyagreement.KeyAgreementActivity;
-import org.briarproject.android.keyagreement.ShowQrCodeFragment;
-import org.briarproject.android.panic.PanicPreferencesActivity;
-import org.briarproject.android.panic.PanicResponderActivity;
+import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.android.api.AndroidNotificationManager;
+import org.briarproject.android.api.ReferenceManager;
import org.briarproject.android.util.BriarReportSender;
+import org.briarproject.api.contact.ContactExchangeTask;
+import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.CryptoExecutor;
+import org.briarproject.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.db.DatabaseExecutor;
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.forum.ForumManager;
+import org.briarproject.api.forum.ForumPostFactory;
+import org.briarproject.api.forum.ForumSharingManager;
+import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.introduction.IntroductionManager;
+import org.briarproject.api.invitation.InvitationTaskFactory;
+import org.briarproject.api.keyagreement.KeyAgreementTaskFactory;
+import org.briarproject.api.keyagreement.PayloadEncoder;
+import org.briarproject.api.keyagreement.PayloadParser;
+import org.briarproject.api.lifecycle.IoExecutor;
+import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.messaging.MessagingManager;
+import org.briarproject.api.messaging.PrivateMessageFactory;
+import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.api.plugins.PluginManager;
+import org.briarproject.api.properties.TransportPropertyManager;
+import org.briarproject.api.settings.SettingsManager;
import org.briarproject.plugins.AndroidPluginsModule;
import org.briarproject.system.AndroidSystemModule;
+import java.util.concurrent.Executor;
+
import javax.inject.Singleton;
import dagger.Component;
@@ -39,63 +49,72 @@ import dagger.Component;
AndroidSystemModule.class
})
public interface AndroidComponent extends CoreEagerSingletons {
+ // Exposed objects
+ @CryptoExecutor
+ Executor cryptoExecutor();
+
+ PasswordStrengthEstimator passwordStrengthIndicator();
+
+ CryptoComponent cryptoComponent();
+
+ DatabaseConfig databaseConfig();
+
+ AuthorFactory authFactory();
+
+ ReferenceManager referenceMangager();
+
+ @DatabaseExecutor
+ Executor databaseExecutor();
+
+ LifecycleManager lifecycleManager();
+
+ IdentityManager identityManager();
+
+ PluginManager pluginManager();
+
+ EventBus eventBus();
+
+ InvitationTaskFactory invitationTaskFactory();
+
+ AndroidNotificationManager androidNotificationManager();
+
+ ConnectionRegistry connectionRegistry();
+
+ ContactManager contactManager();
+
+ MessagingManager messagingManager();
+
+ PrivateMessageFactory privateMessageFactory();
+
+ TransportPropertyManager transportPropertyManager();
+
+ ForumManager forumManager();
+
+ ForumSharingManager forumSharingManager();
+
+ ForumPostFactory forumPostFactory();
+
+ SettingsManager settingsManager();
+
+ ContactExchangeTask contactExchangeTask();
+
+ KeyAgreementTaskFactory keyAgreementTaskFactory();
+
+ PayloadEncoder payloadEncoder();
+
+ PayloadParser payloadParser();
+
+ IntroductionManager introductionManager();
+
+ AndroidExecutor androidExecutor();
+
+ @IoExecutor
+ Executor ioExecutor();
void inject(DevReportActivity devReportActivity);
- void inject(SplashScreenActivity activity);
-
- void inject(SetupActivity activity);
-
- void inject(NavDrawerActivity activity);
-
- void inject(PasswordActivity activity);
-
void inject(BriarService activity);
- void inject(PanicResponderActivity activity);
-
- void inject(PanicPreferencesActivity activity);
-
- void inject(AddContactActivity activity);
-
- void inject(KeyAgreementActivity activity);
-
- void inject(ConversationActivity activity);
-
- void inject(CreateIdentityActivity activity);
-
- void inject(AvailableForumsActivity activity);
-
- void inject(WriteForumPostActivity activity);
-
- void inject(CreateForumActivity activity);
-
- void inject(ShareForumActivity activity);
-
- void inject(ContactSelectorFragment fragment);
-
- void inject(ShareForumMessageFragment fragment);
-
- void inject(ReadForumPostActivity activity);
-
- void inject(ForumActivity activity);
-
- void inject(SettingsActivity activity);
-
- void inject(ContactListFragment fragment);
-
- void inject(ForumListFragment fragment);
-
- void inject(ChooseIdentityFragment fragment);
-
- void inject(ShowQrCodeFragment fragment);
-
- void inject(IntroductionActivity activity);
-
- void inject(ContactChooserFragment fragment);
-
- void inject(IntroductionMessageFragment fragment);
-
// Eager singleton load
void inject(AppModule.EagerSingletons init);
diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/org/briarproject/android/BaseActivity.java
index 1a93a006e..fa2e68d6b 100644
--- a/briar-android/src/org/briarproject/android/BaseActivity.java
+++ b/briar-android/src/org/briarproject/android/BaseActivity.java
@@ -1,21 +1,31 @@
package org.briarproject.android;
-import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
+import org.briarproject.android.controller.ActivityLifecycleController;
+
+import java.util.ArrayList;
+import java.util.List;
+
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
public abstract class BaseActivity extends AppCompatActivity {
- public final static String PREFS_NAME = "db";
- public final static String PREF_DB_KEY = "key";
- public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
+ protected ActivityComponent activityComponent;
+
+ private List lifecycleControllers =
+ new ArrayList();
+
+ public void addLifecycleController(
+ ActivityLifecycleController lifecycleController) {
+ this.lifecycleControllers.add(lifecycleController);
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -23,32 +33,52 @@ public abstract class BaseActivity extends AppCompatActivity {
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
- BriarApplication application = (BriarApplication) getApplication();
- injectActivity(application.getApplicationComponent());
+ AndroidComponent applicationComponent =
+ ((BriarApplication) getApplication()).getApplicationComponent();
+
+ activityComponent = DaggerActivityComponent.builder()
+ .androidComponent(applicationComponent)
+ .activityModule(getActivityModule())
+ .build();
+
+ injectActivity(activityComponent);
+
+ for (ActivityLifecycleController alc : lifecycleControllers) {
+ alc.onActivityCreate();
+ }
}
- public abstract void injectActivity(AndroidComponent component);
-
- private SharedPreferences getSharedPrefs() {
- return getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
+ // This exists to make test overrides easier
+ protected ActivityModule getActivityModule() {
+ return new ActivityModule(this);
}
- protected String getEncryptedDatabaseKey() {
- return getSharedPrefs().getString(PREF_DB_KEY, null);
+ @Override
+ protected void onResume() {
+ super.onResume();
+ for (ActivityLifecycleController alc : lifecycleControllers) {
+ alc.onActivityResume();
+ }
}
- protected void storeEncryptedDatabaseKey(final String hex) {
- SharedPreferences.Editor editor = getSharedPrefs().edit();
- editor.putString(PREF_DB_KEY, hex);
- editor.apply();
+ @Override
+ protected void onPause() {
+ super.onPause();
+ for (ActivityLifecycleController alc : lifecycleControllers) {
+ alc.onActivityPause();
+ }
}
- protected void clearSharedPrefs() {
- SharedPreferences.Editor editor = getSharedPrefs().edit();
- editor.clear();
- editor.apply();
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ for (ActivityLifecycleController alc : lifecycleControllers) {
+ alc.onActivityDestroy();
+ }
}
+ public abstract void injectActivity(ActivityComponent component);
+
protected void showSoftKeyboard(View view) {
Object o = getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).showSoftInput(view, SHOW_IMPLICIT);
@@ -59,4 +89,5 @@ public abstract class BaseActivity extends AppCompatActivity {
Object o = getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
}
+
}
diff --git a/briar-android/src/org/briarproject/android/BriarActivity.java b/briar-android/src/org/briarproject/android/BriarActivity.java
index 8043b1a14..0da52cf2b 100644
--- a/briar-android/src/org/briarproject/android/BriarActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarActivity.java
@@ -3,17 +3,11 @@ package org.briarproject.android;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
-import android.os.Bundle;
-import android.os.IBinder;
-import org.briarproject.android.BriarService.BriarBinder;
-import org.briarproject.android.BriarService.BriarServiceConnection;
+import org.briarproject.android.controller.BriarController;
+import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.panic.ExitActivity;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -37,33 +31,14 @@ public abstract class BriarActivity extends BaseActivity {
private static final Logger LOG =
Logger.getLogger(BriarActivity.class.getName());
- private final BriarServiceConnection serviceConnection =
- new BriarServiceConnection();
-
@Inject
- protected DatabaseConfig databaseConfig;
-
- private boolean bound = false;
-
- // Fields that are accessed from background threads must be volatile
- @Inject
- @DatabaseExecutor
- protected volatile Executor dbExecutor;
- @Inject
- protected volatile LifecycleManager lifecycleManager;
-
- @Override
- public void onCreate(Bundle state) {
- super.onCreate(state);
-
- if (databaseConfig.getEncryptionKey() != null) startAndBindService();
- }
+ protected BriarController briarController;
@Override
protected void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
if (request == REQUEST_PASSWORD) {
- if (result == RESULT_OK) startAndBindService();
+ if (result == RESULT_OK) briarController.startAndBindService();
else finish();
}
}
@@ -71,51 +46,22 @@ public abstract class BriarActivity extends BaseActivity {
@Override
public void onResume() {
super.onResume();
- if (databaseConfig.getEncryptionKey() == null && !isFinishing()) {
+ if (!briarController.hasEncryptionKey() && !isFinishing()) {
Intent i = new Intent(this, PasswordActivity.class);
i.setFlags(FLAG_ACTIVITY_NO_ANIMATION | FLAG_ACTIVITY_SINGLE_TOP);
startActivityForResult(i, REQUEST_PASSWORD);
}
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- unbindService();
- }
-
- private void startAndBindService() {
- startService(new Intent(this, BriarService.class));
- bound = bindService(new Intent(this, BriarService.class),
- serviceConnection, 0);
- }
-
- private void unbindService() {
- if (bound) unbindService(serviceConnection);
- }
-
protected void signOut(final boolean removeFromRecentApps) {
- // Use a new thread to avoid deadlock with executor tasks
- new Thread() {
+ briarController.signOut(new UiResultHandler(this) {
+
@Override
- public void run() {
- try {
- // Wait for the service to finish starting up
- IBinder binder = serviceConnection.waitForBinder();
- BriarService service = ((BriarBinder) binder).getService();
- service.waitForStartup();
- // Shut down the service and wait for it to shut down
- LOG.info("Shutting down service");
- service.shutdown();
- service.waitForShutdown();
- } catch (InterruptedException e) {
- LOG.warning("Interrupted while waiting for service");
- Thread.currentThread().interrupt();
- }
+ public void onResultUi(Void result) {
if (removeFromRecentApps) startExitActivity();
else finishAndExit();
}
- }.start();
+ });
}
protected void signOut() {
@@ -123,46 +69,29 @@ public abstract class BriarActivity extends BaseActivity {
}
private void startExitActivity() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Intent intent = new Intent(BriarActivity.this,
- ExitActivity.class);
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK
- | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | FLAG_ACTIVITY_NO_ANIMATION);
- if (Build.VERSION.SDK_INT >= 11)
- intent.addFlags(FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(intent);
- }
- });
+ Intent intent = new Intent(BriarActivity.this,
+ ExitActivity.class);
+ intent.addFlags(FLAG_ACTIVITY_NEW_TASK
+ | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | FLAG_ACTIVITY_NO_ANIMATION);
+ if (Build.VERSION.SDK_INT >= 11)
+ intent.addFlags(FLAG_ACTIVITY_CLEAR_TASK);
+ startActivity(intent);
}
private void finishAndExit() {
- runOnUiThread(new Runnable() {
- public void run() {
- if (Build.VERSION.SDK_INT >= 21) finishAndRemoveTask();
- else finish();
- LOG.info("Exiting");
- System.exit(0);
- }
- });
+ if (Build.VERSION.SDK_INT >= 21) finishAndRemoveTask();
+ else finish();
+ LOG.info("Exiting");
+ System.exit(0);
}
- public void runOnDbThread(final Runnable task) {
- dbExecutor.execute(new Runnable() {
- public void run() {
- try {
- lifecycleManager.waitForDatabase();
- task.run();
- } catch (InterruptedException e) {
- LOG.warning("Interrupted while waiting for database");
- Thread.currentThread().interrupt();
- }
- }
- });
+ @Deprecated
+ public void runOnDbThread(Runnable task) {
+ briarController.runOnDbThread(task);
}
+ @Deprecated
protected void finishOnUiThread() {
runOnUiThread(new Runnable() {
public void run() {
diff --git a/briar-android/src/org/briarproject/android/BriarApplication.java b/briar-android/src/org/briarproject/android/BriarApplication.java
index eec480309..cd28990ad 100644
--- a/briar-android/src/org/briarproject/android/BriarApplication.java
+++ b/briar-android/src/org/briarproject/android/BriarApplication.java
@@ -1,56 +1,10 @@
package org.briarproject.android;
-import android.app.Application;
-import android.content.Context;
+/**
+ * This exists so that the Application object will not necessarily be cast
+ * directly to the Briar application object.
+ */
+public interface BriarApplication {
-import org.acra.ACRA;
-import org.acra.ReportingInteractionMode;
-import org.acra.annotation.ReportsCrashes;
-import org.briarproject.CoreModule;
-import org.briarproject.R;
-import org.briarproject.android.util.BriarReportPrimer;
-import org.briarproject.android.util.BriarReportSenderFactory;
-
-import java.util.logging.Logger;
-
-@ReportsCrashes(
- reportPrimerClass = BriarReportPrimer.class,
- logcatArguments = {"-d", "-v", "time", "*:I"},
- reportSenderFactoryClasses = {BriarReportSenderFactory.class},
- mode = ReportingInteractionMode.DIALOG,
- reportDialogClass = DevReportActivity.class,
- resDialogOkToast = R.string.dev_report_saved,
- deleteOldUnsentReportsOnApplicationStart = false
-)
-public class BriarApplication extends Application {
-
- private static final Logger LOG =
- Logger.getLogger(BriarApplication.class.getName());
-
- private AndroidComponent applicationComponent;
-
- @Override
- protected void attachBaseContext(Context base) {
- super.attachBaseContext(base);
- ACRA.init(this);
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- LOG.info("Created");
-
- applicationComponent = DaggerAndroidComponent.builder()
- .appModule(new AppModule(this))
- .build();
-
- // We need to load the eager singletons directly after making the
- // dependency graphs
- CoreModule.initEagerSingletons(applicationComponent);
- AndroidEagerSingletons.initEagerSingletons(applicationComponent);
- }
-
- public AndroidComponent getApplicationComponent() {
- return applicationComponent;
- }
+ AndroidComponent getApplicationComponent();
}
diff --git a/briar-android/src/org/briarproject/android/BriarApplicationImpl.java b/briar-android/src/org/briarproject/android/BriarApplicationImpl.java
new file mode 100644
index 000000000..5abe5dff2
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/BriarApplicationImpl.java
@@ -0,0 +1,56 @@
+package org.briarproject.android;
+
+import android.app.Application;
+import android.content.Context;
+
+import org.acra.ACRA;
+import org.acra.ReportingInteractionMode;
+import org.acra.annotation.ReportsCrashes;
+import org.briarproject.CoreModule;
+import org.briarproject.R;
+import org.briarproject.android.util.BriarReportPrimer;
+import org.briarproject.android.util.BriarReportSenderFactory;
+
+import java.util.logging.Logger;
+
+@ReportsCrashes(
+ reportPrimerClass = BriarReportPrimer.class,
+ logcatArguments = {"-d", "-v", "time", "*:I"},
+ reportSenderFactoryClasses = {BriarReportSenderFactory.class},
+ mode = ReportingInteractionMode.DIALOG,
+ reportDialogClass = DevReportActivity.class,
+ resDialogOkToast = R.string.dev_report_saved,
+ deleteOldUnsentReportsOnApplicationStart = false
+)
+public class BriarApplicationImpl extends Application implements BriarApplication {
+
+ private static final Logger LOG =
+ Logger.getLogger(BriarApplicationImpl.class.getName());
+
+ private AndroidComponent applicationComponent;
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ ACRA.init(this);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ LOG.info("Created");
+
+ applicationComponent = DaggerAndroidComponent.builder()
+ .appModule(new AppModule(this))
+ .build();
+
+ // We need to load the eager singletons directly after making the
+ // dependency graphs
+ CoreModule.initEagerSingletons(applicationComponent);
+ AndroidEagerSingletons.initEagerSingletons(applicationComponent);
+ }
+
+ public AndroidComponent getApplicationComponent() {
+ return applicationComponent;
+ }
+}
diff --git a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
index 766a11e33..00fe0f39a 100644
--- a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
@@ -10,7 +10,6 @@ import org.briarproject.R;
import org.briarproject.android.contact.ContactListFragment;
import org.briarproject.android.forum.ForumListFragment;
import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.fragment.DashboardFragment;
/**
* This class should be extended by classes that wish to utilise fragments in
@@ -23,9 +22,7 @@ public abstract class BriarFragmentActivity extends BriarActivity {
if (actionBar == null)
return;
- if (fragmentTag.equals(DashboardFragment.TAG)) {
- actionBar.setTitle(R.string.dashboard_toolbar_header);
- } else if (fragmentTag.equals(ContactListFragment.TAG)) {
+ if (fragmentTag.equals(ContactListFragment.TAG)) {
actionBar.setTitle(R.string.contacts_toolbar_header);
} else if (fragmentTag.equals(ForumListFragment.TAG)) {
actionBar.setTitle(R.string.forums_toolbar_header);
@@ -52,7 +49,7 @@ public abstract class BriarFragmentActivity extends BriarActivity {
exiting. This models the typical Google navigation behaviour such
as in Gmail/Inbox.
*/
- startFragment(ContactListFragment.newInstance());
+ startFragment(activityComponent.newContactListFragment());
} else {
super.onBackPressed();
diff --git a/briar-android/src/org/briarproject/android/DevReportActivity.java b/briar-android/src/org/briarproject/android/DevReportActivity.java
index 2ea4e07e3..8f94b5a07 100644
--- a/briar-android/src/org/briarproject/android/DevReportActivity.java
+++ b/briar-android/src/org/briarproject/android/DevReportActivity.java
@@ -89,6 +89,7 @@ public class DevReportActivity extends BaseCrashReportDialog
((BriarApplication) getApplication()).getApplicationComponent()
.inject(this);
+
sharedPreferencesFactory =
new SharedPreferencesFactory(getApplicationContext(),
getConfig());
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
index 367bb12ba..4d18cd6ec 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -1,5 +1,6 @@
package org.briarproject.android;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -13,28 +14,18 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import org.briarproject.R;
-import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.forum.ForumListFragment;
+import org.briarproject.android.controller.NavDrawerController;
+import org.briarproject.android.controller.TransportStateListener;
+import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.util.CustomAnimations;
import org.briarproject.api.TransportId;
-import org.briarproject.android.api.ReferenceManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportDisabledEvent;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
import java.util.ArrayList;
import java.util.List;
@@ -42,11 +33,10 @@ import java.util.logging.Logger;
import javax.inject.Inject;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-
public class NavDrawerActivity extends BriarFragmentActivity implements
- BaseFragment.BaseFragmentListener, EventListener {
+ BaseFragment.BaseFragmentListener, TransportStateListener {
+
+ public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
public static final String INTENT_CONTACTS = "intent_contacts";
public static final String INTENT_FORUMS = "intent_forums";
@@ -57,20 +47,10 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
private ActionBarDrawerToggle drawerToggle;
@Inject
- protected ReferenceManager referenceManager;
- // Fields that are accessed from background threads must be volatile
- @Inject
- protected volatile IdentityManager identityManager;
- @Inject
- protected PluginManager pluginManager;
- @Inject
- protected volatile EventBus eventBus;
+ protected NavDrawerController controller;
private Toolbar toolbar;
private DrawerLayout drawerLayout;
- private Button contactButton;
- private Button forumsButton;
- private Button settingsButton;
private GridView transportsView;
private TextView progressTitle;
private ViewGroup progressViewGroup;
@@ -85,14 +65,14 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
checkAuthorHandle(intent);
clearBackStack();
if (intent.getBooleanExtra(INTENT_FORUMS, false))
- startFragment(ForumListFragment.newInstance());
+ startFragment(activityComponent.newForumListFragment());
else if (intent.getBooleanExtra(INTENT_CONTACTS, false))
- startFragment(ContactListFragment.newInstance());
+ startFragment(activityComponent.newContactListFragment());
}
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -106,14 +86,11 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
setContentView(R.layout.activity_nav_drawer);
- toolbar = (Toolbar)findViewById(R.id.toolbar);
- drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
- contactButton = (Button)findViewById(R.id.nav_btn_contacts);
- forumsButton = (Button)findViewById(R.id.nav_btn_forums);
- settingsButton = (Button)findViewById(R.id.nav_btn_settings);
- transportsView = (GridView)findViewById(R.id.transportsView);
- progressTitle = (TextView)findViewById(R.id.title_progress_bar);
- progressViewGroup = (ViewGroup)findViewById(R.id.container_progress);
+ toolbar = (Toolbar) findViewById(R.id.toolbar);
+ drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ transportsView = (GridView) findViewById(R.id.transportsView);
+ progressTitle = (TextView) findViewById(R.id.title_progress_bar);
+ progressViewGroup = (ViewGroup) findViewById(R.id.container_progress);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -133,7 +110,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
}
};
drawerLayout.setDrawerListener(drawerToggle);
- if (state == null) startFragment(ContactListFragment.newInstance());
+ if (state == null) startFragment(activityComponent.newContactListFragment());
checkAuthorHandle(getIntent());
initializeTransports(getLayoutInflater());
@@ -143,8 +120,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
}
private void welcomeMessageCheck() {
- SharedPreferences prefs = getSharedPreferences(PREFS_NAME,
- MODE_PRIVATE);
+ SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
if (!prefs.getBoolean(PREF_SEEN_WELCOME_MESSAGE, false)) {
showMessageDialog(R.string.dialog_title_welcome,
R.string.dialog_welcome_message);
@@ -155,22 +131,14 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
@Override
public void onResume() {
super.onResume();
- eventBus.addListener(this);
updateTransports();
}
- @Override
- protected void onPause() {
- super.onPause();
- eventBus.removeListener(this);
- }
-
private void checkAuthorHandle(Intent intent) {
long handle = intent.getLongExtra(KEY_LOCAL_AUTHOR_HANDLE, -1);
if (handle != -1) {
+ LocalAuthor a = controller.removeAuthorHandle(handle);
// The activity was launched from the setup wizard
- LocalAuthor a = referenceManager.removeReference(handle,
- LocalAuthor.class);
if (a != null) {
showLoadingScreen(true, R.string.progress_title_please_wait);
storeLocalAuthor(a);
@@ -189,27 +157,13 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
}
private void storeLocalAuthor(final LocalAuthor a) {
- runOnDbThread(new Runnable() {
- public void run() {
- try {
- long now = System.currentTimeMillis();
- identityManager.addLocalAuthor(a);
- long duration = System.currentTimeMillis() - now;
- if (LOG.isLoggable(INFO))
- LOG.info("Storing author took " + duration + " ms");
-
- runOnUiThread(new Runnable() {
- public void run() {
- hideLoadingScreen();
- }
- });
-
- } catch (DbException e) {
- if (LOG.isLoggable(WARNING))
- LOG.log(WARNING, e.toString(), e);
- }
- }
- });
+ controller.storeLocalAuthor(a,
+ new UiResultHandler(this) {
+ @Override
+ public void onResultUi(Void result) {
+ hideLoadingScreen();
+ }
+ });
}
public void onNavigationClick(View view) {
@@ -217,10 +171,10 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
clearBackStack();
switch (view.getId()) {
case R.id.nav_btn_contacts:
- startFragment(ContactListFragment.newInstance());
+ startFragment(activityComponent.newContactListFragment());
break;
case R.id.nav_btn_forums:
- startFragment(ForumListFragment.newInstance());
+ startFragment(activityComponent.newForumListFragment());
break;
case R.id.nav_btn_settings:
startActivity(new Intent(this, SettingsActivity.class));
@@ -243,7 +197,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
}
@Override
- protected void onPostCreate(Bundle savedInstanceState) {
+ public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@@ -285,24 +239,21 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
Transport tor = new Transport();
tor.id = new TransportId("tor");
- Plugin torPlugin = pluginManager.getPlugin(tor.id);
- tor.enabled = torPlugin != null && torPlugin.isRunning();
+ tor.enabled = controller.isTransportRunning(tor.id);
tor.iconId = R.drawable.transport_tor;
tor.textId = R.string.transport_tor;
transports.add(tor);
Transport bt = new Transport();
bt.id = new TransportId("bt");
- Plugin btPlugin = pluginManager.getPlugin(bt.id);
- bt.enabled = btPlugin != null && btPlugin.isRunning();
+ bt.enabled = controller.isTransportRunning(bt.id);
bt.iconId = R.drawable.transport_bt;
bt.textId = R.string.transport_bt;
transports.add(bt);
Transport lan = new Transport();
lan.id = new TransportId("lan");
- Plugin lanPlugin = pluginManager.getPlugin(lan.id);
- lan.enabled = lanPlugin != null && lanPlugin.isRunning();
+ lan.enabled = controller.isTransportRunning(lan.id);
lan.iconId = R.drawable.transport_lan;
lan.textId = R.string.transport_lan;
transports.add(lan);
@@ -369,27 +320,14 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
private void updateTransports() {
if (transports == null || transportsAdapter == null) return;
for (Transport t : transports) {
- Plugin plugin = pluginManager.getPlugin(t.id);
- t.enabled = plugin != null && plugin.isRunning();
+ t.enabled = controller.isTransportRunning(t.id);
}
transportsAdapter.notifyDataSetChanged();
}
@Override
- public void eventOccurred(Event e) {
- if (e instanceof TransportEnabledEvent) {
- TransportId id = ((TransportEnabledEvent) e).getTransportId();
- if (LOG.isLoggable(INFO)) {
- LOG.info("TransportEnabledEvent: " + id.getString());
- }
- setTransport(id, true);
- } else if (e instanceof TransportDisabledEvent) {
- TransportId id = ((TransportDisabledEvent) e).getTransportId();
- if (LOG.isLoggable(INFO)) {
- LOG.info("TransportDisabledEvent: " + id.getString());
- }
- setTransport(id, false);
- }
+ public void stateUpdate(TransportId id, boolean enabled) {
+ setTransport(id, enabled);
}
private static class Transport {
diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/org/briarproject/android/PasswordActivity.java
index 33f14f206..346b2f2cd 100644
--- a/briar-android/src/org/briarproject/android/PasswordActivity.java
+++ b/briar-android/src/org/briarproject/android/PasswordActivity.java
@@ -3,6 +3,7 @@ package org.briarproject.android;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
@@ -16,14 +17,9 @@ import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import org.briarproject.R;
+import org.briarproject.android.controller.PasswordController;
+import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.util.StringUtils;
-
-import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -34,28 +30,22 @@ import static android.view.View.VISIBLE;
public class PasswordActivity extends BaseActivity {
- @Inject @CryptoExecutor protected Executor cryptoExecutor;
private Button signInButton;
private ProgressBar progress;
private TextInputLayout input;
private EditText password;
- private byte[] encrypted;
-
- // Fields that are accessed from background threads must be volatile
- @Inject protected volatile CryptoComponent crypto;
- @Inject protected volatile DatabaseConfig databaseConfig;
+ @Inject
+ PasswordController passwordController;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
- String hex = getEncryptedDatabaseKey();
- if (hex == null || !databaseConfig.databaseExists()) {
+ if (!passwordController.initialized()) {
clearSharedPrefsAndDeleteEverything();
return;
}
- encrypted = StringUtils.fromHexString(hex);
setContentView(R.layout.activity_password);
signInButton = (Button) findViewById(R.id.btn_sign_in);
@@ -66,8 +56,7 @@ public class PasswordActivity extends BaseActivity {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
- hideSoftKeyboard(password);
- validatePassword(encrypted, password.getText());
+ validatePassword();
return true;
}
});
@@ -90,7 +79,7 @@ public class PasswordActivity extends BaseActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -103,7 +92,7 @@ public class PasswordActivity extends BaseActivity {
}
private void clearSharedPrefsAndDeleteEverything() {
- clearSharedPrefs();
+ passwordController.clearPrefs();
AndroidUtils.deleteAppData(this);
setResult(RESULT_CANCELED);
startActivity(new Intent(this, SetupActivity.class));
@@ -111,7 +100,7 @@ public class PasswordActivity extends BaseActivity {
}
public void onSignInClick(View v) {
- validatePassword(encrypted, password.getText());
+ validatePassword();
}
public void onForgottenPasswordClick(View v) {
@@ -132,47 +121,33 @@ public class PasswordActivity extends BaseActivity {
dialog.show();
}
- private void validatePassword(final byte[] encrypted, Editable e) {
+ private void validatePassword() {
hideSoftKeyboard(password);
- // Replace the button with a progress bar
signInButton.setVisibility(INVISIBLE);
progress.setVisibility(VISIBLE);
- // Decrypt the database key in a background thread
- final String password = e.toString();
- cryptoExecutor.execute(new Runnable() {
- public void run() {
- byte[] key = crypto.decryptWithPassword(encrypted, password);
- if (key == null) {
- tryAgain();
- } else {
- databaseConfig.setEncryptionKey(new SecretKey(key));
- setResultAndFinish();
- }
- }
- });
+ passwordController.validatePassword(password.getText().toString(),
+ new UiResultHandler(this) {
+ @Override
+ public void onResultUi(@NonNull Boolean result) {
+ if (result) {
+ setResult(RESULT_OK);
+ finish();
+ } else {
+ tryAgain();
+ }
+ }
+ });
}
private void tryAgain() {
- runOnUiThread(new Runnable() {
- public void run() {
- AndroidUtils.setError(input, getString(R.string.try_again),
- true);
- signInButton.setVisibility(VISIBLE);
- progress.setVisibility(INVISIBLE);
- password.setText("");
+ AndroidUtils.setError(input, getString(R.string.try_again),
+ true);
+ signInButton.setVisibility(VISIBLE);
+ progress.setVisibility(INVISIBLE);
+ password.setText("");
- // show the keyboard again
- showSoftKeyboard(password);
- }
- });
+ // show the keyboard again
+ showSoftKeyboard(password);
}
- private void setResultAndFinish() {
- runOnUiThread(new Runnable() {
- public void run() {
- setResult(RESULT_OK);
- finish();
- }
- });
- }
}
diff --git a/briar-android/src/org/briarproject/android/SettingsActivity.java b/briar-android/src/org/briarproject/android/SettingsActivity.java
index e270578a7..bb783a065 100644
--- a/briar-android/src/org/briarproject/android/SettingsActivity.java
+++ b/briar-android/src/org/briarproject/android/SettingsActivity.java
@@ -34,7 +34,7 @@ public class SettingsActivity extends BriarActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/org/briarproject/android/SetupActivity.java
index 6caf20e5a..13bb49f4b 100644
--- a/briar-android/src/org/briarproject/android/SetupActivity.java
+++ b/briar-android/src/org/briarproject/android/SetupActivity.java
@@ -2,6 +2,7 @@ package org.briarproject.android;
import android.content.Intent;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextWatcher;
@@ -15,29 +16,18 @@ import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import org.briarproject.R;
+import org.briarproject.android.controller.SetupController;
+import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.util.StrengthMeter;
-import org.briarproject.android.api.ReferenceManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.util.StringUtils;
-import java.util.concurrent.Executor;
-import java.util.logging.Logger;
-
import javax.inject.Inject;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static java.util.logging.Level.INFO;
import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
@@ -45,17 +35,8 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENG
public class SetupActivity extends BaseActivity implements OnClickListener,
OnEditorActionListener {
- private static final Logger LOG =
- Logger.getLogger(SetupActivity.class.getName());
-
- @Inject @CryptoExecutor protected Executor cryptoExecutor;
- @Inject protected PasswordStrengthEstimator strengthEstimator;
-
- // Fields that are accessed from background threads must be volatile
- @Inject protected volatile CryptoComponent crypto;
- @Inject protected volatile DatabaseConfig databaseConfig;
- @Inject protected volatile AuthorFactory authorFactory;
- @Inject protected volatile ReferenceManager referenceManager;
+ @Inject
+ protected SetupController setupController;
TextInputLayout nicknameEntryWrapper;
TextInputLayout passwordEntryWrapper;
@@ -72,15 +53,18 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
super.onCreate(state);
setContentView(R.layout.activity_setup);
- nicknameEntryWrapper = (TextInputLayout)findViewById(R.id.nickname_entry_wrapper);
- passwordEntryWrapper = (TextInputLayout)findViewById(R.id.password_entry_wrapper);
- passwordConfirmationWrapper = (TextInputLayout)findViewById(R.id.password_confirm_wrapper);
- nicknameEntry = (EditText)findViewById(R.id.nickname_entry);
- passwordEntry = (EditText)findViewById(R.id.password_entry);
- passwordConfirmation = (EditText)findViewById(R.id.password_confirm);
- strengthMeter = (StrengthMeter)findViewById(R.id.strength_meter);
- createAccountButton = (Button)findViewById(R.id.create_account);
- progress = (ProgressBar)findViewById(R.id.progress_wheel);
+ nicknameEntryWrapper =
+ (TextInputLayout) findViewById(R.id.nickname_entry_wrapper);
+ passwordEntryWrapper =
+ (TextInputLayout) findViewById(R.id.password_entry_wrapper);
+ passwordConfirmationWrapper =
+ (TextInputLayout) findViewById(R.id.password_confirm_wrapper);
+ nicknameEntry = (EditText) findViewById(R.id.nickname_entry);
+ passwordEntry = (EditText) findViewById(R.id.password_entry);
+ passwordConfirmation = (EditText) findViewById(R.id.password_confirm);
+ strengthMeter = (StrengthMeter) findViewById(R.id.strength_meter);
+ createAccountButton = (Button) findViewById(R.id.create_account);
+ progress = (ProgressBar) findViewById(R.id.progress_wheel);
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
@@ -109,7 +93,7 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -123,7 +107,7 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
String firstPassword = passwordEntry.getText().toString();
String secondPassword = passwordConfirmation.getText().toString();
boolean passwordsMatch = firstPassword.equals(secondPassword);
- float strength = strengthEstimator.estimateStrength(firstPassword);
+ float strength = setupController.estimatePasswordStrength(firstPassword);
strengthMeter.setStrength(strength);
AndroidUtils.setError(nicknameEntryWrapper,
getString(R.string.name_too_long),
@@ -141,6 +125,7 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
hideSoftKeyboard(v);
+
return true;
}
@@ -150,52 +135,21 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
progress.setVisibility(VISIBLE);
final String nickname = nicknameEntry.getText().toString();
final String password = passwordEntry.getText().toString();
- // Store the DB key and create the identity in a background thread
- cryptoExecutor.execute(new Runnable() {
- public void run() {
- SecretKey key = crypto.generateSecretKey();
- databaseConfig.setEncryptionKey(key);
- String hex = encryptDatabaseKey(key, password);
- storeEncryptedDatabaseKey(hex);
- LocalAuthor localAuthor = createLocalAuthor(nickname);
- showDashboard(referenceManager.putReference(localAuthor,
- LocalAuthor.class));
- }
- });
+ setupController.createIdentity(nickname, password,
+ new UiResultHandler(this) {
+ @Override
+ public void onResultUi(@NonNull Long result) {
+ showMain(result);
+ }
+ });
}
- private String encryptDatabaseKey(SecretKey key, String password) {
- long now = System.currentTimeMillis();
- byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
- long duration = System.currentTimeMillis() - now;
- if (LOG.isLoggable(INFO))
- LOG.info("Key derivation took " + duration + " ms");
- return StringUtils.toHexString(encrypted);
- }
-
- private LocalAuthor createLocalAuthor(String nickname) {
- long now = System.currentTimeMillis();
- KeyPair keyPair = crypto.generateSignatureKeyPair();
- byte[] publicKey = keyPair.getPublic().getEncoded();
- byte[] privateKey = keyPair.getPrivate().getEncoded();
- LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
- publicKey, privateKey);
- long duration = System.currentTimeMillis() - now;
- if (LOG.isLoggable(INFO))
- LOG.info("Identity creation took " + duration + " ms");
- return localAuthor;
- }
-
- private void showDashboard(final long handle) {
- runOnUiThread(new Runnable() {
- public void run() {
- Intent i = new Intent(SetupActivity.this,
- NavDrawerActivity.class);
- i.putExtra(BriarActivity.KEY_LOCAL_AUTHOR_HANDLE, handle);
- i.setFlags(FLAG_ACTIVITY_NEW_TASK);
- startActivity(i);
- finish();
- }
- });
+ private void showMain(final long handle) {
+ Intent i = new Intent(SetupActivity.this,
+ NavDrawerActivity.class);
+ i.putExtra(BriarActivity.KEY_LOCAL_AUTHOR_HANDLE, handle);
+ i.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ startActivity(i);
+ finish();
}
}
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
index 0ba0d47b9..e4ff0b941 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
@@ -10,8 +10,8 @@ import android.support.v7.preference.PreferenceManager;
import org.briarproject.R;
import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.android.controller.ConfigController;
import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.db.DatabaseConfig;
import java.util.logging.Logger;
@@ -29,7 +29,7 @@ public class SplashScreenActivity extends BaseActivity {
private static final long EXPIRY_DATE = 1464735600 * 1000L;
@Inject
- protected DatabaseConfig dbConfig;
+ ConfigController configController;
@Inject
protected AndroidExecutor androidExecutor;
@@ -56,7 +56,7 @@ public class SplashScreenActivity extends BaseActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -65,11 +65,11 @@ public class SplashScreenActivity extends BaseActivity {
LOG.info("Expired");
startActivity(new Intent(this, ExpiredActivity.class));
} else {
- String hex = getEncryptedDatabaseKey();
- if (hex != null && dbConfig.databaseExists()) {
+ if (configController.initialized()) {
startActivity(new Intent(this, NavDrawerActivity.class));
} else {
- clearSharedPrefs();
+ configController.clearPrefs();
+ // TODO replace this static call with a controller method
AndroidUtils.deleteAppData(this);
startActivity(new Intent(this, SetupActivity.class));
}
diff --git a/briar-android/src/org/briarproject/android/StartupFailureActivity.java b/briar-android/src/org/briarproject/android/StartupFailureActivity.java
index 5180c33c2..b25836939 100644
--- a/briar-android/src/org/briarproject/android/StartupFailureActivity.java
+++ b/briar-android/src/org/briarproject/android/StartupFailureActivity.java
@@ -20,7 +20,7 @@ public class StartupFailureActivity extends BaseActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
}
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index 82137d92a..5e7e017cd 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -12,8 +12,7 @@ import android.view.View;
import android.view.ViewGroup;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.fragment.BaseEventFragment;
+import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.keyagreement.KeyAgreementActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
@@ -28,6 +27,7 @@ import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.ContactStatusChangedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageValidatedEvent;
import org.briarproject.api.forum.ForumInvitationMessage;
import org.briarproject.api.forum.ForumSharingManager;
@@ -52,22 +52,13 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.BriarActivity.GROUP_ID;
-public class ContactListFragment extends BaseEventFragment {
+public class ContactListFragment extends BaseFragment implements EventListener {
private static final Logger LOG =
Logger.getLogger(ContactListFragment.class.getName());
public final static String TAG = "ContactListFragment";
- public static ContactListFragment newInstance() {
-
- Bundle args = new Bundle();
-
- ContactListFragment fragment = new ContactListFragment();
- fragment.setArguments(args);
- return fragment;
- }
-
@Override
public String getUniqueTag() {
return TAG;
@@ -92,9 +83,10 @@ public class ContactListFragment extends BaseEventFragment {
@Inject
protected volatile EventBus eventBus;
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
+
+ @Inject
+ public ContactListFragment() {
+
}
@Nullable
@@ -155,7 +147,7 @@ public class ContactListFragment extends BaseEventFragment {
@Override
public void onResume() {
super.onResume();
-
+ eventBus.addListener(this);
loadContacts();
}
@@ -163,6 +155,7 @@ public class ContactListFragment extends BaseEventFragment {
public void onPause() {
super.onPause();
adapter.clear();
+ eventBus.removeListener(this);
}
private void loadContacts() {
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index 5a62bef1f..045c58e7f 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -23,6 +23,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.AndroidNotificationManager;
@@ -157,7 +158,7 @@ public class ConversationActivity extends BriarActivity
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java b/briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java
new file mode 100644
index 000000000..68b15592c
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java
@@ -0,0 +1,11 @@
+package org.briarproject.android.controller;
+
+public interface ActivityLifecycleController {
+ void onActivityCreate();
+
+ void onActivityResume();
+
+ void onActivityPause();
+
+ void onActivityDestroy();
+}
diff --git a/briar-android/src/org/briarproject/android/controller/BriarController.java b/briar-android/src/org/briarproject/android/controller/BriarController.java
new file mode 100644
index 000000000..4be89b108
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/BriarController.java
@@ -0,0 +1,14 @@
+package org.briarproject.android.controller;
+
+
+import org.briarproject.android.controller.handler.ResultHandler;
+
+public interface BriarController extends ActivityLifecycleController {
+ void runOnDbThread(final Runnable task);
+
+ void startAndBindService();
+
+ boolean hasEncryptionKey();
+
+ void signOut(ResultHandler eventHandler);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java b/briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java
new file mode 100644
index 000000000..fd24291c7
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java
@@ -0,0 +1,118 @@
+package org.briarproject.android.controller;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.IBinder;
+import android.support.annotation.CallSuper;
+
+import org.briarproject.android.BriarService;
+import org.briarproject.android.BriarService.BriarServiceConnection;
+import org.briarproject.android.controller.handler.ResultHandler;
+import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.db.DatabaseExecutor;
+import org.briarproject.api.lifecycle.LifecycleManager;
+
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+public class BriarControllerImpl implements BriarController {
+
+ private static final Logger LOG =
+ Logger.getLogger(BriarControllerImpl.class.getName());
+
+ @Inject
+ protected BriarServiceConnection serviceConnection;
+ @Inject
+ protected DatabaseConfig databaseConfig;
+ // Fields that are accessed from background threads must be volatile
+ @Inject
+ @DatabaseExecutor
+ protected volatile Executor dbExecutor;
+ @Inject
+ protected volatile LifecycleManager lifecycleManager;
+ @Inject
+ protected Activity activity;
+
+ private boolean bound = false;
+
+ @Inject
+ public BriarControllerImpl() {
+
+ }
+
+ @Override
+ @CallSuper
+ public void onActivityCreate() {
+ if (databaseConfig.getEncryptionKey() != null) startAndBindService();
+ }
+
+ @Override
+ @CallSuper
+ public void onActivityResume() {
+ }
+
+ @Override
+ @CallSuper
+ public void onActivityPause() {
+ }
+
+ @Override
+ @CallSuper
+ public void onActivityDestroy() {
+ unbindService();
+ }
+
+ public void startAndBindService() {
+ activity.startService(new Intent(activity, BriarService.class));
+ bound = activity.bindService(new Intent(activity, BriarService.class),
+ serviceConnection, 0);
+ }
+
+ @Override
+ public boolean hasEncryptionKey() {
+ return databaseConfig.getEncryptionKey() != null;
+ }
+
+ @Override
+ public void signOut(final ResultHandler eventHandler) {
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ // Wait for the service to finish starting up
+ IBinder binder = serviceConnection.waitForBinder();
+ BriarService service = ((BriarService.BriarBinder) binder).getService();
+ service.waitForStartup();
+ // Shut down the service and wait for it to shut down
+ LOG.info("Shutting down service");
+ service.shutdown();
+ service.waitForShutdown();
+ } catch (InterruptedException e) {
+ LOG.warning("Interrupted while waiting for service");
+ }
+ eventHandler.onResult(null);
+ }
+ }.start();
+ }
+
+ private void unbindService() {
+ if (bound) activity.unbindService(serviceConnection);
+ }
+
+ public void runOnDbThread(final Runnable task) {
+ dbExecutor.execute(new Runnable() {
+ public void run() {
+ try {
+ lifecycleManager.waitForDatabase();
+ task.run();
+ } catch (InterruptedException e) {
+ LOG.warning("Interrupted while waiting for database");
+ Thread.currentThread().interrupt();
+ }
+ }
+ });
+ }
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/ConfigController.java b/briar-android/src/org/briarproject/android/controller/ConfigController.java
new file mode 100644
index 000000000..cddbc1bc6
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/ConfigController.java
@@ -0,0 +1,9 @@
+package org.briarproject.android.controller;
+
+public interface ConfigController {
+ String getEncryptedDatabaseKey();
+
+ void clearPrefs();
+
+ boolean initialized();
+}
diff --git a/briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java b/briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java
new file mode 100644
index 000000000..b823b98e2
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java
@@ -0,0 +1,41 @@
+package org.briarproject.android.controller;
+
+import android.content.SharedPreferences;
+
+import org.briarproject.api.db.DatabaseConfig;
+
+import javax.inject.Inject;
+
+public class ConfigControllerImpl implements ConfigController {
+
+ private final static String PREF_DB_KEY = "key";
+
+ @Inject
+ protected SharedPreferences briarPrefs;
+ @Inject
+ protected volatile DatabaseConfig databaseConfig;
+
+ @Inject
+ public ConfigControllerImpl() {
+
+ }
+
+ public String getEncryptedDatabaseKey() {
+ return briarPrefs.getString(PREF_DB_KEY, null);
+ }
+
+ public void clearPrefs() {
+ SharedPreferences.Editor editor = briarPrefs.edit();
+ editor.clear();
+ editor.apply();
+ }
+
+ @Override
+ public boolean initialized() {
+ String hex = getEncryptedDatabaseKey();
+ if (hex != null && databaseConfig.databaseExists()) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/briar-android/src/org/briarproject/android/controller/NavDrawerController.java b/briar-android/src/org/briarproject/android/controller/NavDrawerController.java
new file mode 100644
index 000000000..56d48b1ca
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/NavDrawerController.java
@@ -0,0 +1,16 @@
+package org.briarproject.android.controller;
+
+import org.briarproject.android.controller.handler.UiResultHandler;
+import org.briarproject.api.TransportId;
+import org.briarproject.api.identity.LocalAuthor;
+
+public interface NavDrawerController extends BriarController {
+ void setTransportListener(TransportStateListener transportListener);
+
+ boolean isTransportRunning(TransportId transportId);
+
+ void storeLocalAuthor(LocalAuthor author,
+ UiResultHandler resultHandler);
+
+ LocalAuthor removeAuthorHandle(long handle);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java b/briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java
new file mode 100644
index 000000000..4be03f949
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java
@@ -0,0 +1,136 @@
+package org.briarproject.android.controller;
+
+import android.app.Activity;
+
+import org.briarproject.android.api.ReferenceManager;
+import org.briarproject.android.controller.handler.UiResultHandler;
+import org.briarproject.api.TransportId;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.event.Event;
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
+import org.briarproject.api.event.TransportDisabledEvent;
+import org.briarproject.api.event.TransportEnabledEvent;
+import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.identity.LocalAuthor;
+import org.briarproject.api.plugins.Plugin;
+import org.briarproject.api.plugins.PluginManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+
+public class NavDrawerControllerImpl extends BriarControllerImpl
+ implements NavDrawerController, EventListener {
+
+ private static final Logger LOG =
+ Logger.getLogger(NavDrawerControllerImpl.class.getName());
+
+ @Inject
+ protected ReferenceManager referenceManager;
+ @Inject
+ protected volatile IdentityManager identityManager;
+ @Inject
+ protected PluginManager pluginManager;
+ @Inject
+ protected EventBus eventBus;
+ @Inject
+ protected Activity activity;
+
+ private List transports = new ArrayList();
+
+ private TransportStateListener transportStateListener;
+
+ @Inject
+ public NavDrawerControllerImpl() {
+
+ }
+
+ @Override
+ public void onActivityCreate() {
+ super.onActivityCreate();
+ }
+
+ @Override
+ public void onActivityResume() {
+ super.onActivityResume();
+ eventBus.addListener(this);
+ }
+
+ @Override
+ public void onActivityPause() {
+ super.onActivityPause();
+ eventBus.removeListener(this);
+ }
+
+ @Override
+ public void eventOccurred(Event e) {
+ if (e instanceof TransportEnabledEvent) {
+ TransportId id = ((TransportEnabledEvent) e).getTransportId();
+ if (LOG.isLoggable(INFO)) {
+ LOG.info("TransportEnabledEvent: " + id.getString());
+ }
+ transportStateUpdate(id, true);
+ } else if (e instanceof TransportDisabledEvent) {
+ TransportId id = ((TransportDisabledEvent) e).getTransportId();
+ if (LOG.isLoggable(INFO)) {
+ LOG.info("TransportDisabledEvent: " + id.getString());
+ }
+ transportStateUpdate(id, false);
+ }
+ }
+
+ private void transportStateUpdate(final TransportId id,
+ final boolean enabled) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (transportStateListener != null) {
+ transportStateListener.stateUpdate(id, enabled);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setTransportListener(TransportStateListener transportListener) {
+ this.transportStateListener = transportListener;
+ }
+
+ @Override
+ public boolean isTransportRunning(TransportId transportId) {
+ Plugin plugin = pluginManager.getPlugin(transportId);
+ return plugin != null && plugin.isRunning();
+ }
+
+ @Override
+ public void storeLocalAuthor(final LocalAuthor author,
+ final UiResultHandler resultHandler) {
+ runOnDbThread(new Runnable() {
+ public void run() {
+ try {
+ long now = System.currentTimeMillis();
+ identityManager.addLocalAuthor(author);
+ long duration = System.currentTimeMillis() - now;
+ if (LOG.isLoggable(INFO))
+ LOG.info("Storing author took " + duration + " ms");
+ resultHandler.onResult(null);
+ } catch (final DbException e) {
+ if (LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public LocalAuthor removeAuthorHandle(long handle) {
+ return referenceManager.removeReference(handle,
+ LocalAuthor.class);
+ }
+}
diff --git a/briar-android/src/org/briarproject/android/controller/PasswordController.java b/briar-android/src/org/briarproject/android/controller/PasswordController.java
new file mode 100644
index 000000000..bf1c9b230
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/PasswordController.java
@@ -0,0 +1,8 @@
+package org.briarproject.android.controller;
+
+import org.briarproject.android.controller.handler.ResultHandler;
+
+public interface PasswordController extends ConfigController {
+ void validatePassword(String password,
+ ResultHandler resultHandler);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java b/briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java
new file mode 100644
index 000000000..12f7e4240
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java
@@ -0,0 +1,54 @@
+package org.briarproject.android.controller;
+
+import android.app.Activity;
+
+import org.briarproject.android.controller.handler.ResultHandler;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.CryptoExecutor;
+import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.util.StringUtils;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+public class PasswordControllerImpl extends ConfigControllerImpl
+ implements PasswordController {
+
+ @Inject
+ @CryptoExecutor
+ protected Executor cryptoExecutor;
+ @Inject
+ protected CryptoComponent crypto;
+ @Inject
+ protected Activity activity;
+
+ @Inject
+ public PasswordControllerImpl() {
+
+ }
+
+ @Override
+ public void validatePassword(final String password,
+ final ResultHandler resultHandler) {
+ final byte[] encrypted = getEncryptedKey();
+ cryptoExecutor.execute(new Runnable() {
+ public void run() {
+ byte[] key = crypto.decryptWithPassword(encrypted, password);
+ if (key == null) {
+ resultHandler.onResult(false);
+ } else {
+ databaseConfig.setEncryptionKey(new SecretKey(key));
+ resultHandler.onResult(true);
+ }
+ }
+ });
+ }
+
+ private byte[] getEncryptedKey() {
+ String hex = getEncryptedDatabaseKey();
+ if (hex == null)
+ throw new IllegalStateException("Encrypted database key is null.");
+ return StringUtils.fromHexString(hex);
+ }
+}
diff --git a/briar-android/src/org/briarproject/android/controller/SetupController.java b/briar-android/src/org/briarproject/android/controller/SetupController.java
new file mode 100644
index 000000000..476db0f5e
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/SetupController.java
@@ -0,0 +1,10 @@
+package org.briarproject.android.controller;
+
+import org.briarproject.android.controller.handler.ResultHandler;
+
+public interface SetupController {
+ float estimatePasswordStrength(String password);
+
+ void createIdentity(String nickname, String password,
+ ResultHandler resultHandler);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java b/briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java
new file mode 100644
index 000000000..29bed6d19
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java
@@ -0,0 +1,107 @@
+package org.briarproject.android.controller;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+
+import org.briarproject.android.api.ReferenceManager;
+import org.briarproject.android.controller.handler.ResultHandler;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.CryptoExecutor;
+import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.LocalAuthor;
+import org.briarproject.util.StringUtils;
+
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Level.INFO;
+
+public class SetupControllerImpl implements SetupController {
+
+ private static final Logger LOG =
+ Logger.getLogger(SetupControllerImpl.class.getName());
+
+ private final static String PREF_DB_KEY = "key";
+
+ @Inject
+ @CryptoExecutor
+ protected Executor cryptoExecutor;
+ @Inject
+ protected PasswordStrengthEstimator strengthEstimator;
+
+ // Fields that are accessed from background threads must be volatile
+ @Inject
+ protected volatile CryptoComponent crypto;
+ @Inject
+ protected volatile DatabaseConfig databaseConfig;
+ @Inject
+ protected volatile AuthorFactory authorFactory;
+ @Inject
+ protected volatile ReferenceManager referenceManager;
+ @Inject
+ protected Activity activity;
+ @Inject
+ protected SharedPreferences briarPrefs;
+
+ @Inject
+ public SetupControllerImpl() {
+
+ }
+
+ private String encryptDatabaseKey(SecretKey key, String password) {
+ long now = System.currentTimeMillis();
+ byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
+ long duration = System.currentTimeMillis() - now;
+ if (LOG.isLoggable(INFO))
+ LOG.info("Key derivation took " + duration + " ms");
+ return StringUtils.toHexString(encrypted);
+ }
+
+ private LocalAuthor createLocalAuthor(String nickname) {
+ long now = System.currentTimeMillis();
+ KeyPair keyPair = crypto.generateSignatureKeyPair();
+ byte[] publicKey = keyPair.getPublic().getEncoded();
+ byte[] privateKey = keyPair.getPrivate().getEncoded();
+ LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
+ publicKey, privateKey);
+ long duration = System.currentTimeMillis() - now;
+ if (LOG.isLoggable(INFO))
+ LOG.info("Identity creation took " + duration + " ms");
+ return localAuthor;
+ }
+
+ @Override
+ public float estimatePasswordStrength(String password) {
+ return strengthEstimator.estimateStrength(password);
+ }
+
+ @Override
+ public void createIdentity(final String nickname, final String password,
+ final ResultHandler resultHandler) {
+ cryptoExecutor.execute(new Runnable() {
+ public void run() {
+ SecretKey key = crypto.generateSecretKey();
+ databaseConfig.setEncryptionKey(key);
+ String hex = encryptDatabaseKey(key, password);
+ storeEncryptedDatabaseKey(hex);
+ LocalAuthor localAuthor = createLocalAuthor(nickname);
+ long handle = referenceManager.putReference(localAuthor,
+ LocalAuthor.class);
+ resultHandler.onResult(handle);
+ }
+ });
+ }
+
+ private void storeEncryptedDatabaseKey(final String hex) {
+ SharedPreferences.Editor editor = briarPrefs.edit();
+ editor.putString(PREF_DB_KEY, hex);
+ editor.apply();
+ }
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/TransportStateListener.java b/briar-android/src/org/briarproject/android/controller/TransportStateListener.java
new file mode 100644
index 000000000..0a00c0f7d
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/TransportStateListener.java
@@ -0,0 +1,7 @@
+package org.briarproject.android.controller;
+
+import org.briarproject.api.TransportId;
+
+public interface TransportStateListener {
+ void stateUpdate(TransportId id, boolean enabled);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
new file mode 100644
index 000000000..5d3cb0301
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
@@ -0,0 +1,6 @@
+package org.briarproject.android.controller.handler;
+
+public interface ResultExceptionHandler {
+ void onResult(R result);
+ void onException(E exception);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java b/briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java
new file mode 100644
index 000000000..55516f942
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java
@@ -0,0 +1,5 @@
+package org.briarproject.android.controller.handler;
+
+public interface ResultHandler {
+ void onResult(R result);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
new file mode 100644
index 000000000..7d9c08f4f
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
@@ -0,0 +1,33 @@
+package org.briarproject.android.controller.handler;
+
+import android.app.Activity;
+
+public abstract class UiResultExceptionHandler
+ implements ResultExceptionHandler {
+
+ private final Activity activity;
+
+ public UiResultExceptionHandler(Activity activity) {
+ this.activity = activity;
+ }
+
+ public void onResult(final R result) {
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ onResultUi(result);
+ }
+ });
+ }
+
+ public void onException(final E exception) {
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ onExceptionUi(exception);
+ }
+ });
+ }
+
+ public abstract void onResultUi(R result);
+
+ public abstract void onExceptionUi(E exception);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java b/briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java
new file mode 100644
index 000000000..1998060a5
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java
@@ -0,0 +1,22 @@
+package org.briarproject.android.controller.handler;
+
+import android.app.Activity;
+
+public abstract class UiResultHandler implements ResultHandler {
+
+ private final Activity activity;
+
+ public UiResultHandler(Activity activity) {
+ this.activity = activity;
+ }
+
+ public void onResult(final R result) {
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ onResultUi(result);
+ }
+ });
+ }
+
+ public abstract void onResultUi(R result);
+}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index dd7a722e7..f1e1a7b9e 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -5,6 +5,7 @@ import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.util.BriarRecyclerView;
@@ -61,7 +62,7 @@ public class AvailableForumsActivity extends BriarActivity
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java b/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
index 73de55ec1..cd5ff9bcf 100644
--- a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
@@ -13,7 +13,6 @@ import android.view.View;
import android.view.ViewGroup;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
import org.briarproject.android.contact.BaseContactListAdapter;
import org.briarproject.android.contact.ContactListItem;
import org.briarproject.android.fragment.BaseFragment;
@@ -63,13 +62,15 @@ public class ContactSelectorFragment extends BaseFragment implements
@Inject
protected volatile ForumSharingManager forumSharingManager;
- public static ContactSelectorFragment newInstance(GroupId groupId) {
- Bundle args = new Bundle();
- args.putByteArray(GROUP_ID, groupId.getBytes());
+ public void initBundle(GroupId groupId) {
+ Bundle bundle = new Bundle();
+ bundle.putByteArray(GROUP_ID, groupId.getBytes());
+ setArguments(bundle);
+ }
+
+ @Inject
+ public ContactSelectorFragment() {
- ContactSelectorFragment fragment = new ContactSelectorFragment();
- fragment.setArguments(args);
- return fragment;
}
@Override
@@ -83,11 +84,6 @@ public class ContactSelectorFragment extends BaseFragment implements
}
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
index a35834c93..fbb10650e 100644
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
@@ -15,7 +15,7 @@ import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.api.db.DbException;
import org.briarproject.api.forum.Forum;
@@ -86,7 +86,7 @@ public class CreateForumActivity extends BriarActivity
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index 9a2ec711d..1ea92c3c0 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -19,6 +19,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.AndroidNotificationManager;
@@ -127,7 +128,7 @@ public class ForumActivity extends BriarActivity implements EventListener,
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
index 4aa853bd7..012999093 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
@@ -14,6 +14,7 @@ import android.view.View;
import android.view.ViewGroup;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.fragment.BaseEventFragment;
import org.briarproject.android.util.BriarRecyclerView;
@@ -50,14 +51,6 @@ public class ForumListFragment extends BaseEventFragment implements
private static final Logger LOG =
Logger.getLogger(ForumListFragment.class.getName());
- public static ForumListFragment newInstance() {
-
- Bundle args = new Bundle();
-
- ForumListFragment fragment = new ForumListFragment();
- fragment.setArguments(args);
- return fragment;
- }
private BriarRecyclerView list;
private ForumListAdapter adapter;
@@ -67,6 +60,11 @@ public class ForumListFragment extends BaseEventFragment implements
@Inject protected volatile ForumManager forumManager;
@Inject protected volatile ForumSharingManager forumSharingManager;
+ @Inject
+ public ForumListFragment() {
+
+ }
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -99,11 +97,6 @@ public class ForumListFragment extends BaseEventFragment implements
return TAG;
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Override
public void onResume() {
super.onResume();
diff --git a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
index f320ed6ef..cfc80ace2 100644
--- a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
@@ -12,6 +12,7 @@ import android.widget.ScrollView;
import android.widget.TextView;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.util.AuthorView;
@@ -168,7 +169,7 @@ implements OnClickListener {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
index 820e25666..81bcdf8cd 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
@@ -5,7 +5,7 @@ import android.os.Bundle;
import android.view.View;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.api.contact.ContactId;
@@ -33,7 +33,8 @@ public class ShareForumActivity extends BriarActivity implements
if (savedInstanceState == null) {
ContactSelectorFragment contactSelectorFragment =
- ContactSelectorFragment.newInstance(groupId);
+ activityComponent.newContactSelectorFragment();
+ contactSelectorFragment.initBundle(groupId);
getSupportFragmentManager().beginTransaction()
.add(R.id.shareForumContainer, contactSelectorFragment)
.commit();
@@ -41,7 +42,7 @@ public class ShareForumActivity extends BriarActivity implements
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -49,7 +50,8 @@ public class ShareForumActivity extends BriarActivity implements
Collection contacts) {
ShareForumMessageFragment messageFragment =
- ShareForumMessageFragment.newInstance(groupId, contacts);
+ activityComponent.newShareForumMessageFragment();
+ messageFragment.initBundle(groupId, contacts);
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(android.R.anim.fade_in,
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java b/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
index 7ed79d67c..ab2586666 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
@@ -13,7 +13,6 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
@@ -45,17 +44,16 @@ public class ShareForumMessageFragment extends BaseFragment {
private volatile GroupId groupId;
private volatile Collection contacts;
- public static ShareForumMessageFragment newInstance(GroupId groupId,
- Collection contacts) {
+ public void initBundle(GroupId groupId, Collection contacts) {
+ Bundle bundle = new Bundle();
+ bundle.putByteArray(GROUP_ID, groupId.getBytes());
+ bundle.putIntegerArrayList(CONTACTS, getContactsFromIds(contacts));
+ setArguments(bundle);
+ }
- ShareForumMessageFragment f = new ShareForumMessageFragment();
+ @Inject
+ public ShareForumMessageFragment() {
- Bundle args = new Bundle();
- args.putByteArray(GROUP_ID, groupId.getBytes());
- args.putIntegerArrayList(CONTACTS, getContactsFromIds(contacts));
- f.setArguments(args);
-
- return f;
}
@Override
@@ -69,11 +67,6 @@ public class ShareForumMessageFragment extends BaseFragment {
}
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
index 4087115e0..d2185aa46 100644
--- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
@@ -16,6 +16,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.identity.CreateIdentityActivity;
@@ -161,7 +162,7 @@ implements OnItemSelectedListener, OnClickListener {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
index f353b6e08..69ceab43a 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
@@ -5,9 +5,6 @@ import org.briarproject.api.event.EventListener;
import javax.inject.Inject;
-/**
- * Created by Ernir Erlingsson (ernir@ymirmobile.com) on 8.1.2016.
- */
public abstract class BaseEventFragment extends BaseFragment implements
EventListener {
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
index 494f93c2d..96efaad58 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
@@ -4,9 +4,6 @@ import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarApplication;
-
public abstract class BaseFragment extends Fragment {
public abstract String getUniqueTag();
@@ -27,16 +24,9 @@ public abstract class BaseFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- BriarApplication application =
- (BriarApplication) getActivity().getApplication();
- injectActivity(application.getApplicationComponent());
}
- public abstract void injectActivity(AndroidComponent component);
-
public interface BaseFragmentListener {
-
void showLoadingScreen(boolean isBlocking, int stringId);
void hideLoadingScreen();
@@ -45,4 +35,5 @@ public abstract class BaseFragment extends Fragment {
void runOnDbThread(Runnable runnable);
}
+
}
diff --git a/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java b/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
deleted file mode 100644
index f98c16ab0..000000000
--- a/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.briarproject.android.fragment;
-
-
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.GridView;
-
-import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.plugins.PluginManager;
-
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-public class DashboardFragment extends BaseEventFragment {
-
- public final static String TAG = "DashboardFragment";
-
- private static final Logger LOG =
- Logger.getLogger(DashboardFragment.class.getName());
-
- @Inject
- protected PluginManager pluginManager;
-
- public static DashboardFragment newInstance() {
-
- Bundle args = new Bundle();
-
- DashboardFragment fragment = new DashboardFragment();
- fragment.setArguments(args);
- return fragment;
- }
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View contentView =
- inflater.inflate(R.layout.fragment_dashboard, container, false);
- return contentView;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- }
-
- @Override
- public String getUniqueTag() {
- return TAG;
- }
-
- @Override
- public void injectActivity(AndroidComponent component) {
-
- }
-
- @Override
- public void eventOccurred(Event e) {
-
- }
-}
diff --git a/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java b/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
index d1d37f9fa..b95ca581f 100644
--- a/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
+++ b/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
@@ -14,6 +14,7 @@ import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.util.LayoutUtils;
@@ -114,7 +115,7 @@ implements OnEditorActionListener, OnClickListener {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java b/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java
index 11e30d635..7b1bcbb5c 100644
--- a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java
+++ b/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java
@@ -12,7 +12,6 @@ import android.view.View;
import android.view.ViewGroup;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
import org.briarproject.android.contact.ContactListAdapter;
import org.briarproject.android.contact.ContactListItem;
import org.briarproject.android.contact.ConversationItem;
@@ -66,6 +65,11 @@ public class ContactChooserFragment extends BaseFragment {
@Inject
protected volatile ConnectionRegistry connectionRegistry;
+ @Inject
+ public ContactChooserFragment() {
+
+ }
+
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -77,11 +81,6 @@ public class ContactChooserFragment extends BaseFragment {
}
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java b/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java
index 2faee1a8a..79d511291 100644
--- a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java
+++ b/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java
@@ -3,6 +3,7 @@ package org.briarproject.android.introduction;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.transition.ChangeBounds;
import android.transition.Fade;
@@ -10,7 +11,7 @@ import android.view.MenuItem;
import android.view.View;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.api.contact.Contact;
@@ -33,15 +34,15 @@ public class IntroductionActivity extends BriarActivity implements
setContentView(R.layout.activity_introduction);
if (savedInstanceState == null) {
- ContactChooserFragment chooserFragment =
- new ContactChooserFragment();
getSupportFragmentManager().beginTransaction()
- .add(R.id.introductionContainer, chooserFragment).commit();
+ .add(R.id.introductionContainer,
+ activityComponent.newContactChooserFragment())
+ .commit();
}
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -85,13 +86,14 @@ public class IntroductionActivity extends BriarActivity implements
final Contact c2) {
IntroductionMessageFragment messageFragment =
- IntroductionMessageFragment
- .newInstance(c1.getId().getInt(), c2.getId().getInt());
+ activityComponent.newIntroductionMessageFragment();
+ messageFragment.initBundle(c1.getId().getInt(), c2.getId().getInt());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
messageFragment.setSharedElementEnterTransition(new ChangeBounds());
messageFragment.setEnterTransition(new Fade());
- messageFragment.setSharedElementReturnTransition(new ChangeBounds());
+ messageFragment
+ .setSharedElementReturnTransition(new ChangeBounds());
}
getSupportFragmentManager().beginTransaction()
diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
index ed0547da4..48f0726c0 100644
--- a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
@@ -13,7 +13,6 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.api.FormatException;
import org.briarproject.api.contact.Contact;
@@ -49,18 +48,19 @@ public class IntroductionMessageFragment extends BaseFragment {
@Inject
protected volatile IntroductionManager introductionManager;
- public static IntroductionMessageFragment newInstance(int contactId1,
- int contactId2) {
- IntroductionMessageFragment f = new IntroductionMessageFragment();
-
+ public void initBundle(int contactId1, int contactId2) {
Bundle args = new Bundle();
args.putInt(CONTACT_ID_1, contactId1);
args.putInt(CONTACT_ID_2, contactId2);
- f.setArguments(args);
-
- return f;
+ setArguments(args);
}
+ @Inject
+ public IntroductionMessageFragment() {
+
+ }
+
+
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -72,11 +72,6 @@ public class IntroductionMessageFragment extends BaseFragment {
}
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -183,7 +178,8 @@ public class IntroductionMessageFragment extends BaseFragment {
// actually make the introduction
try {
long timestamp = System.currentTimeMillis();
- introductionManager.makeIntroduction(c1, c2, msg, timestamp);
+ introductionManager
+ .makeIntroduction(c1, c2, msg, timestamp);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
index 2faf5f619..acd8d36a1 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
+++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
@@ -5,7 +5,7 @@ import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.ReferenceManager;
import org.briarproject.api.crypto.CryptoComponent;
@@ -145,7 +145,7 @@ implements InvitationListener {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java b/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
index 16818d36a..40206766e 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
+++ b/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
@@ -13,6 +13,7 @@ import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.identity.CreateIdentityActivity;
@@ -59,11 +60,9 @@ public class ChooseIdentityFragment extends BaseFragment
@Inject
protected volatile IdentityManager identityManager;
- public static ChooseIdentityFragment newInstance() {
- Bundle args = new Bundle();
- ChooseIdentityFragment fragment = new ChooseIdentityFragment();
- fragment.setArguments(args);
- return fragment;
+ @Inject
+ public ChooseIdentityFragment() {
+
}
@Override
@@ -82,11 +81,6 @@ public class ChooseIdentityFragment extends BaseFragment
return TAG;
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
diff --git a/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java
index 185d3c0b1..b2395eaa2 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java
+++ b/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java
@@ -7,6 +7,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarFragmentActivity;
import org.briarproject.android.fragment.BaseFragment;
@@ -63,7 +64,7 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
protected volatile IdentityManager identityManager;
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@@ -96,11 +97,11 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
STEPS));
switch (step) {
case STEP_QR:
- startFragment(ShowQrCodeFragment.newInstance());
+ startFragment(activityComponent.newShowQrCodeFragment());
break;
case STEP_ID:
default:
- startFragment(ChooseIdentityFragment.newInstance());
+ startFragment(activityComponent.newChooseIdentityFragment());
break;
}
}
diff --git a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
index cbe175d8e..8a997168d 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
+++ b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
@@ -86,11 +86,9 @@ public class ShowQrCodeFragment extends BaseEventFragment
private volatile KeyAgreementTask task;
private volatile boolean waitingForBluetooth;
- public static ShowQrCodeFragment newInstance() {
- Bundle args = new Bundle();
- ShowQrCodeFragment fragment = new ShowQrCodeFragment();
- fragment.setArguments(args);
- return fragment;
+ @Inject
+ public ShowQrCodeFragment() {
+
}
@Override
@@ -98,11 +96,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
return TAG;
}
- @Override
- public void injectActivity(AndroidComponent component) {
- component.inject(this);
- }
-
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
diff --git a/briar-android/src/org/briarproject/android/panic/ExitActivity.java b/briar-android/src/org/briarproject/android/panic/ExitActivity.java
index 4417c1fe8..7e8540201 100644
--- a/briar-android/src/org/briarproject/android/panic/ExitActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/ExitActivity.java
@@ -3,6 +3,7 @@ package org.briarproject.android.panic;
import android.os.Build;
import android.os.Bundle;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BaseActivity;
@@ -23,7 +24,7 @@ public class ExitActivity extends BaseActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
}
}
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java b/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
index c25461c34..f0645f3c2 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
@@ -5,6 +5,7 @@ import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
@@ -24,7 +25,7 @@ public class PanicPreferencesActivity extends BriarActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
diff --git a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
index 87ba49e70..fbe549e6e 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
@@ -7,11 +7,11 @@ import android.os.Build;
import android.os.Bundle;
import android.support.v7.preference.PreferenceManager;
-import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.android.controller.ConfigController;
import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.db.DatabaseConfig;
import org.iilab.IilabEngineeringRSA2048Pin;
import java.util.logging.Logger;
@@ -32,9 +32,7 @@ public class PanicResponderActivity extends BriarActivity {
private static final Logger LOG =
Logger.getLogger(PanicResponderActivity.class.getName());
-
- @Inject
- protected DatabaseConfig databaseConfig;
+ @Inject protected ConfigController configController;
@Inject
protected AndroidExecutor androidExecutor;
@@ -105,15 +103,16 @@ public class PanicResponderActivity extends BriarActivity {
}
@Override
- public void injectActivity(AndroidComponent component) {
+ public void injectActivity(ActivityComponent component) {
component.inject(this);
}
private void deleteAllData() {
androidExecutor.execute(new Runnable() {
public void run() {
- clearSharedPrefs();
+ configController.clearPrefs();
// TODO somehow delete/shred the database more thoroughly
+ // TODO replace this static call with a controller method
AndroidUtils.deleteAppData(PanicResponderActivity.this);
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
diff --git a/briar-android/src/org/briarproject/android/util/StrengthMeter.java b/briar-android/src/org/briarproject/android/util/StrengthMeter.java
index eee1e5473..83fb20b8f 100644
--- a/briar-android/src/org/briarproject/android/util/StrengthMeter.java
+++ b/briar-android/src/org/briarproject/android/util/StrengthMeter.java
@@ -23,11 +23,11 @@ import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
public class StrengthMeter extends ProgressBar {
private static final int MAX = 100;
- private static final int RED = Color.rgb(255, 0, 0);
- private static final int ORANGE = Color.rgb(255, 160, 0);
- private static final int YELLOW = Color.rgb(255, 255, 0);
- private static final int LIME = Color.rgb(180, 255, 0);
- private static final int GREEN = Color.rgb(0, 255, 0);
+ public static final int RED = Color.rgb(255, 0, 0);
+ public static final int ORANGE = Color.rgb(255, 160, 0);
+ public static final int YELLOW = Color.rgb(255, 255, 0);
+ public static final int LIME = Color.rgb(180, 255, 0);
+ public static final int GREEN = Color.rgb(0, 255, 0);
private final ShapeDrawable bar;
@@ -57,6 +57,10 @@ public class StrengthMeter extends ProgressBar {
return MAX;
}
+ public int getColor() {
+ return bar.getPaint().getColor();
+ }
+
public void setStrength(float strength) {
if (strength < 0 || strength > 1) throw new IllegalArgumentException();
int colour;
diff --git a/briar-android/src/org/briarproject/system/AndroidSeedProvider.java b/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
index c15e0b411..59c7a6e3a 100644
--- a/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
+++ b/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
@@ -8,6 +8,7 @@ import android.provider.Settings;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.logging.Logger;
import javax.inject.Inject;
@@ -15,6 +16,9 @@ import static android.provider.Settings.Secure.ANDROID_ID;
class AndroidSeedProvider extends LinuxSeedProvider {
+ private static final Logger LOG =
+ Logger.getLogger(LinuxSeedProvider.class.getName());
+
private final Context appContext;
@Inject
@@ -30,7 +34,10 @@ class AndroidSeedProvider extends LinuxSeedProvider {
if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT);
if (Build.SERIAL != null) out.writeUTF(Build.SERIAL);
ContentResolver contentResolver = appContext.getContentResolver();
- out.writeUTF(Settings.Secure.getString(contentResolver, ANDROID_ID));
+ String str = Settings.Secure.getString(contentResolver, ANDROID_ID);
+ if (str != null) {
+ out.writeUTF(str);
+ }
super.writeToEntropyPool(out);
}
}
diff --git a/briar-android/test/java/android/net/http/AndroidHttpClient.java b/briar-android/test/java/android/net/http/AndroidHttpClient.java
new file mode 100644
index 000000000..f2cf7a346
--- /dev/null
+++ b/briar-android/test/java/android/net/http/AndroidHttpClient.java
@@ -0,0 +1,7 @@
+package android.net.http;
+
+// This class is here to fix an issue with Robolectric.
+// https://github.com/robolectric/robolectric/issues/1862
+// TODO Check if this class can be removed on next Robolectric update
+public class AndroidHttpClient {
+}
\ No newline at end of file
diff --git a/briar-android/test/java/briarproject/activity/SetupActivityTest.java b/briar-android/test/java/briarproject/activity/SetupActivityTest.java
new file mode 100644
index 000000000..b58d033b2
--- /dev/null
+++ b/briar-android/test/java/briarproject/activity/SetupActivityTest.java
@@ -0,0 +1,229 @@
+package briarproject.activity;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.support.design.widget.TextInputLayout;
+import android.widget.Button;
+import android.widget.EditText;
+
+import com.google.common.base.Strings;
+
+import org.briarproject.BuildConfig;
+import org.briarproject.R;
+import org.briarproject.android.NavDrawerActivity;
+import org.briarproject.android.controller.SetupController;
+import org.briarproject.android.controller.handler.ResultHandler;
+import org.briarproject.android.util.StrengthMeter;
+import org.briarproject.api.identity.AuthorConstants;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+
+import static junit.framework.Assert.assertEquals;
+import static org.briarproject.api.crypto.PasswordStrengthEstimator.NONE;
+import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
+import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
+import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG;
+import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = BuildConfig.class, sdk = 21,
+ application = TestBriarApplicationImp.class)
+public class SetupActivityTest {
+
+ TestSetupActivity setupActivity;
+ TextInputLayout nicknameEntryWrapper;
+ TextInputLayout passwordEntryWrapper;
+ TextInputLayout passwordConfirmationWrapper;
+ EditText nicknameEntry;
+ EditText passwordEntry;
+ EditText passwordConfirmation;
+ StrengthMeter strengthMeter;
+ Button createAccountButton;
+
+ @Mock
+ SetupController setupController;
+ @Captor
+ ArgumentCaptor> resultCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ setupActivity = Robolectric.setupActivity(TestSetupActivity.class);
+ nicknameEntryWrapper = (TextInputLayout) setupActivity
+ .findViewById(R.id.nickname_entry_wrapper);
+ passwordEntryWrapper = (TextInputLayout) setupActivity
+ .findViewById(R.id.password_entry_wrapper);
+ passwordConfirmationWrapper = (TextInputLayout) setupActivity
+ .findViewById(R.id.password_confirm_wrapper);
+ nicknameEntry =
+ (EditText) setupActivity.findViewById(R.id.nickname_entry);
+ passwordEntry =
+ (EditText) setupActivity.findViewById(R.id.password_entry);
+ passwordConfirmation =
+ (EditText) setupActivity.findViewById(R.id.password_confirm);
+ strengthMeter =
+ (StrengthMeter) setupActivity.findViewById(R.id.strength_meter);
+ createAccountButton =
+ (Button) setupActivity.findViewById(R.id.create_account);
+ }
+
+ private void testStrengthMeter(String pass, float strength, int color) {
+ passwordEntry.setText(pass);
+ assertEquals(strengthMeter.getProgress(),
+ (int) (strengthMeter.getMax() * strength));
+ assertEquals(color, strengthMeter.getColor());
+ }
+
+ @Test
+ public void testPasswordMatchUI() {
+ // Password mismatch
+ passwordEntry.setText("really.safe.password");
+ passwordConfirmation.setText("really.safe.pass");
+ assertEquals(createAccountButton.isEnabled(), false);
+ assertEquals(passwordConfirmationWrapper.getError(),
+ setupActivity.getString(R.string.passwords_do_not_match));
+ // Button enabled
+ passwordEntry.setText("really.safe.pass");
+ passwordConfirmation.setText("really.safe.pass");
+ // Confirm that the password mismatch error message is not visible
+ Assert.assertNotEquals(passwordConfirmationWrapper.getError(),
+ setupActivity.getString(R.string.passwords_do_not_match));
+ // Nick has not been set, expect the button to be disabled
+ assertEquals(createAccountButton.isEnabled(), false);
+ }
+
+ @Test
+ public void testCreateAccountUI() {
+
+ SetupController mockedController = this.setupController;
+ setupActivity.setController(mockedController);
+ // Mock strong password strength answer
+ when(mockedController.estimatePasswordStrength(anyString())).thenReturn(
+ STRONG);
+ String safePass = "really.safe.password";
+ String nick = "nick.nickerton";
+ passwordEntry.setText(safePass);
+ passwordConfirmation.setText(safePass);
+ nicknameEntry.setText(nick);
+ // Confirm that the create account button is clickable
+ assertEquals(createAccountButton.isEnabled(), true);
+ createAccountButton.performClick();
+ // Verify that the controller's method was called with the correct
+ // params and get the callback
+ verify(mockedController, times(1))
+ .createIdentity(eq(nick), eq(safePass), resultCaptor.capture());
+ // execute the callback
+ resultCaptor.getValue().onResult(1L);
+ assertEquals(setupActivity.isFinishing(), true);
+ // Confirm that the correct Activity has been started
+ ShadowActivity shadowActivity = shadowOf(setupActivity);
+ Intent intent = shadowActivity.peekNextStartedActivity();
+ assertEquals(intent.getComponent().getClassName(),
+ NavDrawerActivity.class.getName());
+ }
+
+ @Test
+ public void testNicknameUI() {
+ Assert.assertNotNull(setupActivity);
+ String longNick =
+ Strings.padEnd("*", AuthorConstants.MAX_AUTHOR_NAME_LENGTH + 1,
+ '*');
+ nicknameEntry.setText(longNick);
+ // Nickname should be too long
+ assertEquals(nicknameEntryWrapper.getError(),
+ setupActivity.getString(R.string.name_too_long));
+ }
+
+ @Test
+ public void testAccountCreation() {
+ SetupController controller = setupActivity.getController();
+ // mock a resulthandler
+ ResultHandler resultHandler =
+ (ResultHandler) mock(ResultHandler.class);
+ controller
+ .createIdentity("nick", "some.strong.pass", resultHandler);
+ // blocking verification call with timeout that waits until the mocked
+ // result gets called with handle 0L, the expected value
+ verify(resultHandler, timeout(2000).times(1)).onResult(0L);
+ SharedPreferences prefs =
+ setupActivity.getSharedPreferences("db", Context.MODE_PRIVATE);
+ // Confirm database key
+ assertTrue(prefs.contains("key"));
+ // Note that Robolectric uses its own persistant storage that it
+ // wipes clean after each test run, no need to clean up manually.
+ }
+
+ @Test
+ public void testStrengthMeter() {
+ SetupController controller = setupActivity.getController();
+
+ String strongPass = "very.strong.password.123";
+ String weakPass = "we";
+ String quiteStrongPass = "quite.strong";
+
+ float val = controller.estimatePasswordStrength(strongPass);
+ assertTrue(val == STRONG);
+ val = controller.estimatePasswordStrength(weakPass);
+ assertTrue(val < WEAK && val > NONE);
+ val = controller.estimatePasswordStrength(quiteStrongPass);
+ assertTrue(val < STRONG && val > QUITE_WEAK);
+ }
+
+ @Test
+ public void testStrengthMeterUI() {
+ Assert.assertNotNull(setupActivity);
+ // replace the setup controller with our mocked copy
+ SetupController mockedController = this.setupController;
+ setupActivity.setController(mockedController);
+ // Mock answers for UI testing only
+ when(mockedController.estimatePasswordStrength("strong")).thenReturn(
+ STRONG);
+ when(mockedController.estimatePasswordStrength("qstring")).thenReturn(
+ QUITE_STRONG);
+ when(mockedController.estimatePasswordStrength("qweak")).thenReturn(
+ QUITE_WEAK);
+ when(mockedController.estimatePasswordStrength("weak")).thenReturn(
+ WEAK);
+ when(mockedController.estimatePasswordStrength("empty")).thenReturn(
+ NONE);
+ // Test the meters progress and color for several values
+ testStrengthMeter("strong", STRONG, StrengthMeter.GREEN);
+ Mockito.verify(mockedController, Mockito.times(1))
+ .estimatePasswordStrength(eq("strong"));
+ testStrengthMeter("qstring", QUITE_STRONG, StrengthMeter.LIME);
+ Mockito.verify(mockedController, Mockito.times(1))
+ .estimatePasswordStrength(eq("qstring"));
+ testStrengthMeter("qweak", QUITE_WEAK, StrengthMeter.YELLOW);
+ Mockito.verify(mockedController, Mockito.times(1))
+ .estimatePasswordStrength(eq("qweak"));
+ testStrengthMeter("weak", WEAK, StrengthMeter.ORANGE);
+ Mockito.verify(mockedController, Mockito.times(1))
+ .estimatePasswordStrength(eq("weak"));
+ // Not sure this should be the correct behaviour on an empty input ?
+ testStrengthMeter("empty", NONE, StrengthMeter.RED);
+ Mockito.verify(mockedController, Mockito.times(1))
+ .estimatePasswordStrength(eq("empty"));
+ }
+
+}
diff --git a/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java b/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java
new file mode 100644
index 000000000..8e29d9efd
--- /dev/null
+++ b/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java
@@ -0,0 +1,43 @@
+package briarproject.activity;
+
+import android.app.Application;
+
+import org.briarproject.CoreModule;
+import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.AndroidEagerSingletons;
+import org.briarproject.android.AppModule;
+import org.briarproject.android.BriarApplication;
+import org.briarproject.android.DaggerAndroidComponent;
+
+import java.util.logging.Logger;
+
+/**
+ * This Class only exists to get around ACRA
+ */
+public class TestBriarApplicationImp extends Application implements
+ BriarApplication{
+
+ private static final Logger LOG =
+ Logger.getLogger(TestBriarApplicationImp.class.getName());
+
+ private AndroidComponent applicationComponent;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ LOG.info("Created");
+
+ applicationComponent = DaggerAndroidComponent.builder()
+ .appModule(new AppModule(this))
+ .build();
+
+ // We need to load the eager singletons directly after making the
+ // dependency graphs
+ CoreModule.initEagerSingletons(applicationComponent);
+ AndroidEagerSingletons.initEagerSingletons(applicationComponent);
+ }
+
+ public AndroidComponent getApplicationComponent() {
+ return applicationComponent;
+ }
+}
diff --git a/briar-android/test/java/briarproject/activity/TestSetupActivity.java b/briar-android/test/java/briarproject/activity/TestSetupActivity.java
new file mode 100644
index 000000000..923372a49
--- /dev/null
+++ b/briar-android/test/java/briarproject/activity/TestSetupActivity.java
@@ -0,0 +1,20 @@
+package briarproject.activity;
+
+import org.briarproject.android.SetupActivity;
+import org.briarproject.android.controller.SetupController;
+
+/**
+ * This class exposes the SetupController and offers the possibility to
+ * override it.
+ */
+public class TestSetupActivity extends SetupActivity {
+
+ public SetupController getController() {
+ return this.setupController;
+ }
+
+ public void setController(SetupController setupController) {
+ this.setupController = setupController;
+ }
+
+}
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionModule.java b/briar-core/src/org/briarproject/introduction/IntroductionModule.java
index 9e51aca73..4ea0ac6c3 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionModule.java
+++ b/briar-core/src/org/briarproject/introduction/IntroductionModule.java
@@ -26,7 +26,7 @@ public class IntroductionModule {
@Provides
@Singleton
- MessageValidator getValidator(MessageQueueManager messageQueueManager,
+ MessageValidator provideValidator(MessageQueueManager messageQueueManager,
IntroductionManager introductionManager,
MetadataEncoder metadataEncoder, ClientHelper clientHelper,
Clock clock) {
@@ -43,7 +43,7 @@ public class IntroductionModule {
@Provides
@Singleton
- IntroductionManager getIntroductionManager(
+ IntroductionManager provideIntroductionManager(
LifecycleManager lifecycleManager,
ContactManager contactManager,
MessageQueueManager messageQueueManager,
diff --git a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
index 58b22d32a..6481b4a5f 100644
--- a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
+++ b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
@@ -1,6 +1,6 @@
package org.briarproject.system;
-import static java.util.logging.Level.WARNING;
+import org.briarproject.api.system.SeedProvider;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -13,7 +13,7 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
-import org.briarproject.api.system.SeedProvider;
+import static java.util.logging.Level.WARNING;
class LinuxSeedProvider implements SeedProvider {