diff --git a/src/keepass2android/EntryActivity.cs b/src/keepass2android/EntryActivity.cs
index cfd06273..c325f9d3 100644
--- a/src/keepass2android/EntryActivity.cs
+++ b/src/keepass2android/EntryActivity.cs
@@ -49,11 +49,8 @@ namespace keepass2android
public const String KEY_REFRESH_POS = "refresh_pos";
public const String KEY_CLOSE_AFTER_CREATE = "close_after_create";
- public static void Launch(Activity act, PwEntry pw, int pos) {
- Launch(act, pw, pos, false);
- }
- public static void Launch(Activity act, PwEntry pw, int pos, bool closeAfterCreate) {
+ public static void Launch(Activity act, PwEntry pw, int pos, IAppTask appTask) {
Intent i;
i = new Intent(act, typeof(EntryActivity));
@@ -61,7 +58,8 @@ namespace keepass2android
i.PutExtra(KEY_ENTRY, pw.Uuid.ToHexString());
i.PutExtra(KEY_REFRESH_POS, pos);
- i.PutExtra(KEY_CLOSE_AFTER_CREATE, closeAfterCreate);
+
+ appTask.ToIntent(i);
act.StartActivityForResult(i,0);
}
@@ -71,6 +69,7 @@ namespace keepass2android
private bool mShowPassword;
private int mPos;
+ IAppTask mAppTask;
protected void setEntryView() {
@@ -116,12 +115,12 @@ namespace keepass2android
PwUuid uuid = new PwUuid(MemUtil.HexStringToByteArray(i.GetStringExtra(KEY_ENTRY)));
mPos = i.GetIntExtra(KEY_REFRESH_POS, -1);
- bool closeAfterCreate = i.GetBooleanExtra(KEY_CLOSE_AFTER_CREATE, false);
+ mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
+
+ bool closeAfterCreate = mAppTask.CloseEntryActivityAfterCreate;
mEntry = db.entries [uuid];
-
-
// Refresh Menu contents in case onCreateMenuOptions was called before mEntry was set
ActivityCompat.invalidateOptionsMenu(this);
diff --git a/src/keepass2android/GroupActivity.cs b/src/keepass2android/GroupActivity.cs
index 6a096ae5..3b3b3eca 100644
--- a/src/keepass2android/GroupActivity.cs
+++ b/src/keepass2android/GroupActivity.cs
@@ -45,11 +45,11 @@ namespace keepass2android
private const String TAG = "Group Activity:";
- public static void Launch(Activity act) {
- Launch(act, null);
+ public static void Launch(Activity act, IAppTask appTask) {
+ Launch(act, null, appTask);
}
- public static void Launch (Activity act, PwGroup g)
+ public static void Launch (Activity act, PwGroup g, IAppTask appTask)
{
Intent i;
diff --git a/src/keepass2android/GroupBaseActivity.cs b/src/keepass2android/GroupBaseActivity.cs
index 56c057c3..84bbfb85 100644
--- a/src/keepass2android/GroupBaseActivity.cs
+++ b/src/keepass2android/GroupBaseActivity.cs
@@ -40,7 +40,7 @@ namespace keepass2android
public virtual void LaunchActivityForEntry(KeePassLib.PwEntry pwEntry, int pos)
{
- EntryActivity.Launch(this, pwEntry, pos, false);
+ EntryActivity.Launch(this, pwEntry, pos, mAppTask);
}
public GroupBaseActivity ()
{
@@ -52,10 +52,18 @@ namespace keepass2android
{
}
+
+ protected override void OnSaveInstanceState(Bundle outState)
+ {
+ base.OnSaveInstanceState(outState);
+ mAppTask.ToBundle(outState);
+ }
private ISharedPreferences prefs;
protected PwGroup mGroup;
+
+ internal IAppTask mAppTask;
protected override void OnResume() {
base.OnResume();
@@ -90,6 +98,8 @@ namespace keepass2android
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
+
+ mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
// Likely the app has been killed exit the activity
if ( ! App.getDB().Loaded ) {
diff --git a/src/keepass2android/LifecycleDebugActivity.cs b/src/keepass2android/LifecycleDebugActivity.cs
index c6609bc5..410a31c0 100644
--- a/src/keepass2android/LifecycleDebugActivity.cs
+++ b/src/keepass2android/LifecycleDebugActivity.cs
@@ -69,6 +69,7 @@ namespace keepass2android
{
base.OnCreate(bundle);
Android.Util.Log.Debug("DEBUG",ClassName+".OnCreate");
+ Android.Util.Log.Debug("DEBUG", ClassName+":apptask="+Intent.GetStringExtra("KP2A_APP_TASK_TYPE"));
}
protected override void OnDestroy()
diff --git a/src/keepass2android/PasswordActivity.cs b/src/keepass2android/PasswordActivity.cs
index a14f2508..2ade556a 100644
--- a/src/keepass2android/PasswordActivity.cs
+++ b/src/keepass2android/PasswordActivity.cs
@@ -87,7 +87,7 @@ namespace keepass2android
ioc.CredSaveMode = (IOCredSaveMode)i.GetIntExtra(KEY_SERVERCREDMODE, (int) IOCredSaveMode.NoSave);
}
- public static void Launch(Activity act, String fileName, String urlToSearchFor) {
+ public static void Launch(Activity act, String fileName, IAppTask appTask) {
Java.IO.File dbFile = new Java.IO.File(fileName);
if ( ! dbFile.Exists() ) {
throw new Java.IO.FileNotFoundException();
@@ -96,7 +96,7 @@ namespace keepass2android
Intent i = new Intent(act, typeof(PasswordActivity));
i.PutExtra(KEY_FILENAME, fileName);
- i.PutExtra(FileSelectActivity.UrlToSearch_key, urlToSearchFor);
+ appTask.ToIntent(i);
act.StartActivityForResult(i, 0);
}
@@ -108,18 +108,18 @@ namespace keepass2android
}
- public static void Launch(Activity act, IOConnectionInfo ioc, String urlToSearchFor)
+ public static void Launch(Activity act, IOConnectionInfo ioc, IAppTask appTask)
{
if (ioc.IsLocalFile())
{
- Launch(act, ioc.Path, urlToSearchFor);
+ Launch(act, ioc.Path, appTask);
return;
}
Intent i = new Intent(act, typeof(PasswordActivity));
PutIoConnectionToIntent(ioc, i);
- i.PutExtra(FileSelectActivity.UrlToSearch_key, urlToSearchFor);
+ appTask.ToIntent(i);
act.StartActivityForResult(i, 0);
@@ -127,13 +127,8 @@ namespace keepass2android
public void LaunchNextActivity()
{
+ mAppTask.AfterUnlockDatabase(this);
- if (String.IsNullOrEmpty(mUrlToSearchFor))
- GroupActivity.Launch(this);
- else
- {
- ShareUrlResults.Launch(this, mUrlToSearchFor);
- }
}
void unloadDatabase()
@@ -284,7 +279,7 @@ namespace keepass2android
}
- internal string mUrlToSearchFor;
+ internal IAppTask mAppTask;
protected override void OnCreate(Bundle savedInstanceState)
{
@@ -342,7 +337,7 @@ namespace keepass2android
}
}
- this.mUrlToSearchFor = i.GetStringExtra(FileSelectActivity.UrlToSearch_key);
+ mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
SetContentView(Resource.Layout.password);
populateView();
@@ -449,6 +444,12 @@ namespace keepass2android
}
+
+ protected override void OnSaveInstanceState(Bundle outState)
+ {
+ base.OnSaveInstanceState(outState);
+ mAppTask.ToBundle(outState);
+ }
protected override void OnResume() {
base.OnResume();
diff --git a/src/keepass2android/ShareUrlResults.cs b/src/keepass2android/ShareUrlResults.cs
index e3baadd0..f066562c 100644
--- a/src/keepass2android/ShareUrlResults.cs
+++ b/src/keepass2android/ShareUrlResults.cs
@@ -46,39 +46,38 @@ namespace keepass2android
{
}
- public static void Launch(Activity act, string urlToSearchFor)
+ public static void Launch(Activity act, SearchUrlTask task)
{
Intent i = new Intent(act, typeof(ShareUrlResults));
- i.PutExtra(Intent.ExtraText, urlToSearchFor);
+ task.ToIntent(i);
act.StartActivityForResult(i, 0);
-
}
private Database mDb;
- protected override void OnCreate(Bundle bundle)
+ protected override void OnCreate(Bundle savedInstanceState)
{
- base.OnCreate(bundle);
+ base.OnCreate(savedInstanceState);
SetResult(KeePass.EXIT_CLOSE_AFTER_SEARCH);
-
+
mDb = App.getDB();
- String searchUrl = getSearchUrl(Intent);
+ String searchUrl = ((SearchUrlTask)mAppTask).UrlToSearchFor;
if (!mDb.Loaded)
{
Intent intent = new Intent(this, typeof(FileSelectActivity));
- intent.PutExtra(FileSelectActivity.UrlToSearch_key, searchUrl);
+ mAppTask.ToIntent(intent);
StartActivityForResult(intent, 0);
Finish();
}
else if (mDb.Locked)
{
- PasswordActivity.Launch(this,mDb.mIoc, searchUrl);
+ PasswordActivity.Launch(this,mDb.mIoc, mAppTask);
Finish();
}
else
@@ -88,9 +87,15 @@ namespace keepass2android
}
+ protected override void OnSaveInstanceState(Bundle outState)
+ {
+ base.OnSaveInstanceState(outState);
+ mAppTask.ToBundle(outState);
+ }
+
public override void LaunchActivityForEntry(KeePassLib.PwEntry pwEntry, int pos)
{
- EntryActivity.Launch(this, pwEntry, pos, true);
+ base.LaunchActivityForEntry(pwEntry, pos);
Finish();
}
@@ -133,7 +138,7 @@ namespace keepass2android
}
}
-
+ //show results:
if (mGroup == null || (mGroup.Entries.Count() < 1))
{
SetContentView(new GroupEmptyView(this));
@@ -146,6 +151,7 @@ namespace keepass2android
ListAdapter = new PwGroupListAdapter(this, mGroup);
+ //if there is exactly one match: open the entry
if (mGroup.Entries.Count() == 1)
{
LaunchActivityForEntry(mGroup.Entries.Single(),0);
diff --git a/src/keepass2android/app/AppTask.cs b/src/keepass2android/app/AppTask.cs
new file mode 100644
index 00000000..28f650bd
--- /dev/null
+++ b/src/keepass2android/app/AppTask.cs
@@ -0,0 +1,268 @@
+// Copyright (c) 2013 Philipp Crocoll
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+using System;
+using Android.App;
+using Android.Content;
+using Android.OS;
+using System.Collections.Generic;
+
+namespace keepass2android
+{
+ ///
+ /// Interface for data stored in an intent or bundle as extra string
+ ///
+ public interface IExtra
+ {
+ ///
+ /// put data to a bundle by calling one of the PutXX methods
+ ///
+ void ToBundle(Bundle b);
+
+ ///
+ /// Put data to an intent by calling PutExtra
+ ///
+ void ToIntent(Intent i);
+ }
+
+ ///
+ /// represents data stored in an intent or bundle as extra string
+ ///
+ public class StringExtra: IExtra
+ {
+ public string Key { get; set; }
+ public string Value{ get; set; }
+
+ #region IExtra implementation
+
+ public void ToBundle(Bundle b)
+ {
+ b.PutString(Key, Value);
+ }
+
+ public void ToIntent(Intent i)
+ {
+ i.PutExtra(Key, Value);
+ }
+
+ #endregion
+ }
+
+ ///
+ /// interface for "tasks": this are things the user wants to do and which require several activities
+ ///
+ public interface IAppTask
+ {
+ ///
+ /// Loads the parameters of the task from the given bundle
+ ///
+ void Setup(Bundle b);
+
+ ///
+ /// Returns the parameters of the task for storage in a bundle or intent
+ ///
+ /// The extras.
+ IEnumerable Extras { get;}
+
+ void AfterUnlockDatabase(PasswordActivity act);
+
+ bool CloseEntryActivityAfterCreate
+ {
+ get;
+ }
+ }
+
+ ///
+ /// Implementation of IAppTask for "no task currently active" (Null pattern)
+ ///
+ public class NullTask: IAppTask
+ {
+
+ public void Setup(Bundle b)
+ {
+ }
+
+ public IEnumerable Extras
+ {
+ get
+ {
+ yield break;
+ }
+ }
+
+
+ public void AfterUnlockDatabase(PasswordActivity act)
+ {
+ GroupActivity.Launch(act, this);
+ }
+ public bool CloseEntryActivityAfterCreate
+ {
+ get { return false;}
+ }
+ }
+
+ ///
+ /// User is about to search an entry for a given URL
+ ///
+ public class SearchUrlTask: IAppTask
+ {
+ public const String UrlToSearch_key = "UrlToSearch";
+
+ public string UrlToSearchFor
+ {
+ get;
+ set;
+ }
+
+ public void Setup(Bundle b)
+ {
+ UrlToSearchFor = b.GetString(UrlToSearch_key);
+ }
+ public IEnumerable Extras
+ {
+ get
+ {
+ yield return new StringExtra() { Key=UrlToSearch_key, Value = UrlToSearchFor };
+ }
+ }
+ public void AfterUnlockDatabase(PasswordActivity act)
+ {
+ ShareUrlResults.Launch(act, this);
+ }
+ public bool CloseEntryActivityAfterCreate
+ {
+ get { return true;}
+ }
+ }
+
+
+ ///
+ /// User is about to select an entry for use in another app
+ ///
+ public class SelectEntryTask: IAppTask
+ {
+ public void Setup(Bundle b)
+ {
+ }
+ public IEnumerable Extras
+ {
+ get
+ {
+ yield break;
+ }
+ }
+ public void AfterUnlockDatabase(PasswordActivity act)
+ {
+ GroupActivity.Launch(act, this);
+ }
+ public bool CloseEntryActivityAfterCreate
+ {
+ //keypoint here: close the app after selecting the entry
+ get { return true;}
+ }
+ }
+
+ ///
+ ///
+ ///
+ public static class AppTask
+ {
+ public const String AppTask_key = "KP2A_APPTASK";
+
+ ///
+ /// Should be used in OnCreate to (re)create a task
+ /// if savedInstanceState is not null, the task is recreated from there. Otherwise it's taken from the intent.
+ ///
+ public static IAppTask GetTaskInOnCreate(Bundle savedInstanceState, Intent intent)
+ {
+ if (savedInstanceState != null)
+ {
+ return AppTask.CreateFromBundle(savedInstanceState);
+ }
+ else
+ {
+ return AppTask.CreateFromIntent(intent);
+ }
+ }
+
+ public static IAppTask CreateFromIntent(Intent i)
+ {
+ return CreateFromBundle(i.Extras);
+ }
+
+ public static IAppTask CreateFromBundle(Bundle b)
+ {
+ if (b == null)
+ return new NullTask();
+
+ string taskType = b.GetString("KP2A_APP_TASK_TYPE");
+
+ if (string.IsNullOrEmpty(taskType))
+ return new NullTask();
+
+ Type[] types = {typeof(SearchUrlTask), typeof(NullTask)};
+
+ foreach (Type type in types)
+ {
+ if (taskType == type.Name)
+ {
+ IAppTask task = (IAppTask)Activator.CreateInstance(type);
+ task.Setup(b);
+ return task;
+ }
+ }
+
+ return new NullTask();
+ }
+
+ ///
+ /// Adds the extras of the task to the intent
+ ///
+ public static void ToIntent(this IAppTask task, Intent intent)
+ {
+ AppTask.GetTypeExtra(task.GetType()).ToIntent(intent);
+
+ foreach (IExtra extra in task.Extras)
+ {
+ extra.ToIntent(intent);
+ }
+ }
+
+ ///
+ /// Adds the extras of the task to the bundle
+ ///
+ public static void ToBundle(this IAppTask task, Bundle bundle)
+ {
+ AppTask.GetTypeExtra(task.GetType()).ToBundle(bundle);
+
+ foreach (IExtra extra in task.Extras)
+ {
+ extra.ToBundle(bundle);
+ }
+
+ }
+
+ ///
+ /// Returns an IExtra which must be part of the Extras of a task to describe the type
+ ///
+ static IExtra GetTypeExtra(Type type)
+ {
+ return new StringExtra() { Key="KP2A_APP_TASK_TYPE", Value=type.Name};
+ }
+
+ }
+}
+
diff --git a/src/keepass2android/fileselect/FileSelectActivity.cs b/src/keepass2android/fileselect/FileSelectActivity.cs
index ee44e4e3..39ba3d67 100644
--- a/src/keepass2android/fileselect/FileSelectActivity.cs
+++ b/src/keepass2android/fileselect/FileSelectActivity.cs
@@ -56,17 +56,16 @@ namespace keepass2android
private const int CMENU_CLEAR = Menu.First;
- public const String UrlToSearch_key = "UrlToSearch";
- const String BundleKey_UrlToSearchFor = "UrlToSearch";
const string BundleKey_RecentMode = "RecentMode";
private FileDbHelper mDbHelper;
- private String mUrlToSearch;
-
+
private bool recentMode = false;
view.FileSelectButtons fileSelectButtons;
bool createdWithActivityResult = false;
+ internal IAppTask mAppTask;
+
IOConnectionInfo loadIoc(string defaultFileName)
{
return mDbHelper.cursorToIoc(mDbHelper.fetchFileByName(defaultFileName));
@@ -205,11 +204,16 @@ namespace keepass2android
base.OnCreate(savedInstanceState);
Android.Util.Log.Debug("DEBUG", "FileSelect.OnCreate");
+ Android.Util.Log.Debug("DEBUG", "FileSelect:apptask="+Intent.GetStringExtra("KP2A_APP_TASK_TYPE"));
if (Intent.Action == Intent.ActionSend)
- mUrlToSearch = Intent.GetStringExtra(Intent.ExtraText);
+ {
+ mAppTask = new SearchUrlTask() { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
+ }
else
- mUrlToSearch = Intent.GetStringExtra(UrlToSearch_key);
+ {
+ mAppTask = AppTask.CreateFromIntent(Intent);
+ }
mDbHelper = App.fileDbHelper;
@@ -283,7 +287,7 @@ namespace keepass2android
if (savedInstanceState != null)
{
- mUrlToSearch = savedInstanceState.GetString(BundleKey_UrlToSearchFor, null);
+ mAppTask = AppTask.CreateFromBundle(savedInstanceState);
recentMode = savedInstanceState.GetBoolean(BundleKey_RecentMode, recentMode);
@@ -295,18 +299,18 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
- outState.PutString(BundleKey_UrlToSearchFor, mUrlToSearch);
+ mAppTask.ToBundle(outState);
outState.PutBoolean(BundleKey_RecentMode, recentMode);
}
private class LaunchGroupActivity : FileOnFinish {
- FileSelectActivity activty;
+ FileSelectActivity activity;
private IOConnectionInfo mIoc;
- public LaunchGroupActivity(IOConnectionInfo ioc, FileSelectActivity activty): base(null) {
+ public LaunchGroupActivity(IOConnectionInfo ioc, FileSelectActivity activity): base(null) {
- this.activty = activty;
+ this.activity = activity;
mIoc = ioc;
}
@@ -318,7 +322,7 @@ namespace keepass2android
//TODO: getFilename always returns "" -> bug?
dbHelper.createFile(mIoc, getFilename());
- GroupActivity.Launch(activty);
+ GroupActivity.Launch(activity, activity.mAppTask);
} else {
IOConnection.DeleteFile(mIoc);
@@ -380,7 +384,7 @@ namespace keepass2android
ioc.UserName = username;
ioc.Password = password;
ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode;
- PasswordActivity.Launch(this, ioc, mUrlToSearch);
+ PasswordActivity.Launch(this, ioc, mAppTask);
}));
builder.SetView(LayoutInflater.Inflate(Resource.Layout.url_credentials, null));
builder.SetNeutralButton(GetString(Android.Resource.String.Cancel),
@@ -395,7 +399,7 @@ namespace keepass2android
{
try
{
- PasswordActivity.Launch(this, ioc, mUrlToSearch);
+ PasswordActivity.Launch(this, ioc, mAppTask);
} catch (Java.IO.FileNotFoundException)
{
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
@@ -482,7 +486,7 @@ namespace keepass2android
{
if ((Intent.Action == Intent.ActionSend) && (App.getDB().Loaded))
{
- PasswordActivity.Launch(this, App.getDB().mIoc , mUrlToSearch);
+ PasswordActivity.Launch(this, App.getDB().mIoc , mAppTask);
} else
{
@@ -498,7 +502,7 @@ namespace keepass2android
{
try
{
- PasswordActivity.Launch(this, loadIoc(defaultFileName), mUrlToSearch);
+ PasswordActivity.Launch(this, loadIoc(defaultFileName), mAppTask);
} catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long);
diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj
index 29d87522..b14a19be 100644
--- a/src/keepass2android/keepass2android.csproj
+++ b/src/keepass2android/keepass2android.csproj
@@ -160,6 +160,7 @@
+
diff --git a/src/keepass2android/views/PwGroupView.cs b/src/keepass2android/views/PwGroupView.cs
index 5be3d751..8d49d1b4 100644
--- a/src/keepass2android/views/PwGroupView.cs
+++ b/src/keepass2android/views/PwGroupView.cs
@@ -89,7 +89,7 @@ namespace keepass2android.view
}
private void launchGroup() {
- GroupActivity.Launch(mAct, mPw);
+ GroupActivity.Launch(mAct, mPw, mAct.mAppTask);
mAct.OverridePendingTransition(Resource.Animation.anim_enter, Resource.Animation.anim_leave);
}