save info from service to add cipher page

This commit is contained in:
Kyle Spearrin 2017-11-17 14:38:56 -05:00
parent d1c7309b29
commit 184f13b148
9 changed files with 135 additions and 40 deletions

View file

@ -33,7 +33,7 @@ namespace Bit.Android.Autofill
public static FillResponse BuildFillResponse(Context context, FieldCollection fields, List<IFilledItem> items) public static FillResponse BuildFillResponse(Context context, FieldCollection fields, List<IFilledItem> items)
{ {
var responseBuilder = new FillResponse.Builder(); var responseBuilder = new FillResponse.Builder();
if(items != null) if(items != null && items.Count > 0)
{ {
foreach(var item in items) foreach(var item in items)
{ {
@ -44,6 +44,8 @@ namespace Bit.Android.Autofill
} }
} }
} }
AddSaveInfo(responseBuilder, fields);
return responseBuilder.Build(); return responseBuilder.Build();
} }
@ -64,11 +66,11 @@ namespace Bit.Android.Autofill
var view = BuildListView(context.PackageName, "Autofill with bitwarden", var view = BuildListView(context.PackageName, "Autofill with bitwarden",
"Vault locked", Resource.Drawable.icon); "Vault locked", Resource.Drawable.icon);
var intent = new Intent(context, typeof(MainActivity)); var intent = new Intent(context, typeof(MainActivity));
intent.PutExtra("uri", uri);
intent.PutExtra("autofillFramework", true); intent.PutExtra("autofillFramework", true);
//intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop); intent.PutExtra("autofillFrameworkUri", uri);
var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent); var pendingIntent = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent);
responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view); responseBuilder.SetAuthentication(fields.AutofillIds.ToArray(), pendingIntent.IntentSender, view);
AddSaveInfo(responseBuilder, fields);
return responseBuilder.Build(); return responseBuilder.Build();
} }
@ -81,6 +83,12 @@ namespace Bit.Android.Autofill
return view; 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<string> FilterForSupportedHints(string[] hints) public static List<string> FilterForSupportedHints(string[] hints)
{ {
return hints?.Where(h => IsValidHint(h)).ToList() ?? new List<string>(); return hints?.Where(h => IsValidHint(h)).ToList() ?? new List<string>();

View file

@ -5,6 +5,7 @@ using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Service.Autofill; using Android.Service.Autofill;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Enums;
using System.Linq; using System.Linq;
using XLabs.Ioc; using XLabs.Ioc;
@ -41,7 +42,7 @@ namespace Bit.Android.Autofill
_lockService = Resolver.Resolve<ILockService>(); _lockService = Resolver.Resolve<ILockService>();
} }
var isLocked = (await _lockService.GetLockTypeAsync(false)) != App.Enums.LockType.None; var isLocked = (await _lockService.GetLockTypeAsync(false)) != LockType.None;
if(isLocked) if(isLocked)
{ {
var authResponse = AutofillHelpers.BuildAuthResponse(this, parser.FieldCollection, parser.Uri); var authResponse = AutofillHelpers.BuildAuthResponse(this, parser.FieldCollection, parser.Uri);
@ -56,11 +57,6 @@ namespace Bit.Android.Autofill
// build response // build response
var items = await AutofillHelpers.GetFillItemsAsync(_cipherService, parser.Uri); var items = await AutofillHelpers.GetFillItemsAsync(_cipherService, parser.Uri);
if(!items.Any())
{
return;
}
var response = AutofillHelpers.BuildFillResponse(this, parser.FieldCollection, items); var response = AutofillHelpers.BuildFillResponse(this, parser.FieldCollection, items);
callback.OnSuccess(response); callback.OnSuccess(response);
} }
@ -73,12 +69,18 @@ namespace Bit.Android.Autofill
return; return;
} }
var clientState = request.ClientState;
var parser = new Parser(structure); var parser = new Parser(structure);
parser.ParseForSave(); 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);
} }
} }
} }

View file

@ -55,13 +55,14 @@ namespace Bit.Android.Autofill
var isEditText = node.ClassName == "android.widget.EditText"; var isEditText = node.ClassName == "android.widget.EditText";
if(isEditText || (hints?.Length ?? 0) > 0) if(isEditText || (hints?.Length ?? 0) > 0)
{ {
if(Uri == null)
{
Uri = node.IdPackage;
}
if(forFill) if(forFill)
{ {
FieldCollection.Add(new Field(node)); FieldCollection.Add(new Field(node));
if(Uri == null)
{
Uri = node.IdPackage;
}
} }
else else
{ {

View file

@ -23,6 +23,8 @@ using Android.Views.Autofill;
using Android.App.Assist; using Android.App.Assist;
using Bit.Android.Autofill; using Bit.Android.Autofill;
using System.Collections.Generic; using System.Collections.Generic;
using Bit.App.Models;
using Bit.App.Enums;
namespace Bit.Android namespace Bit.Android
{ {
@ -40,7 +42,6 @@ namespace Bit.Android
protected override void OnCreate(Bundle bundle) protected override void OnCreate(Bundle bundle)
{ {
var uri = Intent.GetStringExtra("uri");
if(!Resolver.IsSet) if(!Resolver.IsSet)
{ {
MainApplication.SetIoc(Application); MainApplication.SetIoc(Application);
@ -78,8 +79,7 @@ namespace Bit.Android
_deviceActionService = Resolver.Resolve<IDeviceActionService>(); _deviceActionService = Resolver.Resolve<IDeviceActionService>();
_settings = Resolver.Resolve<ISettings>(); _settings = Resolver.Resolve<ISettings>();
LoadApplication(new App.App( LoadApplication(new App.App(
uri, GetOptions(),
Intent.GetBooleanExtra("myVaultTile", false),
Resolver.Resolve<IAuthService>(), Resolver.Resolve<IAuthService>(),
Resolver.Resolve<IConnectivity>(), Resolver.Resolve<IConnectivity>(),
Resolver.Resolve<IUserDialogs>(), Resolver.Resolve<IUserDialogs>(),
@ -425,5 +425,24 @@ namespace Bit.Android
} }
catch { } 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;
}
} }
} }

View file

@ -14,12 +14,13 @@ using XLabs.Ioc;
using System.Reflection; using System.Reflection;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.App.Models;
namespace Bit.App namespace Bit.App
{ {
public class App : Application public class App : Application
{ {
private string _uri; private AppOptions _options;
private readonly IDatabaseService _databaseService; private readonly IDatabaseService _databaseService;
private readonly IConnectivity _connectivity; private readonly IConnectivity _connectivity;
private readonly IUserDialogs _userDialogs; private readonly IUserDialogs _userDialogs;
@ -34,8 +35,7 @@ namespace Bit.App
private readonly IDeviceActionService _deviceActionService; private readonly IDeviceActionService _deviceActionService;
public App( public App(
string uri, AppOptions options,
bool myVault,
IAuthService authService, IAuthService authService,
IConnectivity connectivity, IConnectivity connectivity,
IUserDialogs userDialogs, IUserDialogs userDialogs,
@ -49,7 +49,7 @@ namespace Bit.App
IAppSettingsService appSettingsService, IAppSettingsService appSettingsService,
IDeviceActionService deviceActionService) IDeviceActionService deviceActionService)
{ {
_uri = uri; _options = options ?? new AppOptions();
_databaseService = databaseService; _databaseService = databaseService;
_connectivity = connectivity; _connectivity = connectivity;
_userDialogs = userDialogs; _userDialogs = userDialogs;
@ -66,13 +66,20 @@ namespace Bit.App
SetCulture(); SetCulture();
SetStyles(); SetStyles();
if(authService.IsAuthenticated && _uri != null) if(authService.IsAuthenticated)
{ {
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_uri)); if(_options.FromAutofillFramework && _options.SaveType.HasValue)
} {
else if(authService.IsAuthenticated) MainPage = new ExtendedNavigationPage(new VaultAddCipherPage(_options));
{ }
MainPage = new MainPage(myVault: myVault); else if (_options.Uri != null)
{
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_options.Uri));
}
else
{
MainPage = new MainPage(myVault: _options.MyVault);
}
} }
else else
{ {
@ -101,7 +108,7 @@ namespace Bit.App
// Handle when your app starts // Handle when your app starts
await CheckLockAsync(false); await CheckLockAsync(false);
if(string.IsNullOrWhiteSpace(_uri)) if(string.IsNullOrWhiteSpace(_options.Uri))
{ {
var updated = Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService, _syncService); var updated = Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService, _syncService);
if(!updated) if(!updated)
@ -168,14 +175,14 @@ namespace Bit.App
private void SetMainPageFromAutofill() private void SetMainPageFromAutofill()
{ {
if(Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(_uri)) if(Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(_options.Uri))
{ {
Task.Run(() => Task.Run(() =>
{ {
Device.BeginInvokeOnMainThread(() => Device.BeginInvokeOnMainThread(() =>
{ {
Current.MainPage = new MainPage(); Current.MainPage = new MainPage();
_uri = null; _options.Uri = null;
}); });
}); });
} }

View file

@ -129,6 +129,7 @@
<Compile Include="Models\Api\Response\TokenResponse.cs" /> <Compile Include="Models\Api\Response\TokenResponse.cs" />
<Compile Include="Models\Api\Response\ProfileResponse.cs" /> <Compile Include="Models\Api\Response\ProfileResponse.cs" />
<Compile Include="Models\Api\LoginDataModel.cs" /> <Compile Include="Models\Api\LoginDataModel.cs" />
<Compile Include="Models\AppOptions.cs" />
<Compile Include="Models\Card.cs" /> <Compile Include="Models\Card.cs" />
<Compile Include="Models\CipherString.cs" /> <Compile Include="Models\CipherString.cs" />
<Compile Include="Models\Data\AttachmentData.cs" /> <Compile Include="Models\Data\AttachmentData.cs" />

View file

@ -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; }
}
}

View file

@ -12,6 +12,7 @@ using XLabs.Ioc;
using Plugin.Settings.Abstractions; using Plugin.Settings.Abstractions;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.App.Enums; using Bit.App.Enums;
using Bit.App.Models.Page;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -30,11 +31,23 @@ namespace Bit.App.Pages
private readonly IDeviceInfoService _deviceInfo; private readonly IDeviceInfoService _deviceInfo;
private readonly string _defaultUri; private readonly string _defaultUri;
private readonly string _defaultName; private readonly string _defaultName;
private readonly string _defaultUsername;
private readonly string _defaultPassword;
private readonly bool _fromAutofill; private readonly bool _fromAutofill;
private readonly bool _fromAutofillFramework;
private DateTime? _lastAction; 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, public VaultAddCipherPage(CipherType type, string defaultUri = null,
string defaultName = null, bool fromAutofill = false) string defaultName = null, bool fromAutofill = false, bool doInit = true)
{ {
_type = type; _type = type;
_defaultUri = defaultUri; _defaultUri = defaultUri;
@ -50,7 +63,10 @@ namespace Bit.App.Pages
_appInfoService = Resolver.Resolve<IAppInfoService>(); _appInfoService = Resolver.Resolve<IAppInfoService>();
_deviceInfo = Resolver.Resolve<IDeviceInfoService>(); _deviceInfo = Resolver.Resolve<IDeviceInfoService>();
Init(); if(doInit)
{
Init();
}
} }
public List<Folder> Folders { get; set; } public List<Folder> 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) private void PasswordButton_Clicked(object sender, EventArgs e)
{ {
LoginPasswordCell.Entry.InvokeToggleIsPassword(); LoginPasswordCell.Entry.InvokeToggleIsPassword();
LoginPasswordCell.Button.Image = LoginPasswordCell.Button.Image =
"eye" + (!LoginPasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png"; "eye" + (!LoginPasswordCell.Entry.IsPasswordFromToggled ? "_slash" : string.Empty) + ".png";
} }
@ -335,7 +362,7 @@ namespace Bit.App.Pages
} }
LoginTotpCell.Entry.DisableAutocapitalize = true; LoginTotpCell.Entry.DisableAutocapitalize = true;
LoginTotpCell.Entry.Autocorrect = false; LoginTotpCell.Entry.Autocorrect = false;
LoginTotpCell.Entry.FontFamily = LoginTotpCell.Entry.FontFamily =
Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier"); Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: LoginTotpCell.Entry, LoginPasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: LoginTotpCell.Entry,
@ -343,8 +370,12 @@ namespace Bit.App.Pages
LoginPasswordCell.Button.Image = "eye.png"; LoginPasswordCell.Button.Image = "eye.png";
LoginPasswordCell.Entry.DisableAutocapitalize = true; LoginPasswordCell.Entry.DisableAutocapitalize = true;
LoginPasswordCell.Entry.Autocorrect = false; LoginPasswordCell.Entry.Autocorrect = false;
LoginPasswordCell.Entry.FontFamily = LoginPasswordCell.Entry.FontFamily =
Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier"); Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
if(!string.IsNullOrWhiteSpace(_defaultPassword))
{
LoginPasswordCell.Entry.Text = _defaultPassword;
}
LoginGenerateCell = new ExtendedTextCell LoginGenerateCell = new ExtendedTextCell
{ {
@ -355,6 +386,10 @@ namespace Bit.App.Pages
LoginUsernameCell = new FormEntryCell(AppResources.Username, nextElement: LoginPasswordCell.Entry); LoginUsernameCell = new FormEntryCell(AppResources.Username, nextElement: LoginPasswordCell.Entry);
LoginUsernameCell.Entry.DisableAutocapitalize = true; LoginUsernameCell.Entry.DisableAutocapitalize = true;
LoginUsernameCell.Entry.Autocorrect = false; LoginUsernameCell.Entry.Autocorrect = false;
if(!string.IsNullOrWhiteSpace(_defaultUsername))
{
LoginUsernameCell.Entry.Text = _defaultUsername;
}
LoginUriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: LoginUsernameCell.Entry); LoginUriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: LoginUsernameCell.Entry);
if(!string.IsNullOrWhiteSpace(_defaultUri)) if(!string.IsNullOrWhiteSpace(_defaultUri))
@ -679,7 +714,16 @@ namespace Bit.App.Pages
{ {
_googleAnalyticsService.TrackAppEvent("CreatedCipher"); _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) else if(saveTask.Errors.Count() > 0)
{ {

View file

@ -55,7 +55,6 @@ namespace Bit.iOS
LoadApplication(new App.App( LoadApplication(new App.App(
null, null,
false,
Resolver.Resolve<IAuthService>(), Resolver.Resolve<IAuthService>(),
Resolver.Resolve<IConnectivity>(), Resolver.Resolve<IConnectivity>(),
Resolver.Resolve<IUserDialogs>(), Resolver.Resolve<IUserDialogs>(),