improved error handling for dropbox filestorage

This commit is contained in:
Philipp Crocoll 2013-09-17 06:53:18 +02:00
parent 15fde6ff92
commit 176ad6244d
8 changed files with 186 additions and 106 deletions

View File

@ -30,7 +30,8 @@ namespace keepass2android
public static void Log(string message)
{
Android.Util.Log.Debug("KP2A", message);
if (message != null)
Android.Util.Log.Debug("KP2A", message);
if (LogToFile)
{
lock (_fileLocker)

View File

@ -17,8 +17,8 @@ namespace keepass2android.Io
{
public class DropboxFileStorage: JavaFileStorage
{
public DropboxFileStorage(Context ctx) :
base(new Keepass2android.Javafilestorage.DropboxFileStorage(ctx))
public DropboxFileStorage(Context ctx, IKp2aApp app) :
base(new Keepass2android.Javafilestorage.DropboxFileStorage(ctx), app)
{
}

View File

@ -1,16 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Java.Lang;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using Keepass2android.Javafilestorage;
@ -23,11 +14,13 @@ namespace keepass2android.Io
{
public abstract IEnumerable<string> SupportedProtocols { get; }
private IJavaFileStorage _jfs;
private readonly IJavaFileStorage _jfs;
private readonly IKp2aApp _app;
public JavaFileStorage(IJavaFileStorage jfs)
public JavaFileStorage(IJavaFileStorage jfs, IKp2aApp app)
{
this._jfs = jfs;
_jfs = jfs;
_app = app;
}
public void DeleteFile(IOConnectionInfo ioc)
@ -37,14 +30,17 @@ namespace keepass2android.Io
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
{
try
return false;
//commented because this currently might use the network which is not permitted here
/*try
{
return _jfs.CheckForFileChangeFast(ioc.Path, previousFileVersion);
return Jfs.CheckForFileChangeFast(ioc.Path, previousFileVersion);
}
catch (Java.Lang.Exception e)
{
throw LogAndConvertJavaException(e);
}
}*/
}
@ -52,7 +48,7 @@ namespace keepass2android.Io
{
try
{
return _jfs.GetCurrentFileVersionFast(ioc.Path);
return Jfs.GetCurrentFileVersionFast(ioc.Path);
}
catch (Java.Lang.Exception e)
{
@ -64,7 +60,7 @@ namespace keepass2android.Io
{
try
{
return _jfs.OpenFileForRead(IocToPath(ioc));
return Jfs.OpenFileForRead(IocToPath(ioc));
}
catch (FileNotFoundException e)
{
@ -77,28 +73,35 @@ namespace keepass2android.Io
}
private static Exception LogAndConvertJavaException(Java.Lang.Exception e)
private Exception LogAndConvertJavaException(Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
var ex = new Exception(e.LocalizedMessage ?? e.Message, e);
var ex = new Exception(e.LocalizedMessage ??
e.Message ??
_app.GetResourceString(UiStringKey.ErrorOcurred)+e, e);
return ex;
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
{
return new JavaFileStorageWriteTransaction(IocToPath(ioc), useFileTransaction, _jfs);
return new JavaFileStorageWriteTransaction(IocToPath(ioc), useFileTransaction, this);
}
public IFileStorageSetup RequiredSetup
{
get
{
if (_jfs.IsConnected)
if (Jfs.IsConnected)
return null;
return new JavaFileStorageSetup(this);
}
}
internal IJavaFileStorage Jfs
{
get { return _jfs; }
}
public class JavaFileStorageSetup : IFileStorageSetup, IFileStorageSetupOnResume
{
private readonly JavaFileStorage _javaFileStorage;
@ -112,11 +115,11 @@ namespace keepass2android.Io
{
try
{
return _javaFileStorage._jfs.TryConnect(activity);
return _javaFileStorage.Jfs.TryConnect(activity);
}
catch (Java.Lang.Exception e)
{
throw LogAndConvertJavaException(e);
throw _javaFileStorage.LogAndConvertJavaException(e);
}
}
@ -124,12 +127,12 @@ namespace keepass2android.Io
{
try
{
_javaFileStorage._jfs.OnResume();
return _javaFileStorage._jfs.IsConnected;
_javaFileStorage.Jfs.OnResume();
return _javaFileStorage.Jfs.IsConnected;
}
catch (Java.Lang.Exception e)
{
throw LogAndConvertJavaException(e);
throw _javaFileStorage.LogAndConvertJavaException(e);
}
}
}
@ -138,10 +141,10 @@ namespace keepass2android.Io
{
private readonly string _path;
private readonly bool _useFileTransaction;
private readonly IJavaFileStorage _javaFileStorage;
private readonly JavaFileStorage _javaFileStorage;
private MemoryStream _memoryStream;
public JavaFileStorageWriteTransaction(string path, bool useFileTransaction, IJavaFileStorage javaFileStorage)
public JavaFileStorageWriteTransaction(string path, bool useFileTransaction, JavaFileStorage javaFileStorage)
{
_path = path;
_useFileTransaction = useFileTransaction;
@ -163,11 +166,11 @@ namespace keepass2android.Io
{
try
{
_javaFileStorage.UploadFile(_path, _memoryStream.ToArray(), _useFileTransaction);
_javaFileStorage.Jfs.UploadFile(_path, _memoryStream.ToArray(), _useFileTransaction);
}
catch (Java.Lang.Exception e)
{
LogAndConvertJavaException(e);
throw _javaFileStorage.LogAndConvertJavaException(e);
}
}
}

View File

@ -22,6 +22,7 @@ import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.android.AuthActivity;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.exception.DropboxUnlinkedException;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;
import com.dropbox.client2.session.TokenPair;
@ -182,6 +183,14 @@ public class DropboxFileStorage implements JavaFileStorage {
Log.d(TAG, "Exception of type " +e.getClass().getName()+":" + e.getMessage());
if (DropboxUnlinkedException.class.isAssignableFrom(e.getClass()) )
{
Log.d(TAG, "LoggedIn=false (due to unlink exception)");
setLoggedIn(false);
return new Exception("Unlinked from Dropbox!", e);
}
//test for special error FileNotFound which must be reported with FileNotFoundException
if (DropboxServerException.class.isAssignableFrom(e.getClass()) )
{

View File

@ -47,9 +47,9 @@ namespace keepass2android
public const String KeyFilename = "fileName";
private const String KeyKeyfile = "keyFile";
private const String KeyServerusername = "serverCredUser";
private const String KeyServerpassword = "serverCredPwd";
private const String KeyServercredmode = "serverCredRememberMode";
public const String KeyServerusername = "serverCredUser";
public const String KeyServerpassword = "serverCredPwd";
public const String KeyServercredmode = "serverCredRememberMode";
private const String ViewIntent = "android.intent.action.VIEW";
private const string ShowpasswordKey = "ShowPassword";
@ -74,7 +74,7 @@ namespace keepass2android
}
static void PutIoConnectionToIntent(IOConnectionInfo ioc, Intent i)
public static void PutIoConnectionToIntent(IOConnectionInfo ioc, Intent i)
{
i.PutExtra(KeyFilename, ioc.Path);
i.PutExtra(KeyServerusername, ioc.UserName);
@ -463,10 +463,23 @@ namespace keepass2android
Kp2aLog.Log("Starting QuickUnlock");
StartActivityForResult(i, 0);
}
else if (_loadDbTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
else
{
// Create task to kick off file loading while the user enters the password
_loadDbTask = Task.Factory.StartNew<MemoryStream>(LoadDbFile);
//database not yet loaded.
//check if FileStorage setup is all done. Usually this should not occur here because the setup is
//performed in FileSelectActivity, but e.g. if the user unlinks from Dropbox saving might fail and
//the user is returned here.
if (App.Kp2a.GetFileStorage(_ioConnection).RequiredSetup != null)
{
GoToFileSelectActivity();
}
//check if pre-loading is enabled but wasn't started yet:
else if (_loadDbTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
{
// Create task to kick off file loading while the user enters the password
_loadDbTask = Task.Factory.StartNew<MemoryStream>(LoadDbFile);
}
}
}
}
@ -539,20 +552,21 @@ namespace keepass2android
return true;
case Resource.Id.menu_change_db:
Intent intent = new Intent(this, typeof(FileSelectActivity));
AppTask.ToIntent(intent);
StartActivityForResult(intent, 0);
Finish();
GoToFileSelectActivity();
return true;
}
return base.OnOptionsItemSelected(item);
}
private void GoToFileSelectActivity()
{
Intent intent = new Intent(this, typeof (FileSelectActivity));
AppTask.ToIntent(intent);
StartActivityForResult(intent, 0);
Finish();
}
private class AfterLoad : OnFinish {
readonly PasswordActivity _act;

View File

@ -1403,41 +1403,41 @@ namespace keepass2android
// aapt resource value: 0x7f060113
public const int BinaryDirectory_title = 2131099923;
// aapt resource value: 0x7f060166
public const int CannotMoveGroupHere = 2131100006;
// aapt resource value: 0x7f060167
public const int CannotMoveGroupHere = 2131100007;
// aapt resource value: 0x7f06017b
public const int ChangeLog = 2131100027;
// aapt resource value: 0x7f06017a
public const int ChangeLog = 2131100026;
// aapt resource value: 0x7f060179
public const int ChangeLog_0_7 = 2131100025;
// aapt resource value: 0x7f060177
public const int ChangeLog_0_8 = 2131100023;
// aapt resource value: 0x7f060176
public const int ChangeLog_0_8_1 = 2131100022;
// aapt resource value: 0x7f060175
public const int ChangeLog_0_8_2 = 2131100021;
// aapt resource value: 0x7f060174
public const int ChangeLog_0_8_3 = 2131100020;
// aapt resource value: 0x7f060173
public const int ChangeLog_0_8_4 = 2131100019;
// aapt resource value: 0x7f060172
public const int ChangeLog_0_8_5 = 2131100018;
// aapt resource value: 0x7f060171
public const int ChangeLog_0_8_6 = 2131100017;
public const int ChangeLog_0_7 = 2131100026;
// aapt resource value: 0x7f060178
public const int ChangeLog_keptDonate = 2131100024;
public const int ChangeLog_0_8 = 2131100024;
// aapt resource value: 0x7f060170
public const int ChangeLog_title = 2131100016;
// aapt resource value: 0x7f060177
public const int ChangeLog_0_8_1 = 2131100023;
// aapt resource value: 0x7f060176
public const int ChangeLog_0_8_2 = 2131100022;
// aapt resource value: 0x7f060175
public const int ChangeLog_0_8_3 = 2131100021;
// aapt resource value: 0x7f060174
public const int ChangeLog_0_8_4 = 2131100020;
// aapt resource value: 0x7f060173
public const int ChangeLog_0_8_5 = 2131100019;
// aapt resource value: 0x7f060172
public const int ChangeLog_0_8_6 = 2131100018;
// aapt resource value: 0x7f060179
public const int ChangeLog_keptDonate = 2131100025;
// aapt resource value: 0x7f060171
public const int ChangeLog_title = 2131100017;
// aapt resource value: 0x7f060032
public const int CheckForFileChangesOnSave_key = 2131099698;
@ -1487,6 +1487,9 @@ namespace keepass2android
// aapt resource value: 0x7f060158
public const int DownloadingRemoteFile = 2131099992;
// aapt resource value: 0x7f060165
public const int ErrorOcurred = 2131100005;
// aapt resource value: 0x7f060055
public const int FileHandling_prefs = 2131099733;
@ -1898,8 +1901,8 @@ namespace keepass2android
// aapt resource value: 0x7f060027
public const int display_prefs_key = 2131099687;
// aapt resource value: 0x7f060167
public const int donate_question = 2131100007;
// aapt resource value: 0x7f060168
public const int donate_question = 2131100008;
// aapt resource value: 0x7f06000c
public const int donate_url = 2131099660;
@ -2054,23 +2057,23 @@ namespace keepass2android
// aapt resource value: 0x7f060094
public const int file_browser = 2131099796;
// aapt resource value: 0x7f06016e
public const int filestoragename_dropbox = 2131100014;
// aapt resource value: 0x7f06016a
public const int filestoragename_file = 2131100010;
// aapt resource value: 0x7f06016f
public const int filestoragename_dropbox = 2131100015;
// aapt resource value: 0x7f06016b
public const int filestoragename_ftp = 2131100011;
// aapt resource value: 0x7f06016f
public const int filestoragename_gdrive = 2131100015;
public const int filestoragename_file = 2131100011;
// aapt resource value: 0x7f06016c
public const int filestoragename_http = 2131100012;
public const int filestoragename_ftp = 2131100012;
// aapt resource value: 0x7f060170
public const int filestoragename_gdrive = 2131100016;
// aapt resource value: 0x7f06016d
public const int filestoragename_https = 2131100013;
public const int filestoragename_http = 2131100013;
// aapt resource value: 0x7f06016e
public const int filestoragename_https = 2131100014;
// aapt resource value: 0x7f06000f
public const int further_author_names = 2131099663;
@ -2282,8 +2285,8 @@ namespace keepass2android
// aapt resource value: 0x7f0600cc
public const int no_results = 2131099852;
// aapt resource value: 0x7f060169
public const int no_thanks = 2131100009;
// aapt resource value: 0x7f06016a
public const int no_thanks = 2131100010;
// aapt resource value: 0x7f0600cd
public const int no_url_handler = 2131099853;
@ -2297,8 +2300,8 @@ namespace keepass2android
// aapt resource value: 0x7f060012
public const int oi_filemanager_web = 2131099666;
// aapt resource value: 0x7f060168
public const int ok_donate = 2131100008;
// aapt resource value: 0x7f060169
public const int ok_donate = 2131100009;
// aapt resource value: 0x7f06001b
public const int omitbackup_key = 2131099675;
@ -2444,8 +2447,8 @@ namespace keepass2android
// aapt resource value: 0x7f060145
public const int suggest_improvements = 2131099973;
// aapt resource value: 0x7f060165
public const int synchronize_database_menu = 2131100005;
// aapt resource value: 0x7f060166
public const int synchronize_database_menu = 2131100006;
// aapt resource value: 0x7f060147
public const int translate_app = 2131099975;

View File

@ -386,7 +386,7 @@ namespace keepass2android
{
_fileStorages = new List<IFileStorage>
{
new DropboxFileStorage(Application.Context),
new DropboxFileStorage(Application.Context, this),
new BuiltInFileStorage()
};
}

View File

@ -25,6 +25,7 @@ using Android.Views;
using Android.Widget;
using Android.Content.PM;
using KeePassLib.Serialization;
using keepass2android.Io;
namespace keepass2android
{
@ -59,9 +60,9 @@ namespace keepass2android
private bool _recentMode;
view.FileSelectButtons _fileSelectButtons;
bool _createdWithActivityResult;
internal AppTask AppTask;
private IOConnectionInfo _iocToLaunch;
void ShowFilenameDialog(bool showOpenButton, bool showCreateButton, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
{
@ -279,6 +280,18 @@ namespace keepass2android
AppTask = AppTask.CreateFromBundle(savedInstanceState);
_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
string filenameToLaunch = savedInstanceState.GetString(PasswordActivity.KeyFilename);
if (filenameToLaunch != null)
{
_iocToLaunch = new IOConnectionInfo()
{
Path = filenameToLaunch,
UserName = savedInstanceState.GetString(PasswordActivity.KeyServerusername),
Password = savedInstanceState.GetString(PasswordActivity.KeyServerpassword),
CredSaveMode = (IOCredSaveMode) savedInstanceState.GetInt(PasswordActivity.KeyServercredmode)
};
}
}
@ -305,6 +318,14 @@ namespace keepass2android
base.OnSaveInstanceState(outState);
AppTask.ToBundle(outState);
outState.PutBoolean(BundleKeyRecentMode, _recentMode);
if (_iocToLaunch != null)
{
outState.PutString(PasswordActivity.KeyFilename, _iocToLaunch.Path);
outState.PutString(PasswordActivity.KeyServerusername, _iocToLaunch.UserName);
outState.PutString(PasswordActivity.KeyServerpassword, _iocToLaunch.Password);
outState.PutInt(PasswordActivity.KeyServercredmode, (int)_iocToLaunch.CredSaveMode);
}
}
private class LaunchGroupActivity : FileOnFinish {
@ -382,7 +403,18 @@ namespace keepass2android
void LaunchPasswordActivityForIoc(IOConnectionInfo ioc)
{
if (App.Kp2a.GetFileStorage(ioc).RequiresCredentials(ioc))
IFileStorage fileStorage = App.Kp2a.GetFileStorage(ioc);
if (fileStorage.RequiredSetup != null)
{
if (!fileStorage.RequiredSetup.TrySetup(this))
{
//store ioc to launch. TrySetup hopefully launched another activity so we can check again in OnResume
_iocToLaunch = ioc;
return;
}
}
if (fileStorage.RequiresCredentials(ioc))
{
//Build dialog to query credentials:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@ -416,7 +448,7 @@ namespace keepass2android
Finish();
} catch (Java.IO.FileNotFoundException)
{
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
}
}
}
@ -439,8 +471,6 @@ namespace keepass2android
{
base.OnActivityResult(requestCode, resultCode, data);
_createdWithActivityResult = true;
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
{
Finish();
@ -501,8 +531,29 @@ namespace keepass2android
Intent intent = Intent;
StartActivity(intent);
Finish();
return;
}
//check if we are resuming after setting up the file storage:
if (_iocToLaunch != null)
{
try
{
IOConnectionInfo iocToLaunch = _iocToLaunch;
_iocToLaunch = null;
IFileStorageSetupOnResume fsSetup = App.Kp2a.GetFileStorage(iocToLaunch).RequiredSetup as IFileStorageSetupOnResume;
if ((fsSetup == null) || (fsSetup.TrySetupOnResume(this)))
{
LaunchPasswordActivityForIoc(iocToLaunch);
}
}
catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
}
}
_fileSelectButtons.UpdateExternalStorageWarning();
@ -517,8 +568,7 @@ namespace keepass2android
var db = App.Kp2a.GetDb();
if (db.Loaded)
{
PasswordActivity.Launch(this, db.Ioc, AppTask);
Finish();
LaunchPasswordActivityForIoc(db.Ioc);
}