1 // Copyright 2015 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.
5 #include "chrome/browser/extensions/api/automation_internal/automation_event_router.h"
11 #include "base/stl_util.h"
12 #include "base/values.h"
13 #include "chrome/common/extensions/api/automation_internal.h"
14 #include "chrome/common/extensions/chrome_extension_messages.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/notification_source.h"
17 #include "content/public/browser/notification_types.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "extensions/browser/event_router.h"
20 #include "ui/accessibility/ax_enums.h"
21 #include "ui/accessibility/ax_node_data.h"
23 namespace extensions
{
26 AutomationEventRouter
* AutomationEventRouter::GetInstance() {
27 return base::Singleton
<
28 AutomationEventRouter
,
29 base::LeakySingletonTraits
<AutomationEventRouter
>>::get();
32 AutomationEventRouter::AutomationEventRouter() {
33 registrar_
.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
34 content::NotificationService::AllBrowserContextsAndSources());
35 registrar_
.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
36 content::NotificationService::AllBrowserContextsAndSources());
39 AutomationEventRouter::~AutomationEventRouter() {
42 void AutomationEventRouter::RegisterListenerForOneTree(
43 int listener_process_id
,
44 int listener_routing_id
,
45 int source_ax_tree_id
) {
46 Register(listener_process_id
, listener_routing_id
, source_ax_tree_id
, false);
49 void AutomationEventRouter::RegisterListenerWithDesktopPermission(
50 int listener_process_id
,
51 int listener_routing_id
) {
52 Register(listener_process_id
, listener_routing_id
, 0, true);
55 void AutomationEventRouter::DispatchAccessibilityEvent(
56 const ExtensionMsg_AccessibilityEventParams
& params
) {
57 for (const auto& listener
: listeners_
) {
58 if (!listener
.desktop
&&
59 listener
.tree_ids
.find(params
.tree_id
) == listener
.tree_ids
.end()) {
63 content::RenderProcessHost
* rph
=
64 content::RenderProcessHost::FromID(listener
.process_id
);
65 rph
->Send(new ExtensionMsg_AccessibilityEvent(listener
.routing_id
,
70 void AutomationEventRouter::DispatchTreeDestroyedEvent(
72 content::BrowserContext
* browser_context
) {
73 scoped_ptr
<base::ListValue
> args(
74 api::automation_internal::OnAccessibilityTreeDestroyed::Create(tree_id
));
75 scoped_ptr
<Event
> event(new Event(
76 events::AUTOMATION_INTERNAL_ON_ACCESSIBILITY_TREE_DESTROYED
,
77 api::automation_internal::OnAccessibilityTreeDestroyed::kEventName
,
79 event
->restrict_to_browser_context
= browser_context
;
80 EventRouter::Get(browser_context
)->BroadcastEvent(event
.Pass());
83 AutomationEventRouter::AutomationListener::AutomationListener() {
86 AutomationEventRouter::AutomationListener::~AutomationListener() {
89 void AutomationEventRouter::Register(
90 int listener_process_id
,
91 int listener_routing_id
,
94 auto iter
= std::find_if(
97 [listener_process_id
, listener_routing_id
](
98 const AutomationListener
& item
) {
99 return (item
.process_id
== listener_process_id
&&
100 item
.routing_id
== listener_routing_id
);
103 // Add a new entry if we don't have one with that process and routing id.
104 if (iter
== listeners_
.end()) {
105 AutomationListener listener
;
106 listener
.routing_id
= listener_routing_id
;
107 listener
.process_id
= listener_process_id
;
108 listener
.desktop
= desktop
;
109 listener
.tree_ids
.insert(ax_tree_id
);
110 listeners_
.push_back(listener
);
114 // We have an entry with that process and routing id, so update the set of
115 // tree ids it wants to listen to, and update its desktop permission.
116 iter
->tree_ids
.insert(ax_tree_id
);
118 iter
->desktop
= true;
121 void AutomationEventRouter::Observe(
123 const content::NotificationSource
& source
,
124 const content::NotificationDetails
& details
) {
125 if (type
!= content::NOTIFICATION_RENDERER_PROCESS_TERMINATED
&&
126 type
!= content::NOTIFICATION_RENDERER_PROCESS_CLOSED
) {
131 content::RenderProcessHost
* rph
=
132 content::Source
<content::RenderProcessHost
>(source
).ptr();
133 int process_id
= rph
->GetID();
138 [process_id
](const AutomationListener
& item
) {
139 return item
.process_id
== process_id
;
144 } // namespace extensions