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