extension_accessibility_api.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/extension_tabs_module.h" 6 7#include "base/json/json_writer.h" 8#include "base/stl_util-inl.h" 9#include "base/string_util.h" 10#include "base/values.h" 11#include "chrome/browser/browser_list.h" 12#include "chrome/browser/browser_window.h" 13#include "chrome/browser/extensions/extension_accessibility_api.h" 14#include "chrome/browser/extensions/extension_accessibility_api_constants.h" 15#include "chrome/browser/extensions/extension_event_router.h" 16#include "chrome/browser/extensions/extension_function_dispatcher.h" 17#include "chrome/browser/extensions/extension_service.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/ui/browser.h" 20#include "chrome/common/extensions/extension.h" 21#include "chrome/common/notification_service.h" 22 23namespace keys = extension_accessibility_api_constants; 24 25// Returns the AccessibilityControlInfo serialized into a JSON string, 26// consisting of an array of a single object of type AccessibilityObject, 27// as defined in the accessibility extension api's json schema. 28std::string ControlInfoToJsonString(const AccessibilityControlInfo* info) { 29 ListValue args; 30 DictionaryValue* dict = new DictionaryValue(); 31 info->SerializeToDict(dict); 32 args.Append(dict); 33 std::string json_args; 34 base::JSONWriter::Write(&args, false, &json_args); 35 return json_args; 36} 37 38ExtensionAccessibilityEventRouter* 39 ExtensionAccessibilityEventRouter::GetInstance() { 40 return Singleton<ExtensionAccessibilityEventRouter>::get(); 41} 42 43ExtensionAccessibilityEventRouter::ExtensionAccessibilityEventRouter() 44 : enabled_(false) {} 45 46ExtensionAccessibilityEventRouter::~ExtensionAccessibilityEventRouter() { 47 STLDeleteElements(&on_enabled_listeners_); 48 STLDeleteElements(&on_disabled_listeners_); 49} 50 51void ExtensionAccessibilityEventRouter::ObserveProfile(Profile* profile) { 52 last_focused_control_dict_.Clear(); 53 54 if (registrar_.IsEmpty()) { 55 registrar_.Add(this, 56 NotificationType::ACCESSIBILITY_WINDOW_OPENED, 57 NotificationService::AllSources()); 58 registrar_.Add(this, 59 NotificationType::ACCESSIBILITY_WINDOW_CLOSED, 60 NotificationService::AllSources()); 61 registrar_.Add(this, 62 NotificationType::ACCESSIBILITY_CONTROL_FOCUSED, 63 NotificationService::AllSources()); 64 registrar_.Add(this, 65 NotificationType::ACCESSIBILITY_CONTROL_ACTION, 66 NotificationService::AllSources()); 67 registrar_.Add(this, 68 NotificationType::ACCESSIBILITY_TEXT_CHANGED, 69 NotificationService::AllSources()); 70 registrar_.Add(this, 71 NotificationType::ACCESSIBILITY_MENU_OPENED, 72 NotificationService::AllSources()); 73 registrar_.Add(this, 74 NotificationType::ACCESSIBILITY_MENU_CLOSED, 75 NotificationService::AllSources()); 76 } 77} 78 79void ExtensionAccessibilityEventRouter::Observe( 80 NotificationType type, 81 const NotificationSource& source, 82 const NotificationDetails& details) { 83 switch (type.value) { 84 case NotificationType::ACCESSIBILITY_WINDOW_OPENED: 85 OnWindowOpened(Details<const AccessibilityWindowInfo>(details).ptr()); 86 break; 87 case NotificationType::ACCESSIBILITY_WINDOW_CLOSED: 88 OnWindowClosed(Details<const AccessibilityWindowInfo>(details).ptr()); 89 break; 90 case NotificationType::ACCESSIBILITY_CONTROL_FOCUSED: 91 OnControlFocused(Details<const AccessibilityControlInfo>(details).ptr()); 92 break; 93 case NotificationType::ACCESSIBILITY_CONTROL_ACTION: 94 OnControlAction(Details<const AccessibilityControlInfo>(details).ptr()); 95 break; 96 case NotificationType::ACCESSIBILITY_TEXT_CHANGED: 97 OnTextChanged(Details<const AccessibilityControlInfo>(details).ptr()); 98 break; 99 case NotificationType::ACCESSIBILITY_MENU_OPENED: 100 OnMenuOpened(Details<const AccessibilityMenuInfo>(details).ptr()); 101 break; 102 case NotificationType::ACCESSIBILITY_MENU_CLOSED: 103 OnMenuClosed(Details<const AccessibilityMenuInfo>(details).ptr()); 104 break; 105 default: 106 NOTREACHED(); 107 } 108} 109 110void ExtensionAccessibilityEventRouter::SetAccessibilityEnabled(bool enabled) { 111 if (enabled_ != enabled) { 112 enabled_ = enabled; 113 if (enabled_) { 114 for (unsigned int i = 0; i < on_enabled_listeners_.size(); i++) { 115 on_enabled_listeners_[i]->Run(); 116 } 117 } else { 118 for (unsigned int i = 0; i < on_disabled_listeners_.size(); i++) { 119 on_disabled_listeners_[i]->Run(); 120 } 121 } 122 } 123} 124 125bool ExtensionAccessibilityEventRouter::IsAccessibilityEnabled() const { 126 return enabled_; 127} 128 129void ExtensionAccessibilityEventRouter::AddOnEnabledListener( 130 Callback* callback) { 131 on_enabled_listeners_.push_back(callback); 132} 133 134void ExtensionAccessibilityEventRouter::AddOnDisabledListener( 135 Callback* callback) { 136 on_disabled_listeners_.push_back(callback); 137} 138 139void ExtensionAccessibilityEventRouter::OnWindowOpened( 140 const AccessibilityWindowInfo* info) { 141 std::string json_args = ControlInfoToJsonString(info); 142 DispatchEvent(info->profile(), keys::kOnWindowOpened, json_args); 143} 144 145void ExtensionAccessibilityEventRouter::OnWindowClosed( 146 const AccessibilityWindowInfo* info) { 147 std::string json_args = ControlInfoToJsonString(info); 148 DispatchEvent(info->profile(), keys::kOnWindowClosed, json_args); 149} 150 151void ExtensionAccessibilityEventRouter::OnControlFocused( 152 const AccessibilityControlInfo* info) { 153 last_focused_control_dict_.Clear(); 154 info->SerializeToDict(&last_focused_control_dict_); 155 std::string json_args = ControlInfoToJsonString(info); 156 DispatchEvent(info->profile(), keys::kOnControlFocused, json_args); 157} 158 159void ExtensionAccessibilityEventRouter::OnControlAction( 160 const AccessibilityControlInfo* info) { 161 std::string json_args = ControlInfoToJsonString(info); 162 DispatchEvent(info->profile(), keys::kOnControlAction, json_args); 163} 164 165void ExtensionAccessibilityEventRouter::OnTextChanged( 166 const AccessibilityControlInfo* info) { 167 std::string json_args = ControlInfoToJsonString(info); 168 DispatchEvent(info->profile(), keys::kOnTextChanged, json_args); 169} 170 171void ExtensionAccessibilityEventRouter::OnMenuOpened( 172 const AccessibilityMenuInfo* info) { 173 std::string json_args = ControlInfoToJsonString(info); 174 DispatchEvent(info->profile(), keys::kOnMenuOpened, json_args); 175} 176 177void ExtensionAccessibilityEventRouter::OnMenuClosed( 178 const AccessibilityMenuInfo* info) { 179 std::string json_args = ControlInfoToJsonString(info); 180 DispatchEvent(info->profile(), keys::kOnMenuClosed, json_args); 181} 182 183void ExtensionAccessibilityEventRouter::DispatchEvent( 184 Profile* profile, 185 const char* event_name, 186 const std::string& json_args) { 187 if (enabled_ && profile && profile->GetExtensionEventRouter()) { 188 profile->GetExtensionEventRouter()->DispatchEventToRenderers( 189 event_name, json_args, NULL, GURL()); 190 } 191} 192 193bool SetAccessibilityEnabledFunction::RunImpl() { 194 bool enabled; 195 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled)); 196 ExtensionAccessibilityEventRouter::GetInstance() 197 ->SetAccessibilityEnabled(enabled); 198 return true; 199} 200 201bool GetFocusedControlFunction::RunImpl() { 202 // Get the serialized dict from the last focused control and return it. 203 // However, if the dict is empty, that means we haven't seen any focus 204 // events yet, so return null instead. 205 ExtensionAccessibilityEventRouter *accessibility_event_router = 206 ExtensionAccessibilityEventRouter::GetInstance(); 207 DictionaryValue *last_focused_control_dict = 208 accessibility_event_router->last_focused_control_dict(); 209 if (last_focused_control_dict->size()) { 210 result_.reset(last_focused_control_dict->DeepCopyWithoutEmptyChildren()); 211 } else { 212 result_.reset(Value::CreateNullValue()); 213 } 214 return true; 215} 216