Home | History | Annotate | Download | only in extensions
      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.
     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*
     38     ExtensionAccessibilityEventRouter::GetInstance() {
     39   return Singleton<ExtensionAccessibilityEventRouter>::get();
     40 }
     41 
     42 ExtensionAccessibilityEventRouter::ExtensionAccessibilityEventRouter()
     43     : enabled_(false) {}
     44 
     45 ExtensionAccessibilityEventRouter::~ExtensionAccessibilityEventRouter() {
     46   STLDeleteElements(&on_enabled_listeners_);
     47   STLDeleteElements(&on_disabled_listeners_);
     48 }
     49 
     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 
     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 
    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 
    124 bool ExtensionAccessibilityEventRouter::IsAccessibilityEnabled() const {
    125   return enabled_;
    126 }
    127 
    128 void ExtensionAccessibilityEventRouter::AddOnEnabledListener(
    129     Callback* callback) {
    130   on_enabled_listeners_.push_back(callback);
    131 }
    132 
    133 void ExtensionAccessibilityEventRouter::AddOnDisabledListener(
    134     Callback* callback) {
    135   on_disabled_listeners_.push_back(callback);
    136 }
    137 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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