add tools page for autofill service

This commit is contained in:
Kyle Spearrin 2017-11-27 17:27:11 -05:00
parent 9bbddd6aeb
commit 783c4d104c
17 changed files with 222 additions and 5 deletions

View file

@ -1,4 +1,5 @@
using Android.App;
using Android.Views.Autofill;
using Bit.App.Abstractions;
using System.Linq;
using AndroidApp = Android.App.Application;
@ -13,14 +14,27 @@ namespace Bit.Android.Services
public string Build => AndroidApp.Context.ApplicationContext.PackageManager
.GetPackageInfo(AndroidApp.Context.PackageName, 0).VersionCode.ToString();
public bool AutofillServiceEnabled => AutofillRunning();
public bool AutofillAccessibilityServiceEnabled => AutofillAccessibilityRunning();
public bool AutofillServiceEnabled => AutofillEnabled();
private bool AutofillRunning()
private bool AutofillAccessibilityRunning()
{
var manager = ((ActivityManager)Xamarin.Forms.Forms.Context.GetSystemService("activity"));
var services = manager.GetRunningServices(int.MaxValue);
return services.Any(s => s.Process.ToLowerInvariant().Contains("bitwarden") &&
s.Service.ClassName.ToLowerInvariant().Contains("autofill"));
}
private bool AutofillEnabled()
{
if(global::Android.OS.Build.VERSION.SdkInt < global::Android.OS.BuildVersionCodes.O)
{
return false;
}
var activity = (MainActivity)Xamarin.Forms.Forms.Context;
var afm = (AutofillManager)activity.GetSystemService(Java.Lang.Class.FromType(typeof(AutofillManager)));
return afm.IsEnabled;
}
}
}

View file

@ -407,5 +407,13 @@ namespace Bit.Android.Services
ActivityCompat.RequestPermissions(CrossCurrentActivity.Current.Activity, new string[] { permission },
Constants.SelectFilePermissionRequestCode);
}
public void OpenAutofillSettings()
{
var activity = (MainActivity)Forms.Context;
var intent = new Intent(Settings.ActionRequestSetAutofillService);
intent.SetData(global::Android.Net.Uri.Parse("package:com.x8bit.bitwarden"));
activity.StartActivity(intent);
}
}
}

View file

@ -1,6 +1,7 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Views.Autofill;
using Bit.App.Abstractions;
namespace Bit.Android.Services
@ -44,5 +45,18 @@ namespace Bit.Android.Services
}
public bool NfcEnabled => Utilities.NfcEnabled();
public bool HasCamera => Xamarin.Forms.Forms.Context.PackageManager.HasSystemFeature(PackageManager.FeatureCamera);
public bool AutofillServiceSupported => AutofillSupported();
private bool AutofillSupported()
{
if(Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return false;
}
var activity = (MainActivity)Xamarin.Forms.Forms.Context;
var afm = (AutofillManager)activity.GetSystemService(Java.Lang.Class.FromType(typeof(AutofillManager)));
return afm.IsAutofillSupported;
}
}
}

View file

@ -4,6 +4,7 @@
{
string Build { get; }
string Version { get; }
bool AutofillAccessibilityServiceEnabled { get; }
bool AutofillServiceEnabled { get; }
}
}

View file

@ -16,6 +16,7 @@ namespace Bit.App.Abstractions
void RateApp();
void DismissKeyboard();
void OpenAccessibilitySettings();
void OpenAutofillSettings();
void LaunchApp(string appName);
}
}

View file

@ -7,5 +7,6 @@
float Scale { get; }
bool NfcEnabled { get; }
bool HasCamera { get; }
bool AutofillServiceSupported { get; }
}
}

View file

@ -182,6 +182,7 @@
<Compile Include="Pages\Settings\SettingsEditFolderPage.cs" />
<Compile Include="Pages\Lock\LockFingerprintPage.cs" />
<Compile Include="Pages\Settings\SettingsAboutPage.cs" />
<Compile Include="Pages\Tools\ToolsAutofillServicePage2.cs" />
<Compile Include="Pages\Tools\ToolsAutofillServicePage.cs" />
<Compile Include="Pages\Tools\ToolsExtensionPage.cs" />
<Compile Include="Pages\Tools\ToolsPasswordGeneratorSettingsPage.cs" />

View file

@ -200,7 +200,7 @@ namespace Bit.App.Pages
private void UpdateEnabled()
{
ScrollView.Content = _appInfoService.AutofillServiceEnabled ? EnabledStackLayout : DisabledStackLayout;
ScrollView.Content = _appInfoService.AutofillAccessibilityServiceEnabled ? EnabledStackLayout : DisabledStackLayout;
}
private Label BuildServiceLabel()

View file

@ -0,0 +1,153 @@
using System;
using Bit.App.Controls;
using Xamarin.Forms;
using XLabs.Ioc;
using Bit.App.Abstractions;
using Bit.App.Resources;
namespace Bit.App.Pages
{
public class ToolsAutofillServicePage2 : ExtendedContentPage
{
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly IAppInfoService _appInfoService;
private readonly IDeviceActionService _deviceActionService;
private bool _pageDisappeared = false;
public ToolsAutofillServicePage2()
{
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_appInfoService = Resolver.Resolve<IAppInfoService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
Init();
}
public StackLayout EnabledStackLayout { get; set; }
public StackLayout DisabledStackLayout { get; set; }
public ScrollView ScrollView { get; set; }
public void Init()
{
var enabledFs = new FormattedString();
var statusSpan = new Span { Text = string.Concat(AppResources.Status, " ") };
enabledFs.Spans.Add(statusSpan);
enabledFs.Spans.Add(new Span
{
Text = AppResources.Enabled,
ForegroundColor = Color.Green,
FontAttributes = FontAttributes.Bold,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
});
var statusEnabledLabel = new Label
{
FormattedText = enabledFs,
HorizontalTextAlignment = TextAlignment.Center,
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
TextColor = Color.Black
};
var disabledFs = new FormattedString();
disabledFs.Spans.Add(statusSpan);
disabledFs.Spans.Add(new Span
{
Text = AppResources.Disabled,
ForegroundColor = Color.FromHex("c62929"),
FontAttributes = FontAttributes.Bold,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
});
var statusDisabledLabel = new Label
{
FormattedText = disabledFs,
HorizontalTextAlignment = TextAlignment.Center,
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
TextColor = Color.Black
};
DisabledStackLayout = new StackLayout
{
Children = { BuildServiceLabel(), statusDisabledLabel, BuildGoButton() },
Orientation = StackOrientation.Vertical,
Spacing = 20,
Padding = new Thickness(20, 30),
VerticalOptions = LayoutOptions.FillAndExpand
};
EnabledStackLayout = new StackLayout
{
Children = { BuildServiceLabel(), statusEnabledLabel },
Orientation = StackOrientation.Vertical,
Spacing = 20,
Padding = new Thickness(20, 30),
VerticalOptions = LayoutOptions.FillAndExpand
};
ScrollView = new ScrollView { Content = DisabledStackLayout };
UpdateEnabled();
Device.StartTimer(new TimeSpan(0, 0, 3), () =>
{
if(_pageDisappeared)
{
return false;
}
UpdateEnabled();
return true;
});
Title = AppResources.AutofillService;
Content = ScrollView;
}
protected override void OnAppearing()
{
_pageDisappeared = false;
base.OnAppearing();
}
protected override void OnDisappearing()
{
_pageDisappeared = true;
base.OnDisappearing();
}
private void UpdateEnabled()
{
ScrollView.Content = _appInfoService.AutofillServiceEnabled ? EnabledStackLayout : DisabledStackLayout;
}
private Label BuildServiceLabel()
{
return new Label
{
Text = AppResources.AutofillDescription,
VerticalOptions = LayoutOptions.Start,
HorizontalTextAlignment = TextAlignment.Center,
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
};
}
private ExtendedButton BuildGoButton()
{
return new ExtendedButton
{
Text = AppResources.BitwardenAutofillServiceOpenSettings,
Command = new Command(() =>
{
_googleAnalyticsService.TrackAppEvent("OpenAutofillSettings");
_deviceActionService.OpenAutofillSettings();
}),
VerticalOptions = LayoutOptions.End,
HorizontalOptions = LayoutOptions.Fill,
Style = (Style)Application.Current.Resources["btn-primary"],
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Button))
};
}
}
}

View file

@ -15,11 +15,13 @@ namespace Bit.App.Pages
{
private readonly IUserDialogs _userDialogs;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly IDeviceInfoService _deviceInfoService;
public ToolsPage()
{
_userDialogs = Resolver.Resolve<IUserDialogs>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
Init();
}
@ -116,7 +118,14 @@ namespace Bit.App.Pages
private void AutofillCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage()));
if(_deviceInfoService.AutofillServiceSupported)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage2()));
}
else
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage()));
}
}
private void ExtensionCell_Tapped(object sender, EventArgs e)

View file

@ -242,7 +242,7 @@ namespace Bit.App.Pages
DisplayAlert(AppResources.BitwardenAppExtension, AppResources.BitwardenAppExtensionAlert,
AppResources.Ok);
}
else if(Device.RuntimePlatform == Device.Android && !_appInfoService.AutofillServiceEnabled)
else if(Device.RuntimePlatform == Device.Android && !_appInfoService.AutofillAccessibilityServiceEnabled)
{
DisplayAlert(AppResources.BitwardenAutofillService, AppResources.BitwardenAutofillServiceAlert,
AppResources.Ok);

View file

@ -16,6 +16,7 @@ namespace Bit.UWP.Services
}
}
public bool AutofillAccessibilityServiceEnabled => false;
public bool AutofillServiceEnabled => false;
}
}

View file

@ -55,6 +55,11 @@ namespace Bit.UWP.Services
}
}
public void OpenAutofillSettings()
{
throw new NotImplementedException();
}
public Task SelectFileAsync()
{
var picker = new Windows.Storage.Pickers.FileOpenPicker

View file

@ -39,5 +39,7 @@ namespace Bit.UWP.Services
return cameraList?.Any() ?? false;
}
}
public bool AutofillServiceSupported => false;
}
}

View file

@ -24,5 +24,6 @@ namespace Bit.iOS.Core.Services
public float Scale => (float)UIScreen.MainScreen.Scale;
public bool NfcEnabled => false;
public bool HasCamera => true;
public bool AutofillServiceSupported => false;
}
}

View file

@ -8,6 +8,7 @@ namespace Bit.iOS.Services
{
public string Build => NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString();
public string Version => NSBundle.MainBundle.InfoDictionary["CFBundleShortVersionString"].ToString();
public bool AutofillAccessibilityServiceEnabled => false;
public bool AutofillServiceEnabled => false;
}
}

View file

@ -250,5 +250,10 @@ namespace Bit.iOS.Services
{
throw new NotImplementedException();
}
public void OpenAutofillSettings()
{
throw new NotImplementedException();
}
}
}