Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1388)

Unified Diff: chrome/browser/extensions/api/automation_internal/automation_event_router.cc

Issue 1151523009: Forward accessibility events to the automation extension process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@step1
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..019d365d26b621bc8931d2f5afe0744d3f33136f
--- /dev/null
+++ b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
@@ -0,0 +1,132 @@
+// 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 <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 {
+
+struct AutomationListener {
+ int routing_id;
+ int process_id;
+ bool desktop;
+ std::set<int> tree_ids;
+};
+
+// 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() {
+ STLDeleteContainerPairSecondPointers(listener_map_.begin(),
+ listener_map_.end());
+}
+
+void AutomationEventRouter::AddListener(
+ ExtensionId extension_id,
+ int ax_tree_id,
+ int process_id,
+ int routing_id,
+ bool desktop) {
+ auto iter = listener_map_.find(extension_id);
+ AutomationListener* listener;
not at google - send to devlin 2015/06/02 23:59:24 it's nice to initialize pointers to nullptr
dmazzoni 2015/06/04 20:07:39 Done.
+ if (iter != listener_map_.end()) {
+ listener = iter->second;
not at google - send to devlin 2015/06/02 23:59:24 What happens if the listener that is already there
dmazzoni 2015/06/04 20:07:39 OK, I tried to clarify it. I realized it was a mis
+ } else {
+ listener = new AutomationListener();
+ listener->routing_id = routing_id;
+ listener->process_id = process_id;
+ listener->desktop = desktop;
+ listener_map_.insert(std::make_pair(extension_id, listener));
not at google - send to devlin 2015/06/02 23:59:24 I would have thought that listener_map_[extension_
dmazzoni 2015/06/04 20:07:39 Doesn't compile, but moot as I simplified it.
+ }
+ listener->tree_ids.insert(ax_tree_id);
+}
+
+void AutomationEventRouter::DispatchAccessibilityEventToAutomation(
+ const ExtensionMsg_AccessibilityEventParams& params) {
+ for (auto iter = listener_map_.begin();
+ iter != listener_map_.end();
+ ++iter) {
not at google - send to devlin 2015/06/02 23:59:24 You can use a range-based for loop here, I think?
dmazzoni 2015/06/04 20:07:39 Done.
+ AutomationListener* listener = iter->second;
+ 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::DispatchTreeDestroyedEventToAutomation(
+ int process_id,
+ int routing_id,
+ content::BrowserContext* browser_context) {
+ int tree_id = AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(
+ process_id, routing_id);
+
+ std::string event_name(
+ api::automation_internal::OnAccessibilityTreeDestroyed::kEventName);
+ scoped_ptr<base::ListValue> args(
+ api::automation_internal::OnAccessibilityTreeDestroyed::Create(tree_id));
+ if (browser_context && EventRouter::Get(browser_context)) {
not at google - send to devlin 2015/06/02 23:59:24 Checking for |browser_context| here implies it can
dmazzoni 2015/06/04 20:07:39 Hmmm, I can't see a good reason why. The caller sh
+ scoped_ptr<Event> event(new Event(event_name, args.Pass()));
+ event->restrict_to_browser_context = browser_context;
+ EventRouter::Get(browser_context)->BroadcastEvent(event.Pass());
+ }
+ AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(tree_id);
+}
+
+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();
+
+ auto iter = listener_map_.begin();
+ while (iter != listener_map_.end()) {
+ auto temp = iter;
not at google - send to devlin 2015/06/02 23:59:24 apologies for nit, but for what it's worth I've mo
dmazzoni 2015/06/04 20:07:39 Thanks, that's cleaner.
+ iter++;
+ if (temp->second->process_id == process_id) {
+ delete temp->second;
+ listener_map_.erase(temp);
+ }
+ }
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698