summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-30 01:18:56 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-30 01:18:56 +0000
commit5cbe1e21980f42927d7d1c11cc860131be266e7e (patch)
tree3b52e15044336cb89e3004214b4714e6148e5ea9 /chrome/browser/extensions
parent7a12518454d36fb4ac79431f56106b38cd2482ab (diff)
downloadchromium_src-5cbe1e21980f42927d7d1c11cc860131be266e7e.zip
chromium_src-5cbe1e21980f42927d7d1c11cc860131be266e7e.tar.gz
chromium_src-5cbe1e21980f42927d7d1c11cc860131be266e7e.tar.bz2
Add an accessibility API for events raised outside of the web content.
BUG=none TEST=none patch by Dominic Mazzoni <dmazzoni [at] google> review url: http://codereview.chromium.org/402099/show git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37597 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/extension_accessibility_api.cc181
-rw-r--r--chrome/browser/extensions/extension_accessibility_api.h96
-rw-r--r--chrome/browser/extensions/extension_accessibility_api_constants.cc38
-rw-r--r--chrome/browser/extensions/extension_accessibility_api_constants.h43
-rw-r--r--chrome/browser/extensions/extension_accessibility_apitest.cc17
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc5
-rw-r--r--chrome/browser/extensions/extensions_service.cc2
7 files changed, 382 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
new file mode 100644
index 0000000..24428af
--- /dev/null
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_tabs_module.h"
+
+#include "base/json/json_writer.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_accessibility_api.h"
+#include "chrome/browser/extensions/extension_accessibility_api_constants.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/extensions/extension.h"
+
+namespace keys = extension_accessibility_api_constants;
+
+// Returns the AccessibilityControlInfo serialized into a JSON string,
+// consisting of an array of a single object of type AccessibilityObject,
+// as defined in the accessibility extension api's json schema.
+std::string ControlInfoToJsonString(const AccessibilityControlInfo* info) {
+ ListValue args;
+ DictionaryValue* dict = new DictionaryValue();
+ info->SerializeToDict(dict);
+ args.Append(dict);
+ std::string json_args;
+ base::JSONWriter::Write(&args, false, &json_args);
+ return json_args;
+}
+
+ExtensionAccessibilityEventRouter*
+ ExtensionAccessibilityEventRouter::GetInstance() {
+ return Singleton<ExtensionAccessibilityEventRouter>::get();
+}
+
+void ExtensionAccessibilityEventRouter::ObserveProfile(Profile* profile) {
+ last_focused_control_dict_.Clear();
+
+ if (registrar_.IsEmpty()) {
+ registrar_.Add(this,
+ NotificationType::ACCESSIBILITY_WINDOW_OPENED,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::ACCESSIBILITY_WINDOW_CLOSED,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::ACCESSIBILITY_CONTROL_FOCUSED,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::ACCESSIBILITY_CONTROL_ACTION,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::ACCESSIBILITY_TEXT_CHANGED,
+ NotificationService::AllSources());
+ }
+}
+
+void ExtensionAccessibilityEventRouter::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::ACCESSIBILITY_WINDOW_OPENED:
+ OnWindowOpened(Details<const AccessibilityWindowInfo>(details).ptr());
+ break;
+ case NotificationType::ACCESSIBILITY_WINDOW_CLOSED:
+ OnWindowClosed(Details<const AccessibilityWindowInfo>(details).ptr());
+ break;
+ case NotificationType::ACCESSIBILITY_CONTROL_FOCUSED:
+ OnControlFocused(Details<const AccessibilityControlInfo>(details).ptr());
+ break;
+ case NotificationType::ACCESSIBILITY_CONTROL_ACTION:
+ OnControlAction(Details<const AccessibilityControlInfo>(details).ptr());
+ break;
+ case NotificationType::ACCESSIBILITY_TEXT_CHANGED:
+ OnTextChanged(Details<const AccessibilityControlInfo>(details).ptr());
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void ExtensionAccessibilityEventRouter::SetAccessibilityEnabled(bool enabled) {
+ if (enabled_ != enabled) {
+ enabled_ = enabled;
+ if (enabled_) {
+ for (unsigned int i = 0; i < on_enabled_listeners_.size(); i++) {
+ on_enabled_listeners_[i]->Run();
+ }
+ } else {
+ for (unsigned int i = 0; i < on_disabled_listeners_.size(); i++) {
+ on_disabled_listeners_[i]->Run();
+ }
+ }
+ }
+}
+
+bool ExtensionAccessibilityEventRouter::IsAccessibilityEnabled() const {
+ return enabled_;
+}
+
+void ExtensionAccessibilityEventRouter::AddOnEnabledListener(
+ Callback* callback) {
+ on_enabled_listeners_.push_back(callback);
+}
+
+void ExtensionAccessibilityEventRouter::AddOnDisabledListener(
+ Callback* callback) {
+ on_disabled_listeners_.push_back(callback);
+}
+
+void ExtensionAccessibilityEventRouter::OnWindowOpened(
+ const AccessibilityWindowInfo* info) {
+ std::string json_args = ControlInfoToJsonString(info);
+ DispatchEvent(info->profile(), keys::kOnWindowOpened, json_args);
+}
+
+void ExtensionAccessibilityEventRouter::OnWindowClosed(
+ const AccessibilityWindowInfo* info) {
+ std::string json_args = ControlInfoToJsonString(info);
+ DispatchEvent(info->profile(), keys::kOnWindowClosed, json_args);
+}
+
+void ExtensionAccessibilityEventRouter::OnControlFocused(
+ const AccessibilityControlInfo* info) {
+ last_focused_control_dict_.Clear();
+ info->SerializeToDict(&last_focused_control_dict_);
+ std::string json_args = ControlInfoToJsonString(info);
+ DispatchEvent(info->profile(), keys::kOnControlFocused, json_args);
+}
+
+void ExtensionAccessibilityEventRouter::OnControlAction(
+ const AccessibilityControlInfo* info) {
+ std::string json_args = ControlInfoToJsonString(info);
+ DispatchEvent(info->profile(), keys::kOnControlAction, json_args);
+}
+
+void ExtensionAccessibilityEventRouter::OnTextChanged(
+ const AccessibilityControlInfo* info) {
+ std::string json_args = ControlInfoToJsonString(info);
+ DispatchEvent(info->profile(), keys::kOnTextChanged, json_args);
+}
+
+void ExtensionAccessibilityEventRouter::DispatchEvent(
+ Profile* profile,
+ const char* event_name,
+ const std::string& json_args) {
+ if (enabled_ && profile && profile->GetExtensionMessageService()) {
+ profile->GetExtensionMessageService()->
+ DispatchEventToRenderers(event_name, json_args);
+ }
+}
+
+bool SetAccessibilityEnabledFunction::RunImpl() {
+ bool enabled;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsBoolean(&enabled));
+ ExtensionAccessibilityEventRouter::GetInstance()
+ ->SetAccessibilityEnabled(enabled);
+ return true;
+}
+
+bool GetFocusedControlFunction::RunImpl() {
+ // Get the serialized dict from the last focused control and return it.
+ // However, if the dict is empty, that means we haven't seen any focus
+ // events yet, so return null instead.
+ ExtensionAccessibilityEventRouter *accessibility_event_router =
+ ExtensionAccessibilityEventRouter::GetInstance();
+ DictionaryValue *last_focused_control_dict =
+ accessibility_event_router->last_focused_control_dict();
+ if (last_focused_control_dict->size()) {
+ result_.reset(last_focused_control_dict->DeepCopyWithoutEmptyChildren());
+ } else {
+ result_.reset(Value::CreateNullValue());
+ }
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_accessibility_api.h b/chrome/browser/extensions/extension_accessibility_api.h
new file mode 100644
index 0000000..afae039
--- /dev/null
+++ b/chrome/browser/extensions/extension_accessibility_api.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_H_
+
+#include <string>
+#include <vector>
+
+#include "base/singleton.h"
+#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/common/accessibility_events.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_registrar.h"
+
+// Observes the profile and routes accessibility notifications as events
+// to the extension system.
+class ExtensionAccessibilityEventRouter : public NotificationObserver {
+ public:
+ // Single instance of the event router.
+ static ExtensionAccessibilityEventRouter* GetInstance();
+
+ // Safe to call multiple times.
+ void ObserveProfile(Profile* profile);
+
+ // Get the dict representing the last control that received an
+ // OnControlFocus event.
+ DictionaryValue* last_focused_control_dict() {
+ return &last_focused_control_dict_;
+ }
+
+ // Accessibility support is disabled until an extension expicitly enables
+ // it, so that this extension api has no impact on Chrome's performance
+ // otherwise. These methods handle enabling, disabling, querying the
+ // status, and installing callbacks to execute when accessibility support
+ // is enabled or disabled.
+ void SetAccessibilityEnabled(bool enabled);
+ bool IsAccessibilityEnabled() const;
+ typedef Callback0::Type Callback;
+ void AddOnEnabledListener(Callback* callback);
+ void AddOnDisabledListener(Callback* callback);
+
+ private:
+ friend struct DefaultSingletonTraits<ExtensionAccessibilityEventRouter>;
+
+ ExtensionAccessibilityEventRouter()
+ : enabled_(false) {}
+ virtual ~ExtensionAccessibilityEventRouter() {}
+
+ // NotificationObserver::Observe.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ void OnWindowOpened(const AccessibilityWindowInfo* details);
+ void OnWindowClosed(const AccessibilityWindowInfo* details);
+ void OnControlFocused(const AccessibilityControlInfo* details);
+ void OnControlAction(const AccessibilityControlInfo* details);
+ void OnTextChanged(const AccessibilityControlInfo* details);
+
+ void DispatchEvent(Profile* profile,
+ const char* event_name,
+ const std::string& json_args);
+
+ // Used for tracking registrations to history service notifications.
+ NotificationRegistrar registrar_;
+
+ DictionaryValue last_focused_control_dict_;
+
+ bool enabled_;
+ std::vector<Callback*> on_enabled_listeners_;
+ std::vector<Callback*> on_disabled_listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionAccessibilityEventRouter);
+};
+
+// API function that enables or disables accessibility support. Event
+// listeners are only installed when accessibility support is enabled, to
+// minimize the impact.
+class SetAccessibilityEnabledFunction : public SyncExtensionFunction {
+ virtual ~SetAccessibilityEnabledFunction() {}
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME(
+ "experimental.accessibility.setAccessibilityEnabled")
+};
+
+// API function that returns the most recent focused control.
+class GetFocusedControlFunction : public SyncExtensionFunction {
+ virtual ~GetFocusedControlFunction() {}
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME(
+ "experimental.accessibility.getFocusedControl")
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_H_
diff --git a/chrome/browser/extensions/extension_accessibility_api_constants.cc b/chrome/browser/extensions/extension_accessibility_api_constants.cc
new file mode 100644
index 0000000..72d6138
--- /dev/null
+++ b/chrome/browser/extensions/extension_accessibility_api_constants.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_accessibility_api_constants.h"
+
+namespace extension_accessibility_api_constants {
+
+// String keys for AccessibilityObject properties.
+const wchar_t kTypeKey[] = L"type";
+const wchar_t kNameKey[] = L"name";
+const wchar_t kDetailsKey[] = L"details";
+const wchar_t kValueKey[] = L"details.value";
+const wchar_t kPasswordKey[] = L"details.isPassword";
+const wchar_t kItemCountKey[] = L"details.itemCount";
+const wchar_t kItemIndexKey[] = L"details.itemIndex";
+const wchar_t kSelectionStartKey[] = L"details.selectionStart";
+const wchar_t kSelectionEndKey[] = L"details.selectionEnd";
+const wchar_t kCheckedKey[] = L"details.isChecked";
+
+// Events.
+const char kOnWindowOpened[] = "experimental.accessibility.onWindowOpened";
+const char kOnWindowClosed[] = "experimental.accessibility.onWindowClosed";
+const char kOnControlFocused[] = "experimental.accessibility.onControlFocused";
+const char kOnControlAction[] = "experimental.accessibility.onControlAction";
+const char kOnTextChanged[] = "experimental.accessibility.onTextChanged";
+
+// Types of controls that can receive accessibility events.
+extern const char kTypeButton[] = "button";
+extern const char kTypeCheckbox[] = "checkbox";
+extern const char kTypeComboBox[] = "combobox";
+extern const char kTypeLink[] = "link";
+extern const char kTypeRadioButton[] = "radiobutton";
+extern const char kTypeTab[] = "tab";
+extern const char kTypeTextBox[] = "textbox";
+extern const char kTypeWindow[] = "window";
+
+} // namespace extension_accessibility_api_constants
diff --git a/chrome/browser/extensions/extension_accessibility_api_constants.h b/chrome/browser/extensions/extension_accessibility_api_constants.h
new file mode 100644
index 0000000..2020ec8
--- /dev/null
+++ b/chrome/browser/extensions/extension_accessibility_api_constants.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Constants used to for the Accessibility API.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_CONSTANTS_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_CONSTANTS_H_
+
+namespace extension_accessibility_api_constants {
+
+// Keys.
+extern const wchar_t kTypeKey[];
+extern const wchar_t kNameKey[];
+extern const wchar_t kDetailsKey[];
+extern const wchar_t kValueKey[];
+extern const wchar_t kPasswordKey[];
+extern const wchar_t kItemCountKey[];
+extern const wchar_t kItemIndexKey[];
+extern const wchar_t kSelectionStartKey[];
+extern const wchar_t kSelectionEndKey[];
+extern const wchar_t kCheckedKey[];
+
+// Events.
+extern const char kOnWindowOpened[];
+extern const char kOnWindowClosed[];
+extern const char kOnControlFocused[];
+extern const char kOnControlAction[];
+extern const char kOnTextChanged[];
+
+// Types of controls that can receive accessibility events
+extern const char kTypeButton[];
+extern const char kTypeCheckbox[];
+extern const char kTypeComboBox[];
+extern const char kTypeLink[];
+extern const char kTypeRadioButton[];
+extern const char kTypeTab[];
+extern const char kTypeTextBox[];
+extern const char kTypeWindow[];
+
+}; // namespace extension_accessibility_api_constants
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACCESSIBILITY_API_CONSTANTS_H_
diff --git a/chrome/browser/extensions/extension_accessibility_apitest.cc b/chrome/browser/extensions/extension_accessibility_apitest.cc
new file mode 100644
index 0000000..692dc9c
--- /dev/null
+++ b/chrome/browser/extensions/extension_accessibility_apitest.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+
+// This extension is currently only supported on Linux and Chrome OS.
+#if defined(OS_LINUX)
+#define MAYBE_Accessibility Accessibility
+#else
+#define MAYBE_Accessibility DISABLED_Accessibility
+#endif
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Accessibility) {
+ StartHTTPServer();
+ ASSERT_TRUE(RunExtensionTest("accessibility")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index bdba709..936d871 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/execute_code_in_tab_function.h"
+#include "chrome/browser/extensions/extension_accessibility_api.h"
#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_bookmarks_module_constants.h"
@@ -169,6 +170,10 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<ExtensionTestFailFunction>();
RegisterFunction<ExtensionTestLogFunction>();
RegisterFunction<ExtensionTestQuotaResetFunction>();
+
+ // Accessibility.
+ RegisterFunction<GetFocusedControlFunction>();
+ RegisterFunction<SetAccessibilityEnabledFunction>();
}
void FactoryRegistry::GetAllNames(std::vector<std::string>* names) {
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 0846dad..3834ed5 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_accessibility_api.h"
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_dom_ui.h"
@@ -164,6 +165,7 @@ void ExtensionsService::Init() {
// Start up the extension event routers.
ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_);
+ ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_);
LoadAllExtensions();