private void OverlayPromptToAutofill(AccessibilityNodeInfo root, AccessibilityEvent e) { if (!AccessibilityHelpers.OverlayPermitted()) { System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted"); Toast.MakeText(this, AppResources.AccessibilityOverlayPermissionAlert, ToastLength.Long).Show(); return; } if (_overlayView != null || _anchorNode != null || _overlayAnchorObserverRunning) { CancelOverlayPrompt(); } if (Java.Lang.JavaSystem.CurrentTimeMillis() - _lastAutoFillTime < 1000) { return; } var uri = AccessibilityHelpers.GetUri(root); if (string.IsNullOrWhiteSpace(uri)) { return; } var layoutParams = AccessibilityHelpers.GetOverlayLayoutParams(); var anchorPosition = AccessibilityHelpers.GetOverlayAnchorPosition(root, e.Source); layoutParams.X = anchorPosition.X; layoutParams.Y = anchorPosition.Y; if (_windowManager == null) { _windowManager = GetSystemService(WindowService).JavaCast <IWindowManager>(); } var intent = new Intent(this, typeof(AccessibilityActivity)); intent.PutExtra("uri", uri); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); _overlayView = AccessibilityHelpers.GetOverlayView(this); _overlayView.Click += (sender, eventArgs) => { CancelOverlayPrompt(); StartActivity(intent); }; _anchorNode = e.Source; _lastAnchorX = anchorPosition.X; _lastAnchorY = anchorPosition.Y; _windowManager.AddView(_overlayView, layoutParams); System.Diagnostics.Debug.WriteLine(">>> Accessibility Overlay View Added at X:{0} Y:{1}", layoutParams.X, layoutParams.Y); StartOverlayAnchorObserver(); }
public override void OnAccessibilityEvent(AccessibilityEvent e) { Log.Debug(TAG, "onAccessibilityEvent"); AccessibilityNodeInfo source = e.Source; if (e.EventType == EventTypes.WindowStateChanged && !e.ClassName.Contains("AlertDialog")) { return; } if (e.EventType == EventTypes.WindowContentChanged && (source == null || !source.ClassName.Equals("Android.Widget.TextView"))) { return; } if (e.EventType == EventTypes.WindowContentChanged && System.String.IsNullOrEmpty(source.Text)) { return; } ICharSequence eventText; if (e.EventType == EventTypes.WindowStateChanged) { eventText = (ICharSequence)e.Text; } else { eventText = (ICharSequence)Collections.SingletonList(source.Text); } string text = ProcessUSSDText(eventText); }
private static void FillDataInTextField(AccessibilityNodeInfo edit, string newValue) { Bundle b = new Bundle(); b.PutString(AccessibilityNodeInfo.ActionArgumentSetTextCharsequence, newValue); edit.PerformAction(global::Android.Views.Accessibility.Action.SetText, b); }
private NodeList GetWindowNodes(AccessibilityNodeInfo n, AccessibilityEvent e, Func <AccessibilityNodeInfo, bool> condition, bool disposeIfUnused, NodeList nodes = null) { if (nodes == null) { nodes = new NodeList(); } if (n != null) { var dispose = disposeIfUnused; if (n.WindowId == e.WindowId && !(n.ViewIdResourceName?.StartsWith(SystemUiPackage) ?? false) && condition(n)) { dispose = false; nodes.Add(n); } for (var i = 0; i < n.ChildCount; i++) { GetWindowNodes(n.GetChild(i), e, condition, true, nodes); } if (dispose) { n.Dispose(); } } return(nodes); }
public static Point GetOverlayAnchorPosition(AccessibilityNodeInfo root, AccessibilityNodeInfo anchorView, int rootRectHeight = 0) { if (rootRectHeight == 0) { rootRectHeight = GetNodeHeight(root); } var anchorViewRect = new Rect(); anchorView.GetBoundsInScreen(anchorViewRect); var anchorViewRectLeft = anchorViewRect.Left; var anchorViewRectTop = anchorViewRect.Top; anchorViewRect.Dispose(); var calculatedTop = rootRectHeight - anchorViewRectTop; if ((int)Build.VERSION.SdkInt >= 24) { calculatedTop -= GetNavigationBarHeight(); } return(new Point(anchorViewRectLeft, calculatedTop)); }
public bool ScanAndAutofill(AccessibilityNodeInfo root, AccessibilityEvent e) { var filled = false; var uri = AccessibilityHelpers.GetUri(root); if (uri != null && !uri.Contains(BitwardenWebsite) && AccessibilityHelpers.NeedToAutofill(AccessibilityHelpers.LastCredentials, uri)) { var allEditTexts = AccessibilityHelpers.GetWindowNodes(root, e, n => AccessibilityHelpers.EditText(n), false); var usernameEditText = AccessibilityHelpers.GetUsernameEditText(uri, allEditTexts); var passwordNodes = AccessibilityHelpers.GetWindowNodes(root, e, n => n.Password, false); if (usernameEditText != null || passwordNodes.Count > 0) { AccessibilityHelpers.FillCredentials(usernameEditText, passwordNodes); filled = true; _lastAutoFillTime = Java.Lang.JavaSystem.CurrentTimeMillis(); AccessibilityHelpers.LastCredentials = null; } allEditTexts.Dispose(); passwordNodes.Dispose(); } if (AccessibilityHelpers.LastCredentials != null) { Task.Run(async() => { await Task.Delay(1000); AccessibilityHelpers.LastCredentials = null; }); } return(filled); }
internal override void OnInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { if (!AutomationConfiguration.IsAccessibilityEnabled) { return; } var isAccessible = AutomationProperties.GetAccessibilityView(Owner) != AccessibilityView.Raw; if (isAccessible) { // TODO: Set View.Focusable and View.FocusableInTouchMode to true to ensure SendAccessibilityEvent gets called? info.Focusable = isAccessible; info.ContentDescription = GetName(); info.Password = IsPassword(); info.Enabled = IsEnabled(); // TODO: Use GetAutomationControlType() and GetPattern() instead info.Clickable = GetClickable(); info.Checked = GetChecked(); info.Checkable = GetCheckable(); info.Editable = GetEditable(); info.InputType = GetInputType(); info.MultiLine = GetMultiline(); info.Selected = GetSelected(); info.MaxTextLength = GetMaxTextLength(); info.Scrollable = GetScrollable(); } }
public bool ScanAndAutofill(AccessibilityNodeInfo root, AccessibilityEvent e) { var filled = false; var passwordNodes = AccessibilityHelpers.GetWindowNodes(root, e, n => n.Password, false); if (passwordNodes.Count > 0) { var uri = AccessibilityHelpers.GetUri(root); if (uri != null && !uri.Contains(BitwardenWebsite)) { if (AccessibilityHelpers.NeedToAutofill(AccessibilityHelpers.LastCredentials, uri)) { AccessibilityHelpers.GetNodesAndFill(root, e, passwordNodes); filled = true; _lastAutoFillTime = Java.Lang.JavaSystem.CurrentTimeMillis(); } } AccessibilityHelpers.LastCredentials = null; } else if (AccessibilityHelpers.LastCredentials != null) { Task.Run(async() => { await Task.Delay(1000); AccessibilityHelpers.LastCredentials = null; }); } passwordNodes.Dispose(); return(filled); }
protected string GetAllText(AccessibilityNodeInfo node) { if (node == null) { return("{ }"); } StringBuilder log = new StringBuilder("{"); log.Append($"\"id\" : \"{node.ViewIdResourceName}\", \"text\" : \"{node.Text}\", \"children\" : ["); for (int i = 0; i < node.ChildCount - 1; ++i) { string child = GetAllText(node.GetChild(i)); log.Append(child).Append(","); } if (node.ChildCount != 0) { string child = GetAllText(node.GetChild(node.ChildCount - 1)); log.Append(child); } return(log.Append("] }").ToString()); }
private void AdjustOverlayForScroll(AccessibilityNodeInfo root, AccessibilityEvent e) { if (_overlayView == null || _anchorViewHash <= 0) { return; } var anchorPosition = AccessibilityHelpers.GetOverlayAnchorPosition(_anchorViewHash, root, e); if (anchorPosition == null) { return; } if (anchorPosition.X == _lastAnchorX && anchorPosition.Y == _lastAnchorY) { return; } var layoutParams = AccessibilityHelpers.GetOverlayLayoutParams(); layoutParams.X = anchorPosition.X; layoutParams.Y = anchorPosition.Y; _windowManager.UpdateViewLayout(_overlayView, layoutParams); _lastAnchorX = anchorPosition.X; _lastAnchorY = anchorPosition.Y; System.Diagnostics.Debug.WriteLine(">>> Accessibility Overlay View Updated to X:{0} Y:{1}", layoutParams.X, layoutParams.Y); }
private static string ExtractUri(string uri, AccessibilityNodeInfo addressNode, Browser browser) { if (addressNode?.Text == null) { return(uri); } if (addressNode.Text == null) { return(uri); } uri = browser.GetUriFunction(addressNode.Text)?.Trim(); if (uri != null && uri.Contains(".")) { var hasHttpProtocol = uri.StartsWith("http://") || uri.StartsWith("https://"); if (!hasHttpProtocol && uri.Contains(".")) { if (Uri.TryCreate("http://" + uri, UriKind.Absolute, out var uri2)) { return(string.Concat("http://", uri)); } } if (Uri.TryCreate(uri, UriKind.Absolute, out var uri3)) { return(uri); } } return(uri); }
private string ExtractUri(string uri, AccessibilityNodeInfo addressNode, Browser browser) { if (addressNode?.Text != null) { uri = browser.GetUriFunction(addressNode.Text).Trim(); if (uri != null && uri.Contains(".")) { if (!uri.Contains("://") && !uri.Contains(" ")) { uri = string.Concat("http://", uri); } else if (Build.VERSION.SdkInt <= BuildVersionCodes.KitkatWatch) { var parts = uri.Split(new string[] { ". " }, StringSplitOptions.None); if (parts.Length > 1) { var urlPart = parts.FirstOrDefault(p => p.StartsWith("http")); if (urlPart != null) { uri = urlPart.Trim(); } } } } } return(uri); }
public bool ScanAndAutofill(AccessibilityNodeInfo root, AccessibilityEvent e, NotificationManager notificationManager, bool cancelNotification) { var passwordNodes = GetWindowNodes(root, e, n => n.Password, false); if (passwordNodes.Count > 0) { var uri = GetUri(root); if (uri != null && !uri.Contains(BitwardenWebsite)) { if (NeedToAutofill(AutofillActivity.LastCredentials, uri)) { var allEditTexts = GetWindowNodes(root, e, n => EditText(n), false); var usernameEditText = allEditTexts.TakeWhile(n => !n.Password).LastOrDefault(); FillCredentials(usernameEditText, passwordNodes); allEditTexts.Dispose(); usernameEditText.Dispose(); } else { NotifyToAutofill(uri, notificationManager); cancelNotification = false; } } } AutofillActivity.LastCredentials = null; passwordNodes.Dispose(); return(cancelNotification); }
public bool ScanAndAutofill(AccessibilityNodeInfo root, AccessibilityEvent e, NotificationManager notificationManager, bool cancelNotification) { var passwordNodes = AccessibilityHelpers.GetWindowNodes(root, e, n => n.Password, false); if (passwordNodes.Count > 0) { var uri = AccessibilityHelpers.GetUri(root); if (uri != null && !uri.Contains(BitwardenWebsite)) { if (AccessibilityHelpers.NeedToAutofill(AccessibilityHelpers.LastCredentials, uri)) { AccessibilityHelpers.GetNodesAndFill(root, e, passwordNodes); } else { NotifyToAutofill(uri, notificationManager); cancelNotification = false; } } AccessibilityHelpers.LastCredentials = null; } else if (AccessibilityHelpers.LastCredentials != null) { Task.Run(async() => { await Task.Delay(1000); AccessibilityHelpers.LastCredentials = null; }); } passwordNodes.Dispose(); return(cancelNotification); }
public static string GetUri(AccessibilityNodeInfo root) { var uri = string.Concat(Constants.AndroidAppProtocol, root.PackageName); if (SupportedBrowsers.ContainsKey(root.PackageName)) { var browser = SupportedBrowsers[root.PackageName]; AccessibilityNodeInfo addressNode = null; foreach (var uriViewId in browser.UriViewId.Split(",")) { addressNode = root.FindAccessibilityNodeInfosByViewId( $"{root.PackageName}:id/{uriViewId}").FirstOrDefault(); if (addressNode != null) { break; } } if (addressNode != null) { uri = ExtractUri(uri, addressNode, browser); addressNode.Recycle(); } else { // Return null to prevent overwriting notification pendingIntent uri with browser packageName // (we login to pages, not browsers) return(null); } } return(uri); }
private void CancelOverlayPrompt() { _overlayAnchorObserverRunning = false; if (_windowManager != null && _overlayView != null) { try { _windowManager.RemoveViewImmediate(_overlayView); System.Diagnostics.Debug.WriteLine(">>> Accessibility Overlay View Removed"); } catch { } } _overlayView = null; _lastAnchorX = 0; _lastAnchorY = 0; _isOverlayAboveAnchor = false; if (_anchorNode != null) { _anchorNode.Recycle(); _anchorNode = null; } }
public static bool IsSameNode(AccessibilityNodeInfo info1, AccessibilityNodeInfo info2) { if (info1 != null && info2 != null) { return(info1.Equals(info2) || info1.GetHashCode() == info2.GetHashCode()); } return(false); }
public static bool IsSameNode(AccessibilityNodeInfo node1, AccessibilityNodeInfo node2) { if (node1 != null && node2 != null) { return(node1.Equals(node2) || node1.GetHashCode() == node2.GetHashCode()); } return(false); }
private static bool IsPasswordField(AccessibilityNodeInfo n) { //if (n.Password) Android.Util.Log.Debug(_logTag, "pwdx with " + (n.Text == null ? "null" : n.Text)); var res = n.Password && string.IsNullOrEmpty(n.Text); // if (n.Password) Android.Util.Log.Debug(_logTag, "pwd with " + n.Text + res); return(res); }
private void FillCredentials(AccessibilityNodeInfo usernameNode, IEnumerable <AccessibilityNodeInfo> passwordNodes) { FillEditText(usernameNode, AutofillActivity.LastCredentials?.Username); foreach (var n in passwordNodes) { FillEditText(n, AutofillActivity.LastCredentials?.Password); } }
protected AccessibilityNodeInfo GetRoot(AccessibilityNodeInfo node) { if (node.Parent == null) { return(node); } return(GetRoot(node.Parent)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @TargetApi(android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info) public void OnInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { base.OnInitializeAccessibilityNodeInfo(info); if (Build.VERSION.SdkInt >= Build.VERSION_CODES.IceCreamSandwich) { //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: info.ClassName = typeof(SurfaceRenderView).FullName; } }
public static void FillCredentials(AccessibilityNodeInfo usernameNode, IEnumerable <AccessibilityNodeInfo> passwordNodes) { FillEditText(usernameNode, LastCredentials?.Username); foreach (var n in passwordNodes) { FillEditText(n, LastCredentials?.Password); } }
public static int GetNodeHeight(AccessibilityNodeInfo node) { var nodeRect = new Rect(); node.GetBoundsInScreen(nodeRect); var nodeRectHeight = nodeRect.Height(); nodeRect.Dispose(); return(nodeRectHeight); }
private void FillPassword(string url, AccessibilityNodeInfo usernameEdit, IEnumerable <AccessibilityNodeInfo> passwordFields) { FillDataInTextField(usernameEdit, AutofillActivity.LastReceivedCredentials.User); foreach (var pwd in passwordFields) { FillDataInTextField(pwd, AutofillActivity.LastReceivedCredentials.Password); } AutofillActivity.LastReceivedCredentials = null; }
public static void GetNodesAndFill(AccessibilityNodeInfo root, AccessibilityEvent e, IEnumerable <AccessibilityNodeInfo> passwordNodes) { var allEditTexts = GetWindowNodes(root, e, n => EditText(n), false); var usernameEditText = GetUsernameEditTextIfPasswordExists(allEditTexts); FillCredentials(usernameEditText, passwordNodes); allEditTexts.Dispose(); usernameEditText = null; }
public static void PrintTestData(AccessibilityNodeInfo root, AccessibilityEvent e) { var testNodes = GetWindowNodes(root, e, n => n.ViewIdResourceName != null && n.Text != null, false); var testNodesData = testNodes.Select(n => new { id = n.ViewIdResourceName, text = n.Text }); foreach (var node in testNodesData) { System.Diagnostics.Debug.WriteLine("Node: {0} = {1}", node.id, node.text); } }
private static void UrlFromAddressField(ref string url, AccessibilityNodeInfo addressField) { if (addressField != null) { url = addressField.Text; if (!url.Contains("://")) { url = "http://" + url; } } }
public static void FillEditText(AccessibilityNodeInfo editTextNode, string value) { if (editTextNode == null || value == null) { return; } var bundle = new Bundle(); bundle.PutString(AccessibilityNodeInfo.ActionArgumentSetTextCharsequence, value); editTextNode.PerformAction(Android.Views.Accessibility.Action.SetText, bundle); }
private bool HandleMessageBox(AccessibilityNodeInfo root, string clickId) { AccessibilityNodeInfo panel = GetButtonPanel(root); if (panel == null) { return(false); } AccessibilityNodeInfo button = panel.FindAccessibilityNodeInfosByViewId(clickId).FirstOrDefault(); return(Click(button)); }