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);
        }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
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);
        }
        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();
        }
        private void AdjustOverlayForScroll()
        {
            if (_overlayView == null || _anchorNode == null)
            {
                CancelOverlayPrompt();
                return;
            }

            var root = RootInActiveWindow;
            IEnumerable <AccessibilityWindowInfo> windows = null;

            if (Build.VERSION.SdkInt > BuildVersionCodes.Kitkat)
            {
                windows = Windows;
            }

            var anchorPosition = AccessibilityHelpers.GetOverlayAnchorPosition(_anchorNode, root, windows);

            if (anchorPosition == null)
            {
                CancelOverlayPrompt();
                return;
            }
            else if (anchorPosition.X == -1 && anchorPosition.Y == -1)
            {
                if (_overlayView.Visibility != ViewStates.Gone)
                {
                    _overlayView.Visibility = ViewStates.Gone;
                }
                return;
            }
            else if (anchorPosition.X == _lastAnchorX && anchorPosition.Y == _lastAnchorY)
            {
                if (_overlayView.Visibility != ViewStates.Visible)
                {
                    _overlayView.Visibility = ViewStates.Visible;
                }
                return;
            }

            var layoutParams = AccessibilityHelpers.GetOverlayLayoutParams();

            layoutParams.X = anchorPosition.X;
            layoutParams.Y = anchorPosition.Y;

            _lastAnchorX = anchorPosition.X;
            _lastAnchorY = anchorPosition.Y;

            _windowManager.UpdateViewLayout(_overlayView, layoutParams);

            if (_overlayView.Visibility != ViewStates.Visible)
            {
                _overlayView.Visibility = ViewStates.Visible;
            }

            System.Diagnostics.Debug.WriteLine(">>> Accessibility Overlay View Updated to X:{0} Y:{1}",
                                               layoutParams.X, layoutParams.Y);
        }
        private void OnAutofillTileClick()
        {
            CancelOverlayPrompt();

            var root = RootInActiveWindow;

            if (root != null && root.PackageName != BitwardenPackage &&
                root.PackageName != AccessibilityHelpers.SystemUiPackage &&
                !SkipPackage(root.PackageName))
            {
                var uri = AccessibilityHelpers.GetUri(root);
                if (!string.IsNullOrWhiteSpace(uri))
                {
                    var intent = new Intent(this, typeof(AccessibilityActivity));
                    intent.PutExtra("uri", uri);
                    intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
                    StartActivity(intent);
                    return;
                }
            }

            Toast.MakeText(this, AppResources.AutofillTileUriNotFound, ToastLength.Long).Show();
        }
Пример #8
0
        public override void OnAccessibilityEvent(AccessibilityEvent e)
        {
            try
            {
                var powerManager = GetSystemService(PowerService) as PowerManager;
                if (Build.VERSION.SdkInt > BuildVersionCodes.KitkatWatch && !powerManager.IsInteractive)
                {
                    return;
                }
                else if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop && !powerManager.IsScreenOn)
                {
                    return;
                }

                if (SkipPackage(e?.PackageName))
                {
                    if (e?.PackageName != "com.android.systemui")
                    {
                        CancelOverlayPrompt();
                    }
                    return;
                }

                // AccessibilityHelpers.PrintTestData(RootInActiveWindow, e);

                AccessibilityNodeInfo root = null;

                switch (e.EventType)
                {
                case EventTypes.ViewFocused:
                case EventTypes.ViewClicked:
                    if (e.Source == null || e.PackageName == BitwardenPackage)
                    {
                        CancelOverlayPrompt();
                        break;
                    }

                    root = RootInActiveWindow;
                    if (root == null || root.PackageName != e.PackageName)
                    {
                        break;
                    }

                    if (!(e.Source?.Password ?? false) && !AccessibilityHelpers.IsUsernameEditText(root, e))
                    {
                        CancelOverlayPrompt();
                        break;
                    }
                    if (ScanAndAutofill(root, e))
                    {
                        CancelOverlayPrompt();
                    }
                    else
                    {
                        OverlayPromptToAutofill(root, e);
                    }
                    break;

                case EventTypes.WindowContentChanged:
                case EventTypes.WindowStateChanged:
                    if (AccessibilityHelpers.LastCredentials == null)
                    {
                        break;
                    }
                    if (e.PackageName == BitwardenPackage)
                    {
                        CancelOverlayPrompt();
                        break;
                    }

                    root = RootInActiveWindow;
                    if (root == null || root.PackageName != e.PackageName)
                    {
                        break;
                    }
                    if (ScanAndAutofill(root, e))
                    {
                        CancelOverlayPrompt();
                    }
                    break;

                default:
                    break;
                }
            }
            // Suppress exceptions so that service doesn't crash.
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", ex.GetType(), ex.StackTrace);
            }
        }
Пример #9
0
        public override void OnAccessibilityEvent(AccessibilityEvent e)
        {
            try
            {
                var powerManager = GetSystemService(PowerService) as PowerManager;
                if (Build.VERSION.SdkInt > BuildVersionCodes.KitkatWatch && !powerManager.IsInteractive)
                {
                    return;
                }
                else if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop && !powerManager.IsScreenOn)
                {
                    return;
                }

                if (SkipPackage(e?.PackageName))
                {
                    CancelOverlayPrompt();
                    return;
                }

                var root = RootInActiveWindow;
                if (root == null || root.PackageName != e.PackageName)
                {
                    return;
                }

                // AccessibilityHelpers.PrintTestData(root, e);

                switch (e.EventType)
                {
                case EventTypes.ViewFocused:
                case EventTypes.ViewClicked:
                case EventTypes.ViewScrolled:
                    var isKnownBroswer = AccessibilityHelpers.SupportedBrowsers.ContainsKey(root.PackageName);
                    if (e.EventType == EventTypes.ViewClicked && isKnownBroswer)
                    {
                        break;
                    }
                    if (e.Source == null || e.PackageName == BitwardenPackage)
                    {
                        CancelOverlayPrompt();
                        break;
                    }
                    if (e.EventType == EventTypes.ViewScrolled)
                    {
                        AdjustOverlayForScroll(root, e);
                        break;
                    }
                    else
                    {
                        var isUsernameEditText1 = AccessibilityHelpers.IsUsernameEditText(root, e);
                        var isPasswordEditText1 = e.Source?.Password ?? false;
                        if (!isUsernameEditText1 && !isPasswordEditText1)
                        {
                            CancelOverlayPrompt();
                            break;
                        }
                        if (ScanAndAutofill(root, e))
                        {
                            CancelOverlayPrompt();
                        }
                        else
                        {
                            OverlayPromptToAutofill(root, e);
                        }
                    }
                    break;

                case EventTypes.WindowContentChanged:
                case EventTypes.WindowStateChanged:
                    var isUsernameEditText2 = AccessibilityHelpers.IsUsernameEditText(root, e);
                    var isPasswordEditText2 = e.Source?.Password ?? false;
                    if (e.Source == null || isUsernameEditText2 || isPasswordEditText2)
                    {
                        break;
                    }
                    else if (AccessibilityHelpers.LastCredentials == null)
                    {
                        if (string.IsNullOrWhiteSpace(_lastNotificationUri))
                        {
                            CancelOverlayPrompt();
                            break;
                        }
                        var uri = AccessibilityHelpers.GetUri(root);
                        if (uri != null && uri != _lastNotificationUri)
                        {
                            CancelOverlayPrompt();
                        }
                        else if (uri != null && uri.StartsWith(Constants.AndroidAppProtocol))
                        {
                            CancelOverlayPrompt();
                        }
                        break;
                    }

                    if (e.PackageName == BitwardenPackage)
                    {
                        CancelOverlayPrompt();
                        break;
                    }

                    if (ScanAndAutofill(root, e))
                    {
                        CancelOverlayPrompt();
                    }
                    break;

                default:
                    break;
                }

                root.Dispose();
                e.Dispose();
            }
            // Suppress exceptions so that service doesn't crash.
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(">>> Exception: " + ex.StackTrace);
            }
        }
        private void OverlayPromptToAutofill(AccessibilityNodeInfo root, AccessibilityEvent e)
        {
            if (Java.Lang.JavaSystem.CurrentTimeMillis() - _lastAutoFillTime < 1000 ||
                AccessibilityHelpers.IsAutofillServicePromptVisible(Windows))
            {
                return;
            }

            if (!AccessibilityHelpers.OverlayPermitted())
            {
                if (!AccessibilityHelpers.IsAutofillTileAdded)
                {
                    // The user has the option of only using the autofill tile and leaving the overlay permission
                    // disabled, so only show this toast if they're using accessibility without overlay permission and
                    // have _not_ added the autofill tile
                    System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted");
                    Toast.MakeText(this, AppResources.AccessibilityOverlayPermissionAlert, ToastLength.Long).Show();
                }
                return;
            }

            if (_overlayView != null || _anchorNode != null || _overlayAnchorObserverRunning)
            {
                CancelOverlayPrompt();
            }

            var uri      = AccessibilityHelpers.GetUri(root);
            var fillable = !string.IsNullOrWhiteSpace(uri);

            if (fillable)
            {
                if (_blacklistedUris != null && _blacklistedUris.Any())
                {
                    if (Uri.TryCreate(uri, UriKind.Absolute, out var parsedUri) && parsedUri.Scheme.StartsWith("http"))
                    {
                        fillable = !_blacklistedUris.Contains(
                            string.Format("{0}://{1}", parsedUri.Scheme, parsedUri.Host));
                    }
                    else
                    {
                        fillable = !_blacklistedUris.Contains(uri);
                    }
                }
            }
            if (!fillable)
            {
                return;
            }

            var intent = new Intent(this, typeof(AccessibilityActivity));

            intent.PutExtra("uri", uri);
            intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);

            _overlayView = AccessibilityHelpers.GetOverlayView(this);
            _overlayView.Measure(View.MeasureSpec.MakeMeasureSpec(0, 0),
                                 View.MeasureSpec.MakeMeasureSpec(0, 0));
            _overlayViewHeight  = _overlayView.MeasuredHeight;
            _overlayView.Click += (sender, eventArgs) =>
            {
                CancelOverlayPrompt();
                StartActivity(intent);
            };

            var layoutParams   = AccessibilityHelpers.GetOverlayLayoutParams();
            var anchorPosition = AccessibilityHelpers.GetOverlayAnchorPosition(this, e.Source,
                                                                               _overlayViewHeight, _isOverlayAboveAnchor);

            layoutParams.X = anchorPosition.X;
            layoutParams.Y = anchorPosition.Y;

            if (_windowManager == null)
            {
                _windowManager = GetSystemService(WindowService).JavaCast <IWindowManager>();
            }

            _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();
        }
Пример #11
0
        public override void OnAccessibilityEvent(AccessibilityEvent e)
        {
            try
            {
                var powerManager = GetSystemService(PowerService) as PowerManager;
                if (Build.VERSION.SdkInt > BuildVersionCodes.KitkatWatch && !powerManager.IsInteractive)
                {
                    return;
                }
                else if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop && !powerManager.IsScreenOn)
                {
                    return;
                }

                if (SkipPackage(e?.PackageName))
                {
                    return;
                }

                var root = RootInActiveWindow;
                if (root == null || root.PackageName != e.PackageName)
                {
                    return;
                }

                // AccessibilityHelpers.PrintTestData(root, e);
                LoadServices();
                var settingsTask = LoadSettingsAsync();

                var notificationManager = GetSystemService(NotificationService) as NotificationManager;
                var cancelNotification  = true;

                switch (e.EventType)
                {
                case EventTypes.ViewFocused:
                    if (e.Source == null || !e.Source.Password || !_settingAutofillPasswordField)
                    {
                        break;
                    }
                    if (e.PackageName == BitwardenPackage)
                    {
                        CancelNotification(notificationManager);
                        break;
                    }
                    if (ScanAndAutofill(root, e, notificationManager, cancelNotification))
                    {
                        CancelNotification(notificationManager);
                    }
                    break;

                case EventTypes.WindowContentChanged:
                case EventTypes.WindowStateChanged:
                    if (_settingAutofillPasswordField && e.Source.Password)
                    {
                        break;
                    }
                    else if (_settingAutofillPasswordField && AccessibilityHelpers.LastCredentials == null)
                    {
                        if (string.IsNullOrWhiteSpace(_lastNotificationUri))
                        {
                            CancelNotification(notificationManager);
                            break;
                        }
                        var uri = AccessibilityHelpers.GetUri(root);
                        if (uri != _lastNotificationUri)
                        {
                            CancelNotification(notificationManager);
                        }
                        else if (uri.StartsWith(Constants.AndroidAppProtocol))
                        {
                            CancelNotification(notificationManager, 30000);
                        }
                        break;
                    }

                    if (e.PackageName == BitwardenPackage)
                    {
                        CancelNotification(notificationManager);
                        break;
                    }

                    if (_settingAutofillPersistNotification)
                    {
                        var uri = AccessibilityHelpers.GetUri(root);
                        if (uri != null && !uri.Contains(BitwardenWebsite))
                        {
                            var needToFill = AccessibilityHelpers.NeedToAutofill(
                                AccessibilityHelpers.LastCredentials, uri);
                            if (needToFill)
                            {
                                var passwordNodes = AccessibilityHelpers.GetWindowNodes(root, e,
                                                                                        n => n.Password, false);
                                needToFill = passwordNodes.Any();
                                if (needToFill)
                                {
                                    AccessibilityHelpers.GetNodesAndFill(root, e, passwordNodes);
                                }
                                passwordNodes.Dispose();
                            }
                            if (!needToFill)
                            {
                                NotifyToAutofill(uri, notificationManager);
                                cancelNotification = false;
                            }
                        }
                        AccessibilityHelpers.LastCredentials = null;
                    }
                    else
                    {
                        cancelNotification = ScanAndAutofill(root, e, notificationManager, cancelNotification);
                    }

                    if (cancelNotification)
                    {
                        CancelNotification(notificationManager);
                    }
                    break;

                default:
                    break;
                }

                notificationManager?.Dispose();
                root.Dispose();
                e.Dispose();
            }
            // Suppress exceptions so that service doesn't crash.
            catch { }
        }
Пример #12
0
        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;
            }

            var uri = AccessibilityHelpers.GetUri(root);

            if (string.IsNullOrWhiteSpace(uri))
            {
                return;
            }

            WindowManagerTypes windowManagerType;

            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                windowManagerType = WindowManagerTypes.ApplicationOverlay;
            }
            else
            {
                windowManagerType = WindowManagerTypes.Phone;
            }

            var layoutParams = new WindowManagerLayoutParams(
                ViewGroup.LayoutParams.WrapContent,
                ViewGroup.LayoutParams.WrapContent,
                windowManagerType,
                WindowManagerFlags.NotFocusable | WindowManagerFlags.NotTouchModal,
                Format.Transparent);

            var anchorPosition = AccessibilityHelpers.GetOverlayAnchorPosition(root, e);

            layoutParams.Gravity = GravityFlags.Bottom | GravityFlags.Left;
            layoutParams.X       = anchorPosition.X;
            layoutParams.Y       = anchorPosition.Y;

            var intent = new Intent(this, typeof(AccessibilityActivity));

            intent.PutExtra("uri", uri);
            intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);

            if (_windowManager == null)
            {
                _windowManager = GetSystemService(WindowService).JavaCast <IWindowManager>();
            }

            var updateView = false;

            if (_overlayView != null)
            {
                updateView = true;
            }

            _overlayView        = AccessibilityHelpers.GetOverlayView(this);
            _overlayView.Click += (sender, eventArgs) =>
            {
                CancelOverlayPrompt();
                StartActivity(intent);
            };

            _lastNotificationUri = uri;

            if (updateView)
            {
                _windowManager.UpdateViewLayout(_overlayView, layoutParams);
            }
            else
            {
                _windowManager.AddView(_overlayView, layoutParams);
            }

            System.Diagnostics.Debug.WriteLine(">>> Accessibility Overlay View {0} X:{1} Y:{2}",
                                               updateView ? "Updated to" : "Added at", layoutParams.X, layoutParams.Y);
        }