mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 18:08:26 +03:00
add tools page for autofill service
This commit is contained in:
parent
9bbddd6aeb
commit
783c4d104c
17 changed files with 222 additions and 5 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{
|
||||
string Build { get; }
|
||||
string Version { get; }
|
||||
bool AutofillAccessibilityServiceEnabled { get; }
|
||||
bool AutofillServiceEnabled { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Bit.App.Abstractions
|
|||
void RateApp();
|
||||
void DismissKeyboard();
|
||||
void OpenAccessibilitySettings();
|
||||
void OpenAutofillSettings();
|
||||
void LaunchApp(string appName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,5 +7,6 @@
|
|||
float Scale { get; }
|
||||
bool NfcEnabled { get; }
|
||||
bool HasCamera { get; }
|
||||
bool AutofillServiceSupported { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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()
|
||||
|
|
153
src/App/Pages/Tools/ToolsAutofillServicePage2.cs
Normal file
153
src/App/Pages/Tools/ToolsAutofillServicePage2.cs
Normal 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))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
@ -115,9 +117,16 @@ namespace Bit.App.Pages
|
|||
}
|
||||
|
||||
private void AutofillCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
if(_deviceInfoService.AutofillServiceSupported)
|
||||
{
|
||||
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage2()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage()));
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtensionCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Bit.UWP.Services
|
|||
}
|
||||
}
|
||||
|
||||
public bool AutofillAccessibilityServiceEnabled => false;
|
||||
public bool AutofillServiceEnabled => false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ namespace Bit.UWP.Services
|
|||
}
|
||||
}
|
||||
|
||||
public void OpenAutofillSettings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SelectFileAsync()
|
||||
{
|
||||
var picker = new Windows.Storage.Pickers.FileOpenPicker
|
||||
|
|
|
@ -39,5 +39,7 @@ namespace Bit.UWP.Services
|
|||
return cameraList?.Any() ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutofillServiceSupported => false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,5 +250,10 @@ namespace Bit.iOS.Services
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OpenAutofillSettings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue