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();
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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();
            }
        }
Esempio n. 8
0
        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());
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
 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);
 }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
0
        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;
            }
        }
Esempio n. 17
0
 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);
 }
Esempio n. 19
0
        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);
        }
Esempio n. 20
0
 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));
        }
Esempio n. 22
0
 //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);
        }
Esempio n. 25
0
        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);
            }
        }
Esempio n. 28
0
 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));
        }