summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 21:16:29 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 21:16:29 +0000
commit3e3c452f5119bc837ebc98af5de8d5d75cd04ce6 (patch)
tree8e06f820d5562a0e8f7be427bfff37bb9c92fb78
parent2436a6b19ebb77226b96b0e37623b9b0785e172c (diff)
downloadchromium_src-3e3c452f5119bc837ebc98af5de8d5d75cd04ce6.zip
chromium_src-3e3c452f5119bc837ebc98af5de8d5d75cd04ce6.tar.gz
chromium_src-3e3c452f5119bc837ebc98af5de8d5d75cd04ce6.tar.bz2
Add an accessibility mode for editable text fields only.
This refactors the triggering of accessibility mode from a boolean state and command-line flag to an AccessibilityMode enum that's passed directly when a new RenderView is created, which is also more readable and avoids the extra command-line flag. Adds a new mode that only syncs editable text nodes, and enables this on Windows 8 so that we can support showing the virtual keyboard when an editable text field gets focus. BUG=122061,118641 TEST=Adds new test Review URL: http://codereview.chromium.org/9939011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132267 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_browser_application_mac.mm2
-rw-r--r--content/browser/accessibility/browser_accessibility_state_impl.cc10
-rw-r--r--content/browser/accessibility/dump_accessibility_tree_browsertest.cc3
-rw-r--r--content/browser/accessibility/renderer_accessibility_browsertest.cc52
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc8
-rw-r--r--content/browser/renderer_host/render_process_host_impl.h5
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc19
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc37
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h11
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc6
-rw-r--r--content/common/accessibility_messages.h7
-rw-r--r--content/common/view_message_enums.h17
-rw-r--r--content/common/view_messages.h3
-rw-r--r--content/public/browser/render_process_host.h3
-rw-r--r--content/public/browser/render_widget_host.h5
-rw-r--r--content/public/common/content_switches.cc3
-rw-r--r--content/public/common/content_switches.h1
-rw-r--r--content/renderer/render_thread_impl.cc3
-rw-r--r--content/renderer/render_view_impl.cc15
-rw-r--r--content/renderer/render_view_impl.h10
-rw-r--r--content/renderer/renderer_accessibility.cc75
-rw-r--r--content/renderer/renderer_accessibility.h26
-rw-r--r--content/test/mock_render_process_host.cc2
-rw-r--r--content/test/mock_render_process_host.h2
-rw-r--r--content/test/render_view_test.cc3
-rw-r--r--webkit/glue/webaccessibility.h8
26 files changed, 246 insertions, 90 deletions
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm
index 765cec2..26eb400 100644
--- a/chrome/browser/chrome_browser_application_mac.mm
+++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -505,7 +505,7 @@ void SwizzleInit() {
if (TabContentsWrapper* contents = *it) {
if (content::RenderViewHost* rvh =
contents->web_contents()->GetRenderViewHost()) {
- rvh->EnableRendererAccessibility();
+ rvh->EnableFullAccessibilityMode();
}
}
}
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index f3b8aaf..b878cdb 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -4,9 +4,11 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "base/command_line.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/timer.h"
+#include "content/public/common/content_switches.h"
#include "ui/gfx/sys_color_change_listener.h"
// Update the accessibility histogram 45 seconds after initialization.
@@ -26,6 +28,10 @@ BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
: BrowserAccessibilityState(),
accessibility_enabled_(false) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceRendererAccessibility)) {
+ OnAccessibilityEnabledManually();
+ }
update_histogram_timer_.Start(
FROM_HERE,
base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs),
@@ -37,6 +43,10 @@ BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
}
void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableRendererAccessibility)) {
+ return;
+ }
accessibility_enabled_ = true;
}
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 5a7125c..d47da85 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -89,7 +89,7 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RenderViewHostImpl* view_host =
static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(host));
view_host->set_save_accessibility_tree_for_testing(true);
- view_host->EnableRendererAccessibility();
+ view_host->SetAccessibilityMode(AccessibilityModeComplete);
// Setup test paths.
FilePath dir_test_data;
@@ -199,4 +199,3 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
}
} while (!(html_file = file_enumerator.Next()).empty());
}
-
diff --git a/content/browser/accessibility/renderer_accessibility_browsertest.cc b/content/browser/accessibility/renderer_accessibility_browsertest.cc
index 76d77fd..e8c5acc 100644
--- a/content/browser/accessibility/renderer_accessibility_browsertest.cc
+++ b/content/browser/accessibility/renderer_accessibility_browsertest.cc
@@ -35,7 +35,8 @@ class RendererAccessibilityBrowserTest : public InProcessBrowserTest {
// Tell the renderer to send an accessibility tree, then wait for the
// notification that it's been received.
- const WebAccessibility& GetWebAccessibilityTree() {
+ const WebAccessibility& GetWebAccessibilityTree(
+ AccessibilityMode accessibility_mode = AccessibilityModeComplete) {
ui_test_utils::WindowedNotificationObserver tree_updated_observer(
content::NOTIFICATION_RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED,
content::NotificationService::AllSources());
@@ -45,7 +46,7 @@ class RendererAccessibilityBrowserTest : public InProcessBrowserTest {
RenderWidgetHostImpl::From(host_view->GetRenderWidgetHost());
RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(host);
view_host->set_save_accessibility_tree_for_testing(true);
- view_host->EnableRendererAccessibility();
+ view_host->SetAccessibilityMode(accessibility_mode);
tree_updated_observer.Wait();
return view_host->accessibility_tree_for_testing();
}
@@ -463,4 +464,51 @@ IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
true, GetBoolAttr(textbox, WebAccessibility::ATTR_CAN_SET_VALUE));
}
+IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
+ CrossPlatformEditableTextOnlyMode) {
+ const char url_str[] =
+ "data:text/html,"
+ "<!doctype html>"
+ "<h1>Heading</h1>"
+ "<input type=text value=text0>"
+ "<textarea>text1</textarea>"
+ "<div role=textbox>text2</div>"
+ "<ul>"
+ " <li><input type=text value=text3>"
+ " <li><textarea>text4</textarea>"
+ " <li><div role=textbox>text5</div>"
+ " <li><button>button</button>"
+ "</ul>";
+
+ GURL url(url_str);
+ browser()->OpenURL(OpenURLParams(
+ url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
+ const WebAccessibility& tree = GetWebAccessibilityTree(
+ AccessibilityModeEditableTextOnly);
+
+ const WebAccessibility& text0 = tree.children[0];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text0.role);
+ EXPECT_STREQ("text0", UTF16ToUTF8(text0.value).c_str());
+
+ const WebAccessibility& text1 = tree.children[1];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXTAREA, text1.role);
+ EXPECT_STREQ("text1", UTF16ToUTF8(text1.value).c_str());
+
+ const WebAccessibility& text2 = tree.children[2];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text2.role);
+ EXPECT_STREQ("text2", UTF16ToUTF8(text2.value).c_str());
+
+ const WebAccessibility& text3 = tree.children[3];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text3.role);
+ EXPECT_STREQ("text3", UTF16ToUTF8(text3.value).c_str());
+
+ const WebAccessibility& text4 = tree.children[4];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXTAREA, text4.role);
+ EXPECT_STREQ("text4", UTF16ToUTF8(text4.value).c_str());
+
+ const WebAccessibility& text5 = tree.children[5];
+ EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text5.role);
+ EXPECT_STREQ("text5", UTF16ToUTF8(text5.value).c_str());
+}
+
} // namespace
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 2800992..29724ec 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -279,7 +279,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_(
FROM_HERE, base::TimeDelta::FromSeconds(5),
this, &RenderProcessHostImpl::ClearTransportDIBCache)),
- accessibility_enabled_(false),
is_initialized_(false),
id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
browser_context_(browser_context),
@@ -353,14 +352,12 @@ void RenderProcessHostImpl::EnableSendQueue() {
is_initialized_ = false;
}
-bool RenderProcessHostImpl::Init(bool is_accessibility_enabled) {
+bool RenderProcessHostImpl::Init() {
// calling Init() more than once does nothing, this makes it more convenient
// for the view host which may not be sure in some cases
if (channel_.get())
return true;
- accessibility_enabled_ = is_accessibility_enabled;
-
CommandLine::StringType renderer_prefix;
#if defined(OS_POSIX)
// A command prefix is something prepended to the command line of the spawned
@@ -615,9 +612,6 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kRendererProcess);
- if (accessibility_enabled_)
- command_line->AppendSwitch(switches::kEnableAccessibility);
-
// Now send any options from our own command line we want to propagate.
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 71a41eb..b1986e7 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -58,7 +58,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// RenderProcessHost implementation (public portion).
virtual void EnableSendQueue() OVERRIDE;
- virtual bool Init(bool is_accessibility_enabled) OVERRIDE;
+ virtual bool Init() OVERRIDE;
virtual int GetNextRoutingID() OVERRIDE;
virtual void CancelResourceRequests(int render_widget_id) OVERRIDE;
virtual void CrossSiteSwapOutACK(const ViewMsg_SwapOut_Params& params)
@@ -220,9 +220,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Used in single-process mode.
scoped_ptr<RendererMainThread> in_process_renderer_;
- // True if this prcoess should have accessibility enabled;
- bool accessibility_enabled_;
-
// True after Init() has been called. We can't just check channel_ because we
// also reset that in the case of process termination.
bool is_initialized_;
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index f333925..04de175 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -18,6 +18,9 @@
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/cross_site_request_manager.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
@@ -33,6 +36,7 @@
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/content_browser_client.h"
@@ -205,7 +209,7 @@ bool RenderViewHostImpl::CreateRenderView(const string16& frame_name,
// initialized it) or may not (we have our own process or the old process
// crashed) have been initialized. Calling Init multiple times will be
// ignored, so this is safe.
- if (!GetProcess()->Init(renderer_accessible()))
+ if (!GetProcess()->Init())
return false;
DCHECK(GetProcess()->HasConnection());
DCHECK(GetProcess()->GetBrowserContext());
@@ -245,6 +249,19 @@ bool RenderViewHostImpl::CreateRenderView(const string16& frame_name,
gfx::NativeViewFromId(GetNativeViewId()));
#endif
params.guest = guest_;
+ params.accessibility_mode =
+ BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser() ?
+ AccessibilityModeComplete :
+ AccessibilityModeOff;
+
+#if defined(OS_WIN)
+ // On Windows 8, always enable accessibility for editable text controls
+ // so we can show the virtual keyboard when one is enabled.
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
+ params.accessibility_mode == AccessibilityModeOff) {
+ params.accessibility_mode = AccessibilityModeEditableTextOnly;
+ }
+#endif
Send(new ViewMsg_New(params));
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index e6835f0..3a526a3 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -28,7 +28,6 @@
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -106,7 +105,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderProcessHost* process,
hung_renderer_delay_ms_(kHungRendererDelayMs),
process_(process),
routing_id_(routing_id),
- renderer_accessible_(false),
surface_id_(0),
is_loading_(false),
is_hidden_(false),
@@ -154,16 +152,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderProcessHost* process,
// Because the widget initializes as is_hidden_ == false,
// tell the process host that we're alive.
process_->WidgetRestored();
-
- // Enable accessibility if it was manually specified or if it was
- // auto-detected.
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceRendererAccessibility)) {
- BrowserAccessibilityState::GetInstance()->OnAccessibilityEnabledManually();
- EnableRendererAccessibility();
- } else if (BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) {
- EnableRendererAccessibility();
- }
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
@@ -701,6 +689,10 @@ void RenderWidgetHostImpl::StopHangMonitorTimeout() {
// started again shortly, which happens to be the common use case.
}
+void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
+ SetAccessibilityMode(AccessibilityModeComplete);
+}
+
void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::ForwardMouseEvent",
"x", mouse_event.x, "y", mouse_event.y);
@@ -1519,23 +1511,6 @@ void RenderWidgetHostImpl::Replace(const string16& word) {
Send(new ViewMsg_Replace(routing_id_, word));
}
-void RenderWidgetHostImpl::EnableRendererAccessibility() {
- if (renderer_accessible_)
- return;
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererAccessibility)) {
- return;
- }
-
- renderer_accessible_ = true;
-
- if (process_->HasConnection()) {
- // Renderer accessibility wasn't enabled on process launch. Enable it now.
- Send(new AccessibilityMsg_Enable(GetRoutingID()));
- }
-}
-
void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
ignore_input_events_ = ignore_input_events;
}
@@ -1611,6 +1586,10 @@ void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
Send(new ViewMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
}
+void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
+ Send(new AccessibilityMsg_SetMode(routing_id_, mode));
+}
+
void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
}
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 2a93e2c..adb71f5 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -19,6 +19,7 @@
#include "base/string16.h"
#include "base/timer.h"
#include "build/build_config.h"
+#include "content/common/view_message_enums.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/common/page_zoom.h"
#include "ui/base/ime/text_input_type.h"
@@ -94,7 +95,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
virtual bool CopyFromBackingStoreToCGContext(const CGRect& dest_rect,
CGContextRef target) OVERRIDE;
#endif
- virtual void EnableRendererAccessibility() OVERRIDE;
+ virtual void EnableFullAccessibilityMode() OVERRIDE;
virtual void ForwardMouseEvent(
const WebKit::WebMouseEvent& mouse_event) OVERRIDE;
virtual void ForwardWheelEvent(
@@ -123,7 +124,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void SetView(RenderWidgetHostView* view);
int surface_id() const { return surface_id_; }
- bool renderer_accessible() { return renderer_accessible_; }
bool empty() const { return current_size_.IsEmpty(); }
@@ -298,6 +298,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void SetEditCommandsForNextKeyEvent(
const std::vector<EditCommand>& commands);
+ // Send a message to the renderer process to change the accessibility mode.
+ void SetAccessibilityMode(AccessibilityMode mode);
+
// Relay a request from assistive technology to perform the default action
// on a given node.
void AccessibilityDoDefaultAction(int object_id);
@@ -550,10 +553,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// The ID of the corresponding object in the Renderer Instance.
int routing_id_;
- // True if renderer accessibility is enabled. This should only be set when a
- // screenreader is detected as it can potentially slow down Chrome.
- bool renderer_accessible_;
-
// Stores random bits of data for others to associate with this object.
base::PropertyBag property_bag_;
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index daeb538..6e749b9 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -464,7 +464,8 @@ gfx::NativeViewId RenderWidgetHostViewWin::GetNativeViewId() const {
gfx::NativeViewAccessible
RenderWidgetHostViewWin::GetNativeViewAccessible() {
- if (render_widget_host_ && !render_widget_host_->renderer_accessible()) {
+ if (render_widget_host_ &&
+ !BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) {
// Attempt to detect screen readers by sending an event with our custom id.
NotifyWinEvent(EVENT_SYSTEM_ALERT, m_hWnd, kIdCustom, CHILDID_SELF);
}
@@ -2289,7 +2290,8 @@ LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam,
// An MSAA client requestes our custom id. Assume that we have detected an
// active windows screen reader.
BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
- render_widget_host_->EnableRendererAccessibility();
+ if (BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser())
+ render_widget_host_->SetAccessibilityMode(AccessibilityModeComplete);
// Return with failure.
return static_cast<LRESULT>(0L);
diff --git a/content/common/accessibility_messages.h b/content/common/accessibility_messages.h
index a37329e..4e6dc0d 100644
--- a/content/common/accessibility_messages.h
+++ b/content/common/accessibility_messages.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "content/common/content_export.h"
+#include "content/common/view_message_enums.h"
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
@@ -88,6 +89,7 @@ enum AccessibilityNotification {
#endif // CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
+IPC_ENUM_TRAITS(AccessibilityMode)
IPC_ENUM_TRAITS(AccessibilityNotification)
IPC_ENUM_TRAITS(webkit_glue::WebAccessibility::BoolAttribute)
@@ -133,8 +135,9 @@ IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
-// Enable accessibility in the renderer process.
-IPC_MESSAGE_ROUTED0(AccessibilityMsg_Enable)
+// Change the accessibility mode in the renderer process.
+IPC_MESSAGE_ROUTED1(AccessibilityMsg_SetMode,
+ AccessibilityMode)
// Relay a request from assistive technology to set focus to a given node.
IPC_MESSAGE_ROUTED1(AccessibilityMsg_SetFocus,
diff --git a/content/common/view_message_enums.h b/content/common/view_message_enums.h
index 29761b2..772dbca 100644
--- a/content/common/view_message_enums.h
+++ b/content/common/view_message_enums.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_COMMON_VIEW_MESSAGES_ENUMS_H_
#define CONTENT_COMMON_VIEW_MESSAGES_ENUMS_H_
+#include "ipc/ipc_message_macros.h"
+
// Values that may be OR'd together to form the 'flags' parameter of a
// ViewHostMsg_UpdateRect_Params structure.
struct ViewHostMsg_UpdateRect_Flags {
@@ -48,4 +50,19 @@ struct ViewMsg_Navigate_Type {
};
};
+enum AccessibilityMode {
+ // WebKit accessibility is off and no accessibility information is
+ // sent from the renderer to the browser process.
+ AccessibilityModeOff,
+
+ // WebKit accessibility is on, but only limited information about
+ // editable text nodes is sent to the browser process. Useful for
+ // implementing limited UIA on tablets.
+ AccessibilityModeEditableTextOnly,
+
+ // WebKit accessibility is on, and the full accessibility tree is synced
+ // to the browser process. Useful for screen readers and magnifiers.
+ AccessibilityModeComplete,
+};
+
#endif // CONTENT_COMMON_VIEW_MESSAGES_ENUMS_H_
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 8d75190..246dc4a 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -648,6 +648,9 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
// Indicates whether this newly created RenderView will be hosted by another
// RenderView.
IPC_STRUCT_MEMBER(bool, guest)
+
+ // The accessibility mode of the renderer.
+ IPC_STRUCT_MEMBER(AccessibilityMode, accessibility_mode)
IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index eec6a6b..c345294 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -61,7 +61,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Message::Sender,
// be called once before the object can be used, but can be called after
// that with no effect. Therefore, if the caller isn't sure about whether
// the process has been created, it should just call Init().
- virtual bool Init(bool is_accessibility_enabled) = 0;
+ virtual bool Init() = 0;
// Gets the next available routing id.
virtual int GetNextRoutingID() = 0;
@@ -242,4 +242,3 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Message::Sender,
} // namespace content.
#endif // CONTENT_PUBLIC_BROWSER_RENDER_PROCESS_HOST_H_
-
diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h
index 45db575..a3ca330 100644
--- a/content/public/browser/render_widget_host.h
+++ b/content/public/browser/render_widget_host.h
@@ -208,9 +208,8 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Channel::Sender {
CGContextRef target) = 0;
#endif
- // Enable renderer accessibility. This should only be called when a
- // screenreader is detected.
- virtual void EnableRendererAccessibility() = 0;
+ // Send a command to the renderer to turn on full accessibility.
+ virtual void EnableFullAccessibilityMode() = 0;
// Forwards the given message to the renderer. These are called by
// the view when it has received a message.
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 7dbe56c..5e68f10 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -217,9 +217,6 @@ const char kEnableAcceleratedPainting[] = "enable-accelerated-painting";
// Enable gpu-accelerated SVG/W3C filters.
const char kEnableAcceleratedFilters[] = "enable-accelerated-filters";
-// Enables WebKit accessibility within the renderer process.
-const char kEnableAccessibility[] = "enable-accessibility";
-
// Turns on extremely verbose logging of accessibility events.
const char kEnableAccessibilityLogging[] = "enable-accessibility-logging";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 3a0d6e4..1f28134 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -76,7 +76,6 @@ extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDomAutomationController[];
CONTENT_EXPORT extern const char kEnableAcceleratedPainting[];
CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
-extern const char kEnableAccessibility[];
extern const char kEnableAccessibilityLogging[];
extern const char kEnableBrowserPlugin[];
CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index a047050..b1aba00 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -890,7 +890,8 @@ void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
params.frame_name,
params.next_page_id,
params.screen_info,
- params.guest);
+ params.guest,
+ params.accessibility_mode);
}
GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index a1d0806..44b0656 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -435,7 +435,8 @@ RenderViewImpl::RenderViewImpl(
const string16& frame_name,
int32 next_page_id,
const WebKit::WebScreenInfo& screen_info,
- bool guest)
+ bool guest,
+ AccessibilityMode accessibility_mode)
: RenderWidget(WebKit::WebPopupTypeNone, screen_info),
webkit_preferences_(webkit_prefs),
send_content_state_immediately_(false),
@@ -474,6 +475,7 @@ RenderViewImpl::RenderViewImpl(
focused_plugin_id_(-1),
#endif
guest_(guest),
+ accessibility_mode_(accessibility_mode),
ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)) {
routing_id_ = routing_id;
surface_id_ = surface_id;
@@ -544,7 +546,7 @@ RenderViewImpl::RenderViewImpl(
// The next group of objects all implement RenderViewObserver, so are deleted
// along with the RenderView automatically.
devtools_agent_ = new DevToolsAgent(this);
- renderer_accessibility_ = new RendererAccessibility(this);
+ renderer_accessibility_ = new RendererAccessibility(this, accessibility_mode);
mouse_lock_dispatcher_ = new MouseLockDispatcher(this);
intents_host_ = new WebIntentsHost(this);
@@ -634,7 +636,8 @@ RenderViewImpl* RenderViewImpl::Create(
const string16& frame_name,
int32 next_page_id,
const WebKit::WebScreenInfo& screen_info,
- bool guest) {
+ bool guest,
+ AccessibilityMode accessibility_mode) {
DCHECK(routing_id != MSG_ROUTING_NONE);
return new RenderViewImpl(
parent_hwnd,
@@ -648,7 +651,8 @@ RenderViewImpl* RenderViewImpl::Create(
frame_name,
next_page_id,
screen_info,
- guest);
+ guest,
+ accessibility_mode);
}
WebPeerConnectionHandler* RenderViewImpl::CreatePeerConnectionHandler(
@@ -1512,7 +1516,8 @@ WebView* RenderViewImpl::createView(
frame_name,
1,
screen_info_,
- guest_);
+ guest_,
+ accessibility_mode_);
view->opened_by_user_gesture_ = params.user_gesture;
// Record whether the creator frame is trying to suppress the opener field.
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 432fe7ec..d6128a2 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -24,6 +24,7 @@
#include "content/common/edit_command.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/navigation_gesture.h"
+#include "content/common/view_message_enums.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
#include "content/public/common/renderer_preferences.h"
@@ -194,7 +195,8 @@ class RenderViewImpl : public RenderWidget,
const string16& frame_name,
int32 next_page_id,
const WebKit::WebScreenInfo& screen_info,
- bool guest);
+ bool guest,
+ AccessibilityMode accessibility_mode);
// Returns the RenderViewImpl containing the given WebView.
CONTENT_EXPORT static RenderViewImpl* FromWebView(WebKit::WebView* webview);
@@ -742,7 +744,8 @@ class RenderViewImpl : public RenderWidget,
const string16& frame_name,
int32 next_page_id,
const WebKit::WebScreenInfo& screen_info,
- bool guest);
+ bool guest,
+ AccessibilityMode accessibility_mode);
// Do not delete directly. This class is reference counted.
virtual ~RenderViewImpl();
@@ -1315,6 +1318,9 @@ class RenderViewImpl : public RenderWidget,
// Indicates whether this RenderView is a guest of another RenderView.
bool guest_;
+ // The accessibility mode.
+ AccessibilityMode accessibility_mode_;
+
// NOTE: pepper_delegate_ should be last member because its constructor calls
// AddObservers method of RenderViewImpl from c-tor.
content::PepperPluginDelegateImpl pepper_delegate_;
diff --git a/content/renderer/renderer_accessibility.cc b/content/renderer/renderer_accessibility.cc
index 7e879ef..bfb22f1 100644
--- a/content/renderer/renderer_accessibility.cc
+++ b/content/renderer/renderer_accessibility.cc
@@ -5,7 +5,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop.h"
-#include "content/common/accessibility_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_accessibility.h"
@@ -84,18 +83,19 @@ bool WebAccessibilityNotificationToAccessibilityNotification(
return true;
}
-RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view)
+RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view,
+ AccessibilityMode mode)
: content::RenderViewObserver(render_view),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
browser_root_(NULL),
last_scroll_offset_(gfx::Size()),
+ mode_(AccessibilityModeOff),
ack_pending_(false),
logging_(false) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kEnableAccessibility))
- WebAccessibilityObject::enableAccessibility();
if (command_line.HasSwitch(switches::kEnableAccessibilityLogging))
logging_ = true;
+ OnSetMode(mode);
}
RendererAccessibility::~RendererAccessibility() {
@@ -104,7 +104,7 @@ RendererAccessibility::~RendererAccessibility() {
bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_Enable, OnEnable)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_SetMode, OnSetMode)
IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction,
OnDoDefaultAction)
@@ -303,11 +303,11 @@ void RendererAccessibility::SendPendingAccessibilityNotifications() {
}
AccessibilityHostMsg_NotificationParams notification_msg;
+ BuildAccessibilityTree(obj, includes_children, &notification_msg.acc_tree);
WebAccessibilityNotificationToAccessibilityNotification(
notification.type, &notification_msg.notification_type);
notification_msg.id = notification.id;
notification_msg.includes_children = includes_children;
- notification_msg.acc_tree = WebAccessibility(obj, includes_children);
if (obj.axID() == root_id) {
DCHECK_EQ(notification_msg.acc_tree.role,
WebAccessibility::ROLE_WEB_AREA);
@@ -486,9 +486,17 @@ void RendererAccessibility::OnNotificationsAck() {
SendPendingAccessibilityNotifications();
}
-void RendererAccessibility::OnEnable() {
- if (WebAccessibilityObject::accessibilityEnabled())
+void RendererAccessibility::OnSetMode(AccessibilityMode mode) {
+ if (mode_ == mode) {
return;
+ }
+
+ mode_ = mode;
+ if (mode_ == AccessibilityModeOff) {
+ // Note: should we have a way to turn off WebKit accessibility?
+ // Right now it's a one-way switch.
+ return;
+ }
WebAccessibilityObject::enableAccessibility();
@@ -561,3 +569,54 @@ WebDocument RendererAccessibility::GetMainDocument() {
else
return WebDocument();
}
+
+bool RendererAccessibility::IsEditableText(const WebAccessibilityObject& obj) {
+ return (obj.roleValue() == WebKit::WebAccessibilityRoleTextArea ||
+ obj.roleValue() == WebKit::WebAccessibilityRoleTextField);
+}
+
+void RendererAccessibility::RecursiveAddEditableTextNodesToTree(
+ const WebAccessibilityObject& src,
+ WebAccessibility* dst) {
+ if (IsEditableText(src)) {
+ dst->children.push_back(WebAccessibility(src, false));
+ } else {
+ int child_count = src.childCount();
+ std::set<int32> child_ids;
+ for (int i = 0; i < child_count; ++i) {
+ WebAccessibilityObject child = src.childAt(i);
+ if (!child.isValid())
+ continue;
+ RecursiveAddEditableTextNodesToTree(child, dst);
+ }
+ }
+}
+
+void RendererAccessibility::BuildAccessibilityTree(
+ const WebAccessibilityObject& src,
+ bool include_children,
+ WebAccessibility* dst) {
+ if (mode_ == AccessibilityModeComplete) {
+ dst->Init(src, include_children);
+ return;
+ }
+
+ // In Editable Text mode, we send a "collapsed" tree of only editable
+ // text nodes as direct descendants of the root.
+ CHECK_EQ(mode_, AccessibilityModeEditableTextOnly);
+ if (IsEditableText(src)) {
+ dst->Init(src, false);
+ return;
+ }
+
+ // If it's not an editable text node, it must be the root, because
+ // BuildAccessibilityTree will never be called on a non-root node
+ // that isn't already in the browser's tree.
+ CHECK_EQ(src.axID(), GetMainDocument().accessibilityObject().axID());
+
+ // Initialize the main document node, but don't add any children.
+ dst->Init(src, false);
+
+ // Find all editable text nodes and add them as children.
+ RecursiveAddEditableTextNodesToTree(src, dst);
+}
diff --git a/content/renderer/renderer_accessibility.h b/content/renderer/renderer_accessibility.h
index 835a00f..e7dd1dc 100644
--- a/content/renderer/renderer_accessibility.h
+++ b/content/renderer/renderer_accessibility.h
@@ -10,6 +10,7 @@
#include "base/hash_tables.h"
#include "base/memory/weak_ptr.h"
+#include "content/common/accessibility_messages.h"
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityNotification.h"
@@ -32,7 +33,8 @@ struct WebAccessibility;
// nodes in the tree (e.g., change focus, or click on a button).
class RendererAccessibility : public content::RenderViewObserver {
public:
- RendererAccessibility(RenderViewImpl* render_view);
+ RendererAccessibility(RenderViewImpl* render_view,
+ AccessibilityMode accessibility_mode);
virtual ~RendererAccessibility();
// RenderView::Observer implementation.
@@ -85,7 +87,7 @@ class RendererAccessibility : public content::RenderViewObserver {
void OnChangeScrollPosition(int acc_obj_id, int scroll_x, int scroll_y);
void OnScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus);
void OnScrollToPoint(int acc_obj_id, gfx::Point point);
- void OnEnable();
+ void OnSetMode(AccessibilityMode mode);
void OnSetFocus(int acc_obj_id);
void OnSetTextSelection(int acc_obj_id, int start_offset, int end_offset);
@@ -98,6 +100,23 @@ class RendererAccessibility : public content::RenderViewObserver {
// no view or frame.
WebKit::WebDocument GetMainDocument();
+ // Checks if a WebKit accessibility object is an editable text node.
+ bool IsEditableText(const WebKit::WebAccessibilityObject& node);
+
+ // Recursively explore the tree of WebKit accessibility objects rooted
+ // at |src|, and for each editable text node encountered, add a
+ // corresponding WebAccessibility node as a child of |dst|.
+ void RecursiveAddEditableTextNodesToTree(
+ const WebKit::WebAccessibilityObject& src,
+ webkit_glue::WebAccessibility* dst);
+
+ // Build a tree of serializable WebAccessibility nodes to send to the
+ // browser process, given a WebAccessibilityObject node from WebKit.
+ // Modifies |dst| in-place, it's assumed to be empty.
+ void BuildAccessibilityTree(const WebKit::WebAccessibilityObject& src,
+ bool include_children,
+ webkit_glue::WebAccessibility* dst);
+
// So we can queue up tasks to be executed later.
base::WeakPtrFactory<RendererAccessibility> weak_factory_;
@@ -116,6 +135,9 @@ class RendererAccessibility : public content::RenderViewObserver {
// is fixed.
gfx::Size last_scroll_offset_;
+ // The current accessibility mode.
+ AccessibilityMode mode_;
+
// Set if we are waiting for an accessibility notification ack.
bool ack_pending_;
diff --git a/content/test/mock_render_process_host.cc b/content/test/mock_render_process_host.cc
index 90ba216..3c1b942 100644
--- a/content/test/mock_render_process_host.cc
+++ b/content/test/mock_render_process_host.cc
@@ -42,7 +42,7 @@ MockRenderProcessHost::~MockRenderProcessHost() {
void MockRenderProcessHost::EnableSendQueue() {
}
-bool MockRenderProcessHost::Init(bool is_accessibility_enabled) {
+bool MockRenderProcessHost::Init() {
return true;
}
diff --git a/content/test/mock_render_process_host.h b/content/test/mock_render_process_host.h
index 4726f66..7548b6d 100644
--- a/content/test/mock_render_process_host.h
+++ b/content/test/mock_render_process_host.h
@@ -34,7 +34,7 @@ class MockRenderProcessHost : public RenderProcessHost {
// RenderProcessHost implementation (public portion).
virtual void EnableSendQueue() OVERRIDE;
- virtual bool Init(bool is_accessibility_enabled) OVERRIDE;
+ virtual bool Init() OVERRIDE;
virtual int GetNextRoutingID() OVERRIDE;
virtual void CancelResourceRequests(int render_widget_id) OVERRIDE;
virtual void CrossSiteSwapOutACK(
diff --git a/content/test/render_view_test.cc b/content/test/render_view_test.cc
index a64f8aa..25e5488 100644
--- a/content/test/render_view_test.cc
+++ b/content/test/render_view_test.cc
@@ -166,7 +166,8 @@ void RenderViewTest::SetUp() {
string16(),
1,
WebKit::WebScreenInfo(),
- false);
+ false,
+ AccessibilityModeOff);
view->AddRef();
view_ = view;
diff --git a/webkit/glue/webaccessibility.h b/webkit/glue/webaccessibility.h
index 3b6df7a..2b5f928 100644
--- a/webkit/glue/webaccessibility.h
+++ b/webkit/glue/webaccessibility.h
@@ -259,6 +259,10 @@ struct WEBKIT_GLUE_EXPORT WebAccessibility {
~WebAccessibility();
+ // Initialize an already-created struct, same as the constructor above.
+ void Init(const WebKit::WebAccessibilityObject& src,
+ bool include_children);
+
#ifndef NDEBUG
std::string DebugString(bool recursive,
int render_routing_id,
@@ -266,10 +270,6 @@ struct WEBKIT_GLUE_EXPORT WebAccessibility {
#endif
private:
- // Initialize an already-created struct, same as the constructor above.
- void Init(const WebKit::WebAccessibilityObject& src,
- bool include_children);
-
// Returns true if |ancestor| is the first unignored parent of |child|,
// which means that when walking up the parent chain from |child|,
// |ancestor| is the *first* ancestor that isn't marked as