diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-30 01:18:56 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-30 01:18:56 +0000 |
commit | 5cbe1e21980f42927d7d1c11cc860131be266e7e (patch) | |
tree | 3b52e15044336cb89e3004214b4714e6148e5ea9 /chrome/browser/extensions | |
parent | 7a12518454d36fb4ac79431f56106b38cd2482ab (diff) | |
download | chromium_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')
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(); |