1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
6 #define UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
7 
8 #include "ui/base/ui_base_export.h"
9 
10 namespace ui {
11 
12 // This object is used to enable cross-process accessibility focus querying.
13 //
14 // The following bullet points describe the need for this class:
15 // * The NSViews in out-of-process NSViews (e.g, for PWAs) will return a
16 //   NSRemoteAccessibilityElement from -[NSView accessibilityFocusedUIElement].
17 // * The focus query is then continued in the browser process by a call to
18 //   -[NSApplication accessibilityFocusedUIElement].
19 // * The default implementation -[NSApplication accessibilityFocusedUIElement]
20 //   in turn queries -[NSApplication keyWindow]'s accessibilityFocusedUIElement
21 //   method.
22 // * This is not what the PWA process wants. The PWA process wants its focus,
23 //   not the browser's focus.
24 // * To make this happen, when the PWA process' NSViews are focused, they
25 //   force the browser's  -[NSApplication accessibilityFocusedUIElement] to
26 //   return their accessibility focus.
27 //
28 // The above-required overriding of focus is done by instantiating an
29 // AccessibilityFocusOverrider and updating its state when the NSView in the
30 // PWA process is focused.
31 class UI_BASE_EXPORT AccessibilityFocusOverrider {
32  public:
33   class Client {
34    public:
35     virtual id GetAccessibilityFocusedUIElement() = 0;
36   };
37 
38   AccessibilityFocusOverrider(Client* client);
39   ~AccessibilityFocusOverrider();
40 
41   // Indicate if the NSApplication that is viewing this element is not this
42   // process. Focus overriding is only needed for cross-process focus.
43   void SetAppIsRemote(bool app_is_remote);
44 
45   // Indicate whether or not the view's window is currently key. This object
46   // will override the application's focused accessibility element only if its
47   // window is key (and the view is the window's first responder).
48   void SetWindowIsKey(bool window_is_key);
49 
50   // Indicate whether or not the view is its window's first responder. This
51   // object will override the application's focused accessibility element only
52   // if the view is the window's first responder (and its window is key).
53   void SetViewIsFirstResponder(bool view_is_first_responder);
54 
55   // Return the overridden focus, or nil if there is no overridden focus.
56   static id GetFocusedUIElement();
57 
58  private:
59   void UpdateOverriddenKeyElement();
60   bool app_is_remote_ = false;
61   bool window_is_key_ = false;
62   bool view_is_first_responder_ = false;
63   Client* const client_;
64 };
65 
66 }  // namespace ui
67 
68 #endif  // UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
69