10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// found in the LICENSE file.
40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/ui/ash/accessibility/automation_manager_ash.h"
60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <vector>
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/memory/singleton.h"
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/browser_process.h"
110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/extensions/api/automation_internal/automation_util.h"
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/profiles/profile_manager.h"
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/ax_event_notification_details.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/browser_context.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/accessibility/ax_aura_obj_cache.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/views/view.h"
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/views/widget/widget.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)using content::BrowserContext;
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// static
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AutomationManagerAsh* AutomationManagerAsh::GetInstance() {
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return Singleton<AutomationManagerAsh>::get();
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::Enable(BrowserContext* context) {
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  enabled_ = true;
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Reset();
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendEvent(context, current_tree_->GetRoot(), ui::AX_EVENT_LOAD_COMPLETE);
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::Disable() {
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  enabled_ = false;
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Reset the serializer to save memory.
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  current_tree_serializer_->Reset();
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::HandleEvent(BrowserContext* context,
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                         views::View* view,
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                         ui::AXEvent event_type) {
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!enabled_) {
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(dtseng): Events should only be delivered to extensions with the
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // desktop permission.
490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  views::Widget* widget = view->GetWidget();
500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!widget)
510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!context && g_browser_process->profile_manager()) {
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    context = g_browser_process->profile_manager()->GetLastUsedProfile();
550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!context) {
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LOG(WARNING) << "Accessibility notification but no browser context";
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  views::AXAuraObjWrapper* aura_obj =
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      views::AXAuraObjCache::GetInstance()->GetOrCreate(view);
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendEvent(context, aura_obj, event_type);
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::DoDefault(int32 id) {
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(enabled_);
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  current_tree_->DoDefault(id);
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::Focus(int32 id) {
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(enabled_);
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  current_tree_->Focus(id);
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::MakeVisible(int32 id) {
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(enabled_);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  current_tree_->MakeVisible(id);
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::SetSelection(int32 id, int32 start, int32 end) {
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(enabled_);
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  current_tree_->SetSelection(id, start, end);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AutomationManagerAsh::AutomationManagerAsh() : enabled_(false) {}
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AutomationManagerAsh::~AutomationManagerAsh() {}
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::Reset() {
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  current_tree_.reset(new AXTreeSourceAsh());
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  current_tree_serializer_.reset(
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new ui::AXTreeSerializer<views::AXAuraObjWrapper*>(
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          current_tree_.get()));
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AutomationManagerAsh::SendEvent(BrowserContext* context,
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       views::AXAuraObjWrapper* aura_obj,
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       ui::AXEvent event_type) {
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::AXTreeUpdate update;
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  current_tree_serializer_->SerializeChanges(aura_obj, &update);
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Route this event to special process/routing ids recognized by the
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Automation API as the desktop tree.
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(dtseng): Would idealy define these special desktop constants in idl.
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::AXEventNotificationDetails detail(update.node_id_to_clear,
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             update.nodes,
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             event_type,
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                             aura_obj->GetID(),
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             0, /* process_id */
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             0 /* routing_id */);
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::vector<content::AXEventNotificationDetails> details;
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  details.push_back(detail);
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::automation_util::DispatchAccessibilityEventsToAutomation(
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      details, context, gfx::Vector2d());
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
117