15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/accessibility/accessibility_extension_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/accessibility/accessibility_extension_api_constants.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/common/extensions/api/accessibility_private.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/infobars/core/confirm_infobar_delegate.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/infobars/core/infobar.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_accessibility_state.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/lazy_background_task_queue.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h"
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extension_accessibility_api_constants;
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace accessibility_private = extensions::api::accessibility_private;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the AccessibilityControlInfo serialized into a JSON string,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// consisting of an array of a single object of type AccessibilityObject,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as defined in the accessibility extension api's json schema.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::ListValue> ControlInfoToEventArguments(
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityEventInfo* info) {
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->SerializeToDict(dict);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(new base::ListValue());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->Append(dict);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return args.Pass();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAccessibilityEventRouter*
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAccessibilityEventRouter::GetInstance() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<ExtensionAccessibilityEventRouter>::get();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAccessibilityEventRouter::ExtensionAccessibilityEventRouter()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : enabled_(false) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAccessibilityEventRouter::~ExtensionAccessibilityEventRouter() {
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  control_event_callback_.Reset();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::SetAccessibilityEnabled(bool enabled) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enabled_ = enabled;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionAccessibilityEventRouter::IsAccessibilityEnabled() const {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return enabled_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::SetControlEventCallbackForTesting(
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ControlEventCallback control_event_callback) {
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(control_event_callback_.is_null());
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  control_event_callback_ = control_event_callback;
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::ClearControlEventCallback() {
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  control_event_callback_.Reset();
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::HandleWindowEvent(
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::AXEvent event,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityWindowInfo* info) {
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!control_event_callback_.is_null())
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    control_event_callback_.Run(event, info);
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (event == ui::AX_EVENT_ALERT)
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    OnWindowOpened(info);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::HandleMenuEvent(
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::AXEvent event,
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const AccessibilityMenuInfo* info) {
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (event) {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_MENU_START:
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_MENU_POPUP_START:
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      OnMenuOpened(info);
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_MENU_END:
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_MENU_POPUP_END:
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      OnMenuClosed(info);
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_FOCUS:
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OnControlFocused(info);
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ui::AX_EVENT_HOVER:
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      OnControlHover(info);
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::HandleControlEvent(
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::AXEvent event,
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const AccessibilityControlInfo* info) {
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!control_event_callback_.is_null())
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    control_event_callback_.Run(event, info);
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (event) {
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_TEXT_CHANGED:
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      OnTextChanged(info);
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_VALUE_CHANGED:
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_ALERT:
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      OnControlAction(info);
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ui::AX_EVENT_FOCUS:
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      OnControlFocused(info);
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ui::AX_EVENT_HOVER:
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      OnControlHover(info);
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NOTREACHED();
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnWindowOpened(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityWindowInfo* info) {
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnWindowOpened::kEventName,
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnControlFocused(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityControlInfo* info) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_focused_control_dict_.Clear();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->SerializeToDict(&last_focused_control_dict_);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnControlFocused::kEventName,
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnControlAction(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityControlInfo* info) {
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnControlAction::kEventName,
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnControlHover(
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AccessibilityControlInfo* info) {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DispatchEvent(info->profile(),
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                accessibility_private::OnControlHover::kEventName,
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                args.Pass());
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnTextChanged(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityControlInfo* info) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnTextChanged::kEventName,
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnMenuOpened(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityMenuInfo* info) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnMenuOpened::kEventName,
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::OnMenuClosed(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AccessibilityMenuInfo* info) {
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> args(ControlInfoToEventArguments(info));
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DispatchEvent(info->profile(),
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                accessibility_private::OnMenuClosed::kEventName,
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                args.Pass());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ExtensionAccessibilityEventRouter::OnChromeVoxLoadStateChanged(
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile,
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool loading,
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool make_announcements) {
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::ListValue> event_args(new base::ListValue());
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event_args->AppendBoolean(loading);
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event_args->AppendBoolean(make_announcements);
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionAccessibilityEventRouter::DispatchEventToChromeVox(
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      profile,
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      accessibility_private::OnChromeVoxLoadStateChanged::kEventName,
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_args.Pass());
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Static.
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ExtensionAccessibilityEventRouter::DispatchEventToChromeVox(
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile,
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char* event_name,
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::ListValue> event_args) {
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::ExtensionSystem* system =
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile);
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!system)
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(event_name,
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                            event_args.Pass()));
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  system->event_router()->DispatchEventWithLazyListener(
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_misc::kChromeVoxExtensionId, event.Pass());
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAccessibilityEventRouter::DispatchEvent(
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* event_name,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::ListValue> event_args) {
2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!enabled_ || !profile)
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!event_router)
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<extensions::Event> event(new extensions::Event(
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      event_name, event_args.Pass()));
2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  event_router->BroadcastEvent(event.Pass());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool AccessibilityPrivateSetAccessibilityEnabledFunction::RunSync() {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enabled;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAccessibilityEventRouter::GetInstance()
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ->SetAccessibilityEnabled(enabled);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool AccessibilityPrivateSetNativeAccessibilityEnabledFunction::RunSync() {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool enabled;
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enabled) {
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::BrowserAccessibilityState::GetInstance()->
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        EnableAccessibility();
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::BrowserAccessibilityState::GetInstance()->
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        DisableAccessibility();
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool AccessibilityPrivateGetFocusedControlFunction::RunSync() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the serialized dict from the last focused control and return it.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if the dict is empty, that means we haven't seen any focus
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events yet, so return null instead.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAccessibilityEventRouter *accessibility_event_router =
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionAccessibilityEventRouter::GetInstance();
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue *last_focused_control_dict =
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      accessibility_event_router->last_focused_control_dict();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_focused_control_dict->size()) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetResult(last_focused_control_dict->DeepCopyWithoutEmptyChildren());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetResult(base::Value::CreateNullValue());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool AccessibilityPrivateGetAlertsForTabFunction::RunSync() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_id;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabStripModel* tab_strip = NULL;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContents* contents = NULL;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_index = -1;
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!extensions::ExtensionTabUtil::GetTabById(tab_id,
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                GetProfile(),
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                include_incognito(),
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                NULL,
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                &tab_strip,
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                &contents,
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                &tab_index)) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_ = extensions::ErrorUtils::FormatErrorMessage(
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::tabs_constants::kTabNotFoundError,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::IntToString(tab_id));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* alerts_value = new base::ListValue;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
298a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  InfoBarService* infobar_service = InfoBarService::FromWebContents(contents);
299a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(hashimoto): Make other kind of alerts available.  crosbug.com/24281
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfirmInfoBarDelegate* confirm_infobar_delegate =
302a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        infobar_service->infobar_at(i)->delegate()->AsConfirmInfoBarDelegate();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (confirm_infobar_delegate) {
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::DictionaryValue* alert_value = new base::DictionaryValue;
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16 message_text =
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          confirm_infobar_delegate->GetMessageText();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alert_value->SetString(keys::kMessageKey, message_text);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alerts_value->Append(alert_value);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetResult(alerts_value);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AccessibilityPrivateSetFocusRingFunction::RunSync() {
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::ListValue* rect_values = NULL;
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &rect_values));
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<gfx::Rect> rects;
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < rect_values->GetSize(); ++i) {
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::DictionaryValue* rect_value = NULL;
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXTENSION_FUNCTION_VALIDATE(rect_values->GetDictionary(i, &rect_value));
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int left, top, width, height;
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kLeft, &left));
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kTop, &top));
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kWidth, &width));
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kHeight, &height));
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    rects.push_back(gfx::Rect(left, top, width, height));
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  chromeos::AccessibilityFocusRingController::GetInstance()->SetFocusRing(
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      rects);
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // defined(OS_CHROMEOS)
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  error_ = keys:: kErrorNotSupported;
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
341