From 184f13b14812a82e0b589e824def44e27277c7e3 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 17 Nov 2017 14:38:56 -0500 Subject: [PATCH] save info from service to add cipher page --- src/Android/Autofill/AutofillHelpers.cs | 14 ++++-- src/Android/Autofill/AutofillService.cs | 22 +++++---- src/Android/Autofill/Parser.cs | 9 ++-- src/Android/MainActivity.cs | 25 ++++++++-- src/App/App.cs | 33 +++++++------ src/App/App.csproj | 1 + src/App/Models/AppOptions.cs | 14 ++++++ src/App/Pages/Vault/VaultAddCipherPage.cs | 56 ++++++++++++++++++++--- src/iOS/AppDelegate.cs | 1 - 9 files changed, 135 insertions(+), 40 deletions(-) create mode 100644 src/App/Models/AppOptions.cs diff --git a/src/Android/Autofill/AutofillHelpers.cs b/src/Android/Autofill/AutofillHelpers.cs index 79bad07bb..510667792 100644 --- a/src/Android/Autofill/AutofillHelpers.cs +++ b/src/Android/Autofill/AutofillHelpers.cs @@ -33,7 +33,7 @@ namespace Bit.Android.Autofill public static FillResponse BuildFillResponse(Context context, FieldCollection fields, List items) { var responseBuilder = new FillResponse.Builder(); - if(items != null) + if(items != null && items.Count > 0) { foreach(var item in items) { @@ -44,6 +44,8 @@ namespace Bit.Android.Autofill } } } + + AddSaveInfo(responseBuilder, fields); return responseBuilder.Build(); } @@ -64,11 +66,11 @@ namespace Bit.Android.Autofill var view = BuildListView(context.PackageName, "Autofill with bitwarden", "Vault locked", Resource.Drawable.icon); var intent = new Intent(context, typeof(MainActivity)); - intent.PutExtra("uri", uri); intent.PutExtra("autofillFramework", true); - //intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop); + intent.PutExtra("autofillFrameworkUri", uri); var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent); responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view); + AddSaveInfo(responseBuilder, fields); return responseBuilder.Build(); } @@ -81,6 +83,12 @@ namespace Bit.Android.Autofill return view; } + public static void AddSaveInfo(FillResponse.Builder responseBuilder, FieldCollection fields) + { + var saveInfo = new SaveInfo.Builder(SaveDataType.Password, fields.AutofillIds.ToArray()).Build(); + responseBuilder.SetSaveInfo(saveInfo); + } + public static List FilterForSupportedHints(string[] hints) { return hints?.Where(h => IsValidHint(h)).ToList() ?? new List(); diff --git a/src/Android/Autofill/AutofillService.cs b/src/Android/Autofill/AutofillService.cs index 46b0e40bd..395aaaf65 100644 --- a/src/Android/Autofill/AutofillService.cs +++ b/src/Android/Autofill/AutofillService.cs @@ -5,6 +5,7 @@ using Android.OS; using Android.Runtime; using Android.Service.Autofill; using Bit.App.Abstractions; +using Bit.App.Enums; using System.Linq; using XLabs.Ioc; @@ -41,7 +42,7 @@ namespace Bit.Android.Autofill _lockService = Resolver.Resolve(); } - var isLocked = (await _lockService.GetLockTypeAsync(false)) != App.Enums.LockType.None; + var isLocked = (await _lockService.GetLockTypeAsync(false)) != LockType.None; if(isLocked) { var authResponse = AutofillHelpers.BuildAuthResponse(this, parser.FieldCollection, parser.Uri); @@ -56,11 +57,6 @@ namespace Bit.Android.Autofill // build response var items = await AutofillHelpers.GetFillItemsAsync(_cipherService, parser.Uri); - if(!items.Any()) - { - return; - } - var response = AutofillHelpers.BuildFillResponse(this, parser.FieldCollection, items); callback.OnSuccess(response); } @@ -73,12 +69,18 @@ namespace Bit.Android.Autofill return; } - var clientState = request.ClientState; - var parser = new Parser(structure); parser.ParseForSave(); - var filledAutofillFieldCollection = parser.FilledFieldCollection; - //SaveFilledAutofillFieldCollection(filledAutofillFieldCollection); + + var intent = new Intent(this, typeof(MainActivity)); + intent.PutExtra("autofillFramework", true); + intent.PutExtra("autofillFrameworkSave", true); + intent.PutExtra("autofillFrameworkType", (int)CipherType.Login); + intent.PutExtra("autofillFrameworkUri", parser.Uri); + intent.PutExtra("autofillFrameworkUsername", "username"); + intent.PutExtra("autofillFrameworkPassword", "pass123"); + intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop); + StartActivity(intent); } } } diff --git a/src/Android/Autofill/Parser.cs b/src/Android/Autofill/Parser.cs index 681dca0a3..3deadb8b0 100644 --- a/src/Android/Autofill/Parser.cs +++ b/src/Android/Autofill/Parser.cs @@ -55,13 +55,14 @@ namespace Bit.Android.Autofill var isEditText = node.ClassName == "android.widget.EditText"; if(isEditText || (hints?.Length ?? 0) > 0) { + if(Uri == null) + { + Uri = node.IdPackage; + } + if(forFill) { FieldCollection.Add(new Field(node)); - if(Uri == null) - { - Uri = node.IdPackage; - } } else { diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index 975cd9303..b7754b8b3 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -23,6 +23,8 @@ using Android.Views.Autofill; using Android.App.Assist; using Bit.Android.Autofill; using System.Collections.Generic; +using Bit.App.Models; +using Bit.App.Enums; namespace Bit.Android { @@ -40,7 +42,6 @@ namespace Bit.Android protected override void OnCreate(Bundle bundle) { - var uri = Intent.GetStringExtra("uri"); if(!Resolver.IsSet) { MainApplication.SetIoc(Application); @@ -78,8 +79,7 @@ namespace Bit.Android _deviceActionService = Resolver.Resolve(); _settings = Resolver.Resolve(); LoadApplication(new App.App( - uri, - Intent.GetBooleanExtra("myVaultTile", false), + GetOptions(), Resolver.Resolve(), Resolver.Resolve(), Resolver.Resolve(), @@ -425,5 +425,24 @@ namespace Bit.Android } catch { } } + + private AppOptions GetOptions() + { + var options = new AppOptions + { + Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra("autofillFrameworkUri"), + MyVault = Intent.GetBooleanExtra("myVaultTile", false), + FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false) + }; + + if(Intent.GetBooleanExtra("autofillFrameworkSave", false)) + { + options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0); + options.SaveUsername = Intent.GetStringExtra("autofillFrameworkUsername"); + options.SavePassword = Intent.GetStringExtra("autofillFrameworkPassword"); + } + + return options; + } } } diff --git a/src/App/App.cs b/src/App/App.cs index 59469aab0..7a3e2e053 100644 --- a/src/App/App.cs +++ b/src/App/App.cs @@ -14,12 +14,13 @@ using XLabs.Ioc; using System.Reflection; using Bit.App.Resources; using Bit.App.Utilities; +using Bit.App.Models; namespace Bit.App { public class App : Application { - private string _uri; + private AppOptions _options; private readonly IDatabaseService _databaseService; private readonly IConnectivity _connectivity; private readonly IUserDialogs _userDialogs; @@ -34,8 +35,7 @@ namespace Bit.App private readonly IDeviceActionService _deviceActionService; public App( - string uri, - bool myVault, + AppOptions options, IAuthService authService, IConnectivity connectivity, IUserDialogs userDialogs, @@ -49,7 +49,7 @@ namespace Bit.App IAppSettingsService appSettingsService, IDeviceActionService deviceActionService) { - _uri = uri; + _options = options ?? new AppOptions(); _databaseService = databaseService; _connectivity = connectivity; _userDialogs = userDialogs; @@ -66,13 +66,20 @@ namespace Bit.App SetCulture(); SetStyles(); - if(authService.IsAuthenticated && _uri != null) + if(authService.IsAuthenticated) { - MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_uri)); - } - else if(authService.IsAuthenticated) - { - MainPage = new MainPage(myVault: myVault); + if(_options.FromAutofillFramework && _options.SaveType.HasValue) + { + MainPage = new ExtendedNavigationPage(new VaultAddCipherPage(_options)); + } + else if (_options.Uri != null) + { + MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options.Uri)); + } + else + { + MainPage = new MainPage(myVault: _options.MyVault); + } } else { @@ -101,7 +108,7 @@ namespace Bit.App // Handle when your app starts await CheckLockAsync(false); - if(string.IsNullOrWhiteSpace(_uri)) + if(string.IsNullOrWhiteSpace(_options.Uri)) { var updated = Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService, _syncService); if(!updated) @@ -168,14 +175,14 @@ namespace Bit.App private void SetMainPageFromAutofill() { - if(Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(_uri)) + if(Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(_options.Uri)) { Task.Run(() => { Device.BeginInvokeOnMainThread(() => { Current.MainPage = new MainPage(); - _uri = null; + _options.Uri = null; }); }); } diff --git a/src/App/App.csproj b/src/App/App.csproj index 0f828d1f5..5572a215f 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -129,6 +129,7 @@ + diff --git a/src/App/Models/AppOptions.cs b/src/App/Models/AppOptions.cs new file mode 100644 index 000000000..cbfe7efa5 --- /dev/null +++ b/src/App/Models/AppOptions.cs @@ -0,0 +1,14 @@ +using Bit.App.Enums; + +namespace Bit.App.Models +{ + public class AppOptions + { + public bool MyVault { get; set; } + public bool FromAutofillFramework { get; set; } + public string Uri { get; set; } + public CipherType? SaveType { get; set; } + public string SaveUsername { get; set; } + public string SavePassword { get; set; } + } +} diff --git a/src/App/Pages/Vault/VaultAddCipherPage.cs b/src/App/Pages/Vault/VaultAddCipherPage.cs index c1cc1e5c6..37bf0f786 100644 --- a/src/App/Pages/Vault/VaultAddCipherPage.cs +++ b/src/App/Pages/Vault/VaultAddCipherPage.cs @@ -12,6 +12,7 @@ using XLabs.Ioc; using Plugin.Settings.Abstractions; using Bit.App.Utilities; using Bit.App.Enums; +using Bit.App.Models.Page; namespace Bit.App.Pages { @@ -30,11 +31,23 @@ namespace Bit.App.Pages private readonly IDeviceInfoService _deviceInfo; private readonly string _defaultUri; private readonly string _defaultName; + private readonly string _defaultUsername; + private readonly string _defaultPassword; private readonly bool _fromAutofill; + private readonly bool _fromAutofillFramework; private DateTime? _lastAction; + public VaultAddCipherPage(AppOptions options) + : this(options.SaveType.Value, options.Uri, options.Uri, options.FromAutofillFramework, false) + { + _defaultUsername = options.SaveUsername; + _defaultPassword = options.SavePassword; + _fromAutofillFramework = options.FromAutofillFramework; + Init(); + } + public VaultAddCipherPage(CipherType type, string defaultUri = null, - string defaultName = null, bool fromAutofill = false) + string defaultName = null, bool fromAutofill = false, bool doInit = true) { _type = type; _defaultUri = defaultUri; @@ -50,7 +63,10 @@ namespace Bit.App.Pages _appInfoService = Resolver.Resolve(); _deviceInfo = Resolver.Resolve(); - Init(); + if(doInit) + { + Init(); + } } public List Folders { get; set; } @@ -266,10 +282,21 @@ namespace Bit.App.Pages } } + protected override bool OnBackButtonPressed() + { + if(_fromAutofillFramework) + { + Application.Current.MainPage = new MainPage(true); + return true; + } + + return base.OnBackButtonPressed(); + } + private void PasswordButton_Clicked(object sender, EventArgs e) { LoginPasswordCell.Entry.InvokeToggleIsPassword(); - LoginPasswordCell.Button.Image = + LoginPasswordCell.Button.Image = "eye" + (!LoginPasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png"; } @@ -335,7 +362,7 @@ namespace Bit.App.Pages } LoginTotpCell.Entry.DisableAutocapitalize = true; LoginTotpCell.Entry.Autocorrect = false; - LoginTotpCell.Entry.FontFamily = + LoginTotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier"); LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: LoginTotpCell.Entry, @@ -343,8 +370,12 @@ namespace Bit.App.Pages LoginPasswordCell.Button.Image = "eye.png"; LoginPasswordCell.Entry.DisableAutocapitalize = true; LoginPasswordCell.Entry.Autocorrect = false; - LoginPasswordCell.Entry.FontFamily = + LoginPasswordCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier"); + if(!string.IsNullOrWhiteSpace(_defaultPassword)) + { + LoginPasswordCell.Entry.Text = _defaultPassword; + } LoginGenerateCell = new ExtendedTextCell { @@ -355,6 +386,10 @@ namespace Bit.App.Pages LoginUsernameCell = new FormEntryCell(AppResources.Username, nextElement: LoginPasswordCell.Entry); LoginUsernameCell.Entry.DisableAutocapitalize = true; LoginUsernameCell.Entry.Autocorrect = false; + if(!string.IsNullOrWhiteSpace(_defaultUsername)) + { + LoginUsernameCell.Entry.Text = _defaultUsername; + } LoginUriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: LoginUsernameCell.Entry); if(!string.IsNullOrWhiteSpace(_defaultUri)) @@ -679,7 +714,16 @@ namespace Bit.App.Pages { _googleAnalyticsService.TrackAppEvent("CreatedCipher"); } - await Navigation.PopForDeviceAsync(); + + if(_fromAutofillFramework) + { + // close and go back to app + MessagingCenter.Send(Application.Current, "Autofill", (VaultListPageModel.Cipher)null); + } + else + { + await Navigation.PopForDeviceAsync(); + } } else if(saveTask.Errors.Count() > 0) { diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs index 1a72e4b6a..53b96584a 100644 --- a/src/iOS/AppDelegate.cs +++ b/src/iOS/AppDelegate.cs @@ -55,7 +55,6 @@ namespace Bit.iOS LoadApplication(new App.App( null, - false, Resolver.Resolve(), Resolver.Resolve(), Resolver.Resolve(),