mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
* Account Switching (#1720) * Account switching * WIP * wip * wip * updates to send test logic * fixed Send tests * fixes for theme handling on account switching and re-adding existing account * switch fixes * fixes * fixes * cleanup * vault timeout fixes * account list status enhancements * logout fixes and token handling improvements * merge latest (#1727) * remove duplicate dependency * fix for initial login token storage paradox (#1730) * Fix avatar color update toolbar item issue on iOS for account switching (#1735) * Updated account switching menu UI (#1733) * updated account switching menu UI * additional changes * add key suffix to constant * GetFirstLetters method tweaks * Fix crash on account switching when logging out when having more than user at a time (#1740) * single account migration to multi-account on app update (#1741) * Account Switching Tap to dismiss (#1743) * Added tap to dismiss on the Account switching overlay and improved a bit the code * Fix account switching overlay background transparent on the proper place * Fixed transparent background and the shadow on the account switching overlay * Fix iOS top space on Account switching list overlay after modal (#1746) * Fix top space added to Account switching list overlay after closing modal * Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well * Usability: dismiss account list on certain events (#1748) * dismiss account list on certain events * use new FireAndForget method for back button logic * Create and use Account Switching overlay control (#1753) * Added Account switching overlay control and its own ViewModel and refactored accordingly * Fix account switching Accounts list binding update * Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755) * Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756) * Usability improvements for logout on vault timeout (#1781) * accountswitching fixes (#1784) * Fix for invalid PIN lock state when switching accounts (#1792) * fix for pin lock flow * named tuple values and updated async * clear send service cache on account switch (#1796) * Global theme and account removal (#1793) * Global theme and account removal * remove redundant call to hide account list overlay * cleanup and additional tweaks * add try/catch to remove account dialog flow Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
177 lines
5.4 KiB
C#
177 lines
5.4 KiB
C#
using static Android.App.Assist.AssistStructure;
|
|
using Android.App.Assist;
|
|
using System.Collections.Generic;
|
|
using Bit.Core;
|
|
using Android.Content;
|
|
using Bit.Core.Abstractions;
|
|
using System.Threading.Tasks;
|
|
using Android.OS;
|
|
|
|
namespace Bit.Droid.Autofill
|
|
{
|
|
public class Parser
|
|
{
|
|
public static HashSet<string> _excludedPackageIds = new HashSet<string>
|
|
{
|
|
"android"
|
|
};
|
|
private readonly AssistStructure _structure;
|
|
private string _uri;
|
|
private string _packageName;
|
|
private string _website;
|
|
|
|
public Parser(AssistStructure structure, Context applicationContext)
|
|
{
|
|
_structure = structure;
|
|
ApplicationContext = applicationContext;
|
|
}
|
|
|
|
public Context ApplicationContext { get; set; }
|
|
public FieldCollection FieldCollection { get; private set; } = new FieldCollection();
|
|
|
|
public string Uri
|
|
{
|
|
get
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(_uri))
|
|
{
|
|
return _uri;
|
|
}
|
|
var websiteNull = string.IsNullOrWhiteSpace(Website);
|
|
if (websiteNull && string.IsNullOrWhiteSpace(PackageName))
|
|
{
|
|
_uri = null;
|
|
}
|
|
else if (!websiteNull)
|
|
{
|
|
_uri = Website;
|
|
}
|
|
else
|
|
{
|
|
_uri = string.Concat(Constants.AndroidAppProtocol, PackageName);
|
|
}
|
|
return _uri;
|
|
}
|
|
}
|
|
|
|
public string PackageName
|
|
{
|
|
get => _packageName;
|
|
set
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
_packageName = _uri = null;
|
|
}
|
|
_packageName = value;
|
|
}
|
|
}
|
|
|
|
public string Website
|
|
{
|
|
get => _website;
|
|
set
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
_website = _uri = null;
|
|
}
|
|
_website = value;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ShouldAutofillAsync(IStateService stateService)
|
|
{
|
|
var fillable = !string.IsNullOrWhiteSpace(Uri) && !AutofillHelpers.BlacklistedUris.Contains(Uri) &&
|
|
FieldCollection != null && FieldCollection.Fillable;
|
|
if (fillable)
|
|
{
|
|
var blacklistedUris = await stateService.GetAutofillBlacklistedUrisAsync();
|
|
if (blacklistedUris != null && blacklistedUris.Count > 0)
|
|
{
|
|
fillable = !new HashSet<string>(blacklistedUris).Contains(Uri);
|
|
}
|
|
}
|
|
return fillable;
|
|
}
|
|
|
|
public void Parse()
|
|
{
|
|
string titlePackageId = null;
|
|
for (var i = 0; i < _structure.WindowNodeCount; i++)
|
|
{
|
|
var node = _structure.GetWindowNodeAt(i);
|
|
if (i == 0)
|
|
{
|
|
titlePackageId = GetTitlePackageId(node);
|
|
}
|
|
ParseNode(node.RootViewNode);
|
|
}
|
|
if (string.IsNullOrWhiteSpace(PackageName) && string.IsNullOrWhiteSpace(Website))
|
|
{
|
|
PackageName = titlePackageId;
|
|
}
|
|
if (!AutofillHelpers.TrustedBrowsers.Contains(PackageName) &&
|
|
!AutofillHelpers.CompatBrowsers.Contains(PackageName))
|
|
{
|
|
Website = null;
|
|
}
|
|
}
|
|
|
|
private void ParseNode(ViewNode node)
|
|
{
|
|
SetPackageAndDomain(node);
|
|
var hints = node.GetAutofillHints();
|
|
var isEditText = node.ClassName == "android.widget.EditText" || node?.HtmlInfo?.Tag == "input";
|
|
if (isEditText || (hints?.Length ?? 0) > 0)
|
|
{
|
|
FieldCollection.Add(new Field(node));
|
|
}
|
|
else
|
|
{
|
|
FieldCollection.IgnoreAutofillIds.Add(node.AutofillId);
|
|
}
|
|
|
|
for (var i = 0; i < node.ChildCount; i++)
|
|
{
|
|
ParseNode(node.GetChildAt(i));
|
|
}
|
|
}
|
|
|
|
private void SetPackageAndDomain(ViewNode node)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(PackageName) && !string.IsNullOrWhiteSpace(node.IdPackage) &&
|
|
!_excludedPackageIds.Contains(node.IdPackage))
|
|
{
|
|
PackageName = node.IdPackage;
|
|
}
|
|
if (string.IsNullOrWhiteSpace(Website) && !string.IsNullOrWhiteSpace(node.WebDomain))
|
|
{
|
|
var scheme = "http";
|
|
if ((int)Build.VERSION.SdkInt >= 28)
|
|
{
|
|
scheme = node.WebScheme;
|
|
}
|
|
Website = string.Format("{0}://{1}", scheme, node.WebDomain);
|
|
}
|
|
}
|
|
|
|
private string GetTitlePackageId(WindowNode node)
|
|
{
|
|
if (node != null && !string.IsNullOrWhiteSpace(node.Title))
|
|
{
|
|
var slashPosition = node.Title.IndexOf('/');
|
|
if (slashPosition > -1)
|
|
{
|
|
var packageId = node.Title.Substring(0, slashPosition);
|
|
if (packageId.Contains("."))
|
|
{
|
|
return packageId;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|