Commit 94853e6e authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

RemoteMacViews: Add mojo plumbing for content accessibility elements

Add a mojo method to send the NSAccessibilityRemoteUIElement tokens for
the NSView and NSWindow in the viewer (app shim) process to the browser
process, and to return the NSAccessibilityRemoteUIElement for the web
contents (in the browser) the viewer (app shim) process.

Update -[BrowserAccessibilityCocoa window] to call either
-[NSView window] or -[NSAccessibilityRemoteUIElement windowUIElement],
depending on which object is returned by GetParentView.

Change -[RenderWidgetHostViewCocoa accessibilityFocusedUIElement] to
call a GetFocusedBrowserAccessibilityElement, which will return the
the NSAccessibilityRemoteUIElement when called in an app shim
process.

Bug: 900846
Change-Id: I0d3d65e9924613b0dc137a08d0030d31981ecfdd
Reviewed-on: https://chromium-review.googlesource.com/c/1351415
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611284}
parent afb3c15d
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "ui/accessibility/ax_range.h" #include "ui/accessibility/ax_range.h"
#include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_platform_node.h" #include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/base/cocoa/remote_accessibility_api.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h" #import "ui/accessibility/platform/ax_platform_node_mac.h"
...@@ -2284,7 +2285,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired"; ...@@ -2284,7 +2285,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (!manager || !manager->GetParentView()) if (!manager || !manager->GetParentView())
return nil; return nil;
return [manager->GetParentView() window]; id parent = manager->GetParentView();
// If |parent| is an NSView in this process, then return the corresponding
// NSWindow.
if (auto* view = base::mac::ObjCCast<NSView>(parent))
return [view window];
// If |parent| is a NSAccessibilityRemoteUIElement for an NSView in another
// process then return the NSAccessibilityRemoteUIElement for its NSWindow in
// that other process.
if (auto* element =
base::mac::ObjCCast<NSAccessibilityRemoteUIElement>(parent)) {
return [element windowUIElement];
}
DLOG(ERROR) << "Failed to find window accessibility element.";
return nil;
} }
- (NSString*)methodNameForAttribute:(NSString*)attribute { - (NSString*)methodNameForAttribute:(NSString*)attribute {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "content/public/browser/ns_view_bridge_factory_impl.h" #include "content/public/browser/ns_view_bridge_factory_impl.h"
#include <utility> #include <utility>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
#include "content/common/render_widget_host_ns_view.mojom.h" #include "content/common/render_widget_host_ns_view.mojom.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/cocoa/remote_accessibility_api.h"
namespace content { namespace content {
...@@ -44,7 +46,29 @@ class RenderWidgetHostNSViewBridgeOwner ...@@ -44,7 +46,29 @@ class RenderWidgetHostNSViewBridgeOwner
} }
// RenderWidgetHostNSViewClientHelper implementation. // RenderWidgetHostNSViewClientHelper implementation.
id GetRootBrowserAccessibilityElement() override { return nil; } id GetRootBrowserAccessibilityElement() override {
NSView* view = bridge_->GetRenderWidgetHostViewCocoa();
NSWindow* window = [view window];
// Send accessibility tokens only once the view has been attached to a
// window.
if (window && !remote_accessibility_element_) {
int64_t browser_pid = 0;
std::vector<uint8_t> element_token;
client_->SyncConnectAccessibilityElements(
ui::RemoteAccessibility::GetTokenForLocalElement(window),
ui::RemoteAccessibility::GetTokenForLocalElement(view), &browser_pid,
&element_token);
[NSAccessibilityRemoteUIElement
registerRemoteUIProcessIdentifier:browser_pid];
remote_accessibility_element_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(element_token);
}
return remote_accessibility_element_.get();
}
id GetFocusedBrowserAccessibilityElement() override {
return GetRootBrowserAccessibilityElement();
}
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event, void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override { const ui::LatencyInfo& latency_info) override {
const blink::WebKeyboardEvent* web_event = const blink::WebKeyboardEvent* web_event =
...@@ -103,6 +127,8 @@ class RenderWidgetHostNSViewBridgeOwner ...@@ -103,6 +127,8 @@ class RenderWidgetHostNSViewBridgeOwner
mojom::RenderWidgetHostNSViewClientAssociatedPtr client_; mojom::RenderWidgetHostNSViewClientAssociatedPtr client_;
std::unique_ptr<RenderWidgetHostNSViewBridgeLocal> bridge_; std::unique_ptr<RenderWidgetHostNSViewBridgeLocal> bridge_;
base::scoped_nsobject<NSAccessibilityRemoteUIElement>
remote_accessibility_element_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridgeOwner); DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridgeOwner);
}; };
......
...@@ -44,6 +44,9 @@ class RenderWidgetHostNSViewClientHelper { ...@@ -44,6 +44,9 @@ class RenderWidgetHostNSViewClientHelper {
// node. // node.
virtual id GetRootBrowserAccessibilityElement() = 0; virtual id GetRootBrowserAccessibilityElement() = 0;
// Return the currently focused accessibility element.
virtual id GetFocusedBrowserAccessibilityElement() = 0;
// Forward a keyboard event to the RenderWidgetHost that is currently handling // Forward a keyboard event to the RenderWidgetHost that is currently handling
// the key-down event. // the key-down event.
virtual void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event, virtual void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
......
...@@ -61,6 +61,7 @@ class DummyClientHelper : public RenderWidgetHostNSViewClientHelper { ...@@ -61,6 +61,7 @@ class DummyClientHelper : public RenderWidgetHostNSViewClientHelper {
private: private:
// RenderWidgetHostNSViewClientHelper implementation. // RenderWidgetHostNSViewClientHelper implementation.
id GetRootBrowserAccessibilityElement() override { return nil; } id GetRootBrowserAccessibilityElement() override { return nil; }
id GetFocusedBrowserAccessibilityElement() override { return nil; }
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event, void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override {} const ui::LatencyInfo& latency_info) override {}
void ForwardKeyboardEventWithCommands( void ForwardKeyboardEventWithCommands(
...@@ -1448,10 +1449,7 @@ void ExtractUnderlines(NSAttributedString* string, ...@@ -1448,10 +1449,7 @@ void ExtractUnderlines(NSAttributedString* string,
} }
- (id)accessibilityFocusedUIElement { - (id)accessibilityFocusedUIElement {
// This function should almost-never be called because when |self| is the return clientHelper_->GetFocusedBrowserAccessibilityElement();
// first responder for the key NSWindow, RenderWidgetHostViewMac's
// AccessibilityFocusOverrider will override the accessibility focus query.
return [super accessibilityFocusedUIElement];
} }
// Below is our NSTextInputClient implementation. // Below is our NSTextInputClient implementation.
......
...@@ -37,6 +37,7 @@ class ScopedPasswordInputEnabler; ...@@ -37,6 +37,7 @@ class ScopedPasswordInputEnabler;
@protocol RenderWidgetHostViewMacDelegate; @protocol RenderWidgetHostViewMacDelegate;
@class NSAccessibilityRemoteUIElement;
@class RenderWidgetHostViewCocoa; @class RenderWidgetHostViewCocoa;
namespace content { namespace content {
...@@ -300,6 +301,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -300,6 +301,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostNSViewClientHelper implementation. // RenderWidgetHostNSViewClientHelper implementation.
id GetRootBrowserAccessibilityElement() override; id GetRootBrowserAccessibilityElement() override;
id GetFocusedBrowserAccessibilityElement() override;
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event, void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override; const ui::LatencyInfo& latency_info) override;
void ForwardKeyboardEventWithCommands( void ForwardKeyboardEventWithCommands(
...@@ -388,6 +390,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -388,6 +390,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void StopSpeaking() override; void StopSpeaking() override;
bool SyncIsSpeaking(bool* is_speaking) override; bool SyncIsSpeaking(bool* is_speaking) override;
void SyncIsSpeaking(SyncIsSpeakingCallback callback) override; void SyncIsSpeaking(SyncIsSpeakingCallback callback) override;
void SyncConnectAccessibilityElements(
const std::vector<uint8_t>& window_token,
const std::vector<uint8_t>& view_token,
SyncConnectAccessibilityElementsCallback callback) override;
// BrowserCompositorMacClient implementation. // BrowserCompositorMacClient implementation.
SkColor BrowserCompositorMacGetGutterColor() const override; SkColor BrowserCompositorMacGetGutterColor() const override;
...@@ -627,6 +633,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -627,6 +633,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// EnsureSurfaceSynchronizedForLayoutTest(). // EnsureSurfaceSynchronizedForLayoutTest().
uint32_t latest_capture_sequence_number_ = 0u; uint32_t latest_capture_sequence_number_ = 0u;
// Remote accessibility objects corresponding to the NSWindow and its root
// NSView.
base::scoped_nsobject<NSAccessibilityRemoteUIElement>
remote_window_accessible_;
base::scoped_nsobject<NSAccessibilityRemoteUIElement> remote_view_accessible_;
// Used to force the NSApplication's focused accessibility element to be the // Used to force the NSApplication's focused accessibility element to be the
// content::BrowserAccessibilityCocoa accessibility tree when the NSView for // content::BrowserAccessibilityCocoa accessibility tree when the NSView for
// this is focused. // this is focused.
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#import "ui/base/clipboard/clipboard_util_mac.h" #import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/cocoa/animation_utils.h" #include "ui/base/cocoa/animation_utils.h"
#include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/base/cocoa/remote_accessibility_api.h"
#import "ui/base/cocoa/secure_password_input.h" #import "ui/base/cocoa/secure_password_input.h"
#include "ui/base/cocoa/text_services_context_menu.h" #include "ui/base/cocoa/text_services_context_menu.h"
#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_features.h"
...@@ -252,6 +253,10 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() { ...@@ -252,6 +253,10 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
void RenderWidgetHostViewMac::MigrateNSViewBridge( void RenderWidgetHostViewMac::MigrateNSViewBridge(
NSViewBridgeFactoryHost* bridge_factory_host, NSViewBridgeFactoryHost* bridge_factory_host,
uint64_t parent_ns_view_id) { uint64_t parent_ns_view_id) {
// Destroy previous remote accessibility elements.
remote_window_accessible_.reset();
remote_view_accessible_.reset();
// Disconnect from the previous bridge (this will have the effect of // Disconnect from the previous bridge (this will have the effect of
// destroying the associated bridge), and close the binding (to allow it // destroying the associated bridge), and close the binding (to allow it
// to be re-bound). Note that |ns_view_bridge_local_| remains valid. // to be re-bound). Note that |ns_view_bridge_local_| remains valid.
...@@ -492,6 +497,8 @@ gfx::NativeView RenderWidgetHostViewMac::GetNativeView() const { ...@@ -492,6 +497,8 @@ gfx::NativeView RenderWidgetHostViewMac::GetNativeView() const {
} }
gfx::NativeViewAccessible RenderWidgetHostViewMac::GetNativeViewAccessible() { gfx::NativeViewAccessible RenderWidgetHostViewMac::GetNativeViewAccessible() {
if (remote_view_accessible_)
return remote_view_accessible_.get();
return cocoa_view(); return cocoa_view();
} }
...@@ -1399,6 +1406,8 @@ gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen( ...@@ -1399,6 +1406,8 @@ gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen(
gfx::NativeViewAccessible gfx::NativeViewAccessible
RenderWidgetHostViewMac::AccessibilityGetNativeViewAccessible() { RenderWidgetHostViewMac::AccessibilityGetNativeViewAccessible() {
if (remote_view_accessible_)
return remote_view_accessible_.get();
return cocoa_view(); return cocoa_view();
} }
...@@ -1433,6 +1442,14 @@ id RenderWidgetHostViewMac::GetRootBrowserAccessibilityElement() { ...@@ -1433,6 +1442,14 @@ id RenderWidgetHostViewMac::GetRootBrowserAccessibilityElement() {
return nil; return nil;
} }
id RenderWidgetHostViewMac::GetFocusedBrowserAccessibilityElement() {
// This function should never be called because
// |accessibility_focus_overrider_| override the application focus query.
DLOG(ERROR) << "GetFocusedBrowserAccessibilityElement should not be reached "
"in-process.";
return nil;
}
bool RenderWidgetHostViewMac::SyncIsRenderViewHost(bool* is_render_view) { bool RenderWidgetHostViewMac::SyncIsRenderViewHost(bool* is_render_view) {
*is_render_view = RenderViewHost::From(host()) != nullptr; *is_render_view = RenderViewHost::From(host()) != nullptr;
return true; return true;
...@@ -1907,6 +1924,23 @@ void RenderWidgetHostViewMac::StopSpeaking() { ...@@ -1907,6 +1924,23 @@ void RenderWidgetHostViewMac::StopSpeaking() {
ui::TextServicesContextMenu::StopSpeaking(); ui::TextServicesContextMenu::StopSpeaking();
} }
void RenderWidgetHostViewMac::SyncConnectAccessibilityElements(
const std::vector<uint8_t>& window_token,
const std::vector<uint8_t>& view_token,
SyncConnectAccessibilityElementsCallback callback) {
remote_window_accessible_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(window_token);
remote_view_accessible_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(view_token);
[remote_view_accessible_ setWindowUIElement:remote_window_accessible_.get()];
[remote_view_accessible_
setTopLevelUIElement:remote_window_accessible_.get()];
id element_id = GetRootBrowserAccessibilityElement();
std::move(callback).Run(
getpid(), ui::RemoteAccessibility::GetTokenForLocalElement(element_id));
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// mojom::RenderWidgetHostNSViewClient functions that translate events and // mojom::RenderWidgetHostNSViewClient functions that translate events and
// forward them to the RenderWidgetHostNSViewClientHelper implementation: // forward them to the RenderWidgetHostNSViewClientHelper implementation:
......
...@@ -230,5 +230,14 @@ interface RenderWidgetHostNSViewClient { ...@@ -230,5 +230,14 @@ interface RenderWidgetHostNSViewClient {
// return the result as |is_speaking|. // return the result as |is_speaking|.
[Sync] [Sync]
SyncIsSpeaking() => (bool is_speaking); SyncIsSpeaking() => (bool is_speaking);
// Return in |element_token| the token for the AX node for this view. Return
// the pid of the browser process to be registered as a remote UI process. Set
// the AX node for this view to have the element indicated by |window_token|
// as its window and the element indicated by |view_token| as its parent.
[Sync]
SyncConnectAccessibilityElements(array<uint8> window_token,
array<uint8> view_token) =>
(int64 host_pid, array<uint8> element_token);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment