Chromium Code Reviews| Index: chrome/browser/extensions/api/automation_internal/automation_event_router.cc |
| diff --git a/chrome/browser/extensions/api/automation_internal/automation_event_router.cc b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..19045ae1aa3928a3896bf80131c1e83fcbd4cbbf |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc |
| @@ -0,0 +1,139 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/extensions/api/automation_internal/automation_event_router.h" |
| + |
| +#include <algorithm> |
| +#include <string> |
| +#include <utility> |
| + |
| +#include "base/stl_util.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/accessibility/ax_tree_id_registry.h" |
| +#include "chrome/common/extensions/api/automation_internal.h" |
| +#include "chrome/common/extensions/chrome_extension_messages.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/notification_source.h" |
| +#include "content/public/browser/notification_types.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "extensions/browser/event_router.h" |
| +#include "ui/accessibility/ax_enums.h" |
| +#include "ui/accessibility/ax_node_data.h" |
| + |
| +namespace extensions { |
| + |
| +// static |
| +AutomationEventRouter* AutomationEventRouter::GetInstance() { |
| + return Singleton<AutomationEventRouter, |
| + LeakySingletonTraits<AutomationEventRouter>>::get(); |
| +} |
| + |
| +AutomationEventRouter::AutomationEventRouter() { |
| + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + content::NotificationService::AllBrowserContextsAndSources()); |
| + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| + content::NotificationService::AllBrowserContextsAndSources()); |
| +} |
| + |
| +AutomationEventRouter::~AutomationEventRouter() { |
| +} |
| + |
| +void AutomationEventRouter::RegisterListenerForOneTree( |
| + int listener_process_id, |
| + int listener_routing_id, |
| + int source_ax_tree_id) { |
| + Register(listener_process_id, listener_routing_id, source_ax_tree_id, false); |
| +} |
| + |
| +void AutomationEventRouter::RegisterListenerWithDesktopPermission( |
| + int listener_process_id, |
| + int listener_routing_id) { |
| + Register(listener_process_id, listener_routing_id, 0, true); |
| +} |
| + |
| +void AutomationEventRouter::DispatchAccessibilityEvent( |
| + const ExtensionMsg_AccessibilityEventParams& params) { |
| + for (const auto& listener : listeners_) { |
| + if (!listener.desktop && |
| + listener.tree_ids.find(params.tree_id) == listener.tree_ids.end()) { |
| + continue; |
| + } |
| + |
| + content::RenderProcessHost* rph = |
| + content::RenderProcessHost::FromID(listener.process_id); |
| + rph->Send(new ExtensionMsg_AccessibilityEvent(listener.routing_id, params)); |
| + } |
| +} |
| + |
| +void AutomationEventRouter::DispatchTreeDestroyedEvent( |
| + int tree_id, |
| + content::BrowserContext* browser_context) { |
| + std::string event_name( |
| + api::automation_internal::OnAccessibilityTreeDestroyed::kEventName); |
| + scoped_ptr<base::ListValue> args( |
| + api::automation_internal::OnAccessibilityTreeDestroyed::Create(tree_id)); |
| + scoped_ptr<Event> event(new Event(event_name, args.Pass())); |
| + event->restrict_to_browser_context = browser_context; |
| + EventRouter::Get(browser_context)->BroadcastEvent(event.Pass()); |
| +} |
| + |
| +AutomationEventRouter::AutomationListener::AutomationListener() { |
| +} |
| + |
| +AutomationEventRouter::AutomationListener::~AutomationListener() { |
| +} |
| + |
| +void AutomationEventRouter::Register( |
| + int listener_process_id, |
| + int listener_routing_id, |
| + int ax_tree_id, |
| + bool desktop) { |
| + auto iter = std::find_if( |
| + listeners_.begin(), |
| + listeners_.end(), |
| + [listener_process_id, listener_routing_id](AutomationListener& item) { |
| + return (item.process_id == listener_process_id && |
| + item.routing_id == listener_routing_id); |
| + }); |
| + |
| + // Add a new entry if we don't have one with that process and routing id. |
| + if (iter == listeners_.end()) { |
| + AutomationListener listener; |
| + listener.routing_id = listener_routing_id; |
| + listener.process_id = listener_process_id; |
| + listener.desktop = desktop; |
| + listener.tree_ids.insert(ax_tree_id); |
| + listeners_.push_back(listener); |
| + return; |
| + } |
| + |
| + // We have an entry with that process and routing id, so update the set of |
| + // tree ids it wants to listen to, and update its desktop permission. |
| + iter->tree_ids.insert(ax_tree_id); |
| + if (desktop) |
| + iter->desktop = true; |
| +} |
| + |
| +void AutomationEventRouter::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + if (type != content::NOTIFICATION_RENDERER_PROCESS_TERMINATED && |
| + type != content::NOTIFICATION_RENDERER_PROCESS_CLOSED) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + content::RenderProcessHost* rph = |
| + content::Source<content::RenderProcessHost>(source).ptr(); |
| + int process_id = rph->GetID(); |
| + std::remove_if( |
| + listeners_.begin(), |
| + listeners_.end(), |
| + [=](AutomationListener& item) { |
|
dcheng
2015/06/08 18:07:05
This lambda is using default capture too
dmazzoni
2015/06/08 18:45:57
Done.
|
| + return item.process_id = process_id; |
| + }); |
| +} |
| + |
| +} // namespace extensions |