Commit 45d40a76 authored by Randy Rossi's avatar Randy Rossi Committed by Commit Bot

More supporting classes for chromecast automation

Part of ongoing effort to get automation tree working
in chromecast.

PS 1 is baseline for copied files. Modifications on top
of that in PS >=2.

Bug: 73383411
Test: None
Change-Id: I30328354dd523f1dc5aadbf7eda708e6be4ba5d2
Reviewed-on: https://chromium-review.googlesource.com/1035447Reviewed-by: default avatarAlex Sakhartchouk <alexst@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Commit-Queue: Randy Rossi <rmrossi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555794}
parent 400d7711
...@@ -224,6 +224,8 @@ cast_source_set("browser") { ...@@ -224,6 +224,8 @@ cast_source_set("browser") {
"cast_web_view_extension.h", "cast_web_view_extension.h",
"extension_request_protocol_handler.cc", "extension_request_protocol_handler.cc",
"extension_request_protocol_handler.h", "extension_request_protocol_handler.h",
"extensions/api/automation_internal/automation_event_router.cc",
"extensions/api/automation_internal/automation_event_router.h",
"extensions/api/automation_internal/automation_internal_api.cc", "extensions/api/automation_internal/automation_internal_api.cc",
"extensions/api/automation_internal/automation_internal_api.h", "extensions/api/automation_internal/automation_internal_api.h",
"extensions/api/bookmarks/bookmarks_api.cc", "extensions/api/bookmarks/bookmarks_api.cc",
......
// 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 "chromecast/browser/extensions/api/automation_internal/automation_event_router.h"
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include "base/stl_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chromecast/common/extensions_api/automation_api_constants.h"
#include "chromecast/common/extensions_api/automation_internal.h"
#include "chromecast/common/extensions_api/cast_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 "extensions/common/extension.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
namespace extensions {
namespace cast {
// static
AutomationEventRouter* AutomationEventRouter::GetInstance() {
return base::Singleton<
AutomationEventRouter,
base::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(
const ExtensionId& extension_id,
int listener_process_id,
int source_ax_tree_id) {
Register(extension_id, listener_process_id, source_ax_tree_id, false);
}
void AutomationEventRouter::RegisterListenerWithDesktopPermission(
const ExtensionId& extension_id,
int listener_process_id) {
Register(extension_id, listener_process_id,
::extensions::api::automation::kDesktopTreeID, true);
}
void AutomationEventRouter::DispatchAccessibilityEvents(
const std::vector<ExtensionMsg_AccessibilityEventParams>& events) {
if (events.empty())
return;
for (const auto& listener : listeners_) {
// Skip listeners that don't want to listen to this tree.
if (!listener.desktop &&
listener.tree_ids.find(events[0].tree_id) == listener.tree_ids.end()) {
continue;
}
content::RenderProcessHost* rph =
content::RenderProcessHost::FromID(listener.process_id);
rph->Send(new ExtensionMsg_AccessibilityEvents(events, true));
}
}
void AutomationEventRouter::DispatchAccessibilityLocationChange(
const ExtensionMsg_AccessibilityLocationChangeParams& params) {
for (const auto& listener : listeners_) {
// Skip listeners that don't want to listen to this tree.
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_AccessibilityLocationChange(params));
}
}
void AutomationEventRouter::DispatchTreeDestroyedEvent(
int tree_id,
content::BrowserContext* browser_context) {
if (listeners_.empty())
return;
std::unique_ptr<base::ListValue> args(
api::automation_internal::OnAccessibilityTreeDestroyed::Create(tree_id));
auto event = std::make_unique<Event>(
events::AUTOMATION_INTERNAL_ON_ACCESSIBILITY_TREE_DESTROYED,
api::automation_internal::OnAccessibilityTreeDestroyed::kEventName,
std::move(args), browser_context);
EventRouter::Get(browser_context)->BroadcastEvent(std::move(event));
}
AutomationEventRouter::AutomationListener::AutomationListener() {}
AutomationEventRouter::AutomationListener::AutomationListener(
const AutomationListener& other) = default;
AutomationEventRouter::AutomationListener::~AutomationListener() {}
void AutomationEventRouter::Register(const ExtensionId& extension_id,
int listener_process_id,
int ax_tree_id,
bool desktop) {
auto iter =
std::find_if(listeners_.begin(), listeners_.end(),
[listener_process_id](const AutomationListener& item) {
return item.process_id == listener_process_id;
});
// Add a new entry if we don't have one with that process.
if (iter == listeners_.end()) {
AutomationListener listener;
listener.extension_id = extension_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 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();
listeners_.erase(std::remove_if(listeners_.begin(), listeners_.end(),
[process_id](const AutomationListener& item) {
return item.process_id == process_id;
}),
listeners_.end());
}
} // namespace cast
} // namespace extensions
// 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.
#ifndef CHROMECAST_BROWSER_EXTENSIONS_API_AUTOMATION_INTERNAL_AUTOMATION_EVENT_ROUTER_H_
#define CHROMECAST_BROWSER_EXTENSIONS_API_AUTOMATION_INTERNAL_AUTOMATION_EVENT_ROUTER_H_
#include <set>
#include <vector>
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "chromecast/common/extensions_api/automation_internal.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/common/extension_id.h"
namespace content {
class BrowserContext;
} // namespace content
namespace ui {
struct AXActionData;
} // namespace ui
struct ExtensionMsg_AccessibilityEventParams;
struct ExtensionMsg_AccessibilityLocationChangeParams;
namespace extensions {
namespace cast {
struct AutomationListener;
class AutomationEventRouter : public content::NotificationObserver {
public:
static AutomationEventRouter* GetInstance();
// Indicates that the listener at |listener_process_id| wants to receive
// automation events from the accessibility tree indicated by
// |source_ax_tree_id|. Automation events are forwarded from now on until the
// listener process dies.
void RegisterListenerForOneTree(const ExtensionId& extension_id,
int listener_process_id,
int source_ax_tree_id);
// Indicates that the listener at |listener_process_id| wants to receive
// automation events from all accessibility trees because it has Desktop
// permission.
void RegisterListenerWithDesktopPermission(const ExtensionId& extension_id,
int listener_process_id);
void DispatchAccessibilityEvents(
const std::vector<ExtensionMsg_AccessibilityEventParams>& events);
void DispatchAccessibilityLocationChange(
const ExtensionMsg_AccessibilityLocationChangeParams& params);
// Notify all automation extensions that an accessibility tree was
// destroyed. If |browser_context| is null,
void DispatchTreeDestroyedEvent(int tree_id,
content::BrowserContext* browser_context);
private:
struct AutomationListener {
AutomationListener();
AutomationListener(const AutomationListener& other);
~AutomationListener();
ExtensionId extension_id;
int process_id;
bool desktop;
std::set<int> tree_ids;
};
AutomationEventRouter();
~AutomationEventRouter() override;
void Register(const ExtensionId& extension_id,
int listener_process_id,
int source_ax_tree_id,
bool desktop);
// content::NotificationObserver interface.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
content::NotificationRegistrar registrar_;
std::vector<AutomationListener> listeners_;
friend struct base::DefaultSingletonTraits<AutomationEventRouter>;
DISALLOW_COPY_AND_ASSIGN(AutomationEventRouter);
};
} // namespace cast
} // namespace extensions
#endif // CHROMECAST_BROWSER_EXTENSIONS_API_AUTOMATION_INTERNAL_AUTOMATION_EVENT_ROUTER_H_
...@@ -30,6 +30,8 @@ cast_source_set("common") { ...@@ -30,6 +30,8 @@ cast_source_set("common") {
sources += [ sources += [
"cast_extensions_client.cc", "cast_extensions_client.cc",
"cast_extensions_client.h", "cast_extensions_client.h",
"extensions_api/cast_extension_messages.cc",
"extensions_api/cast_extension_messages.h",
] ]
deps += [ deps += [
......
...@@ -5,6 +5,7 @@ include_rules = [ ...@@ -5,6 +5,7 @@ include_rules = [
"+extensions/grit", "+extensions/grit",
"+extensions/shell/common/api", "+extensions/shell/common/api",
"+extensions/shell/grit", "+extensions/shell/grit",
"+ui/accessibility",
"+ui/base", "+ui/base",
"+ui/gfx", "+ui/gfx",
] ]
per-file *_messages.cc=set noparent
per-file *_messages.cc=file://ipc/SECURITY_OWNERS
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
// Copyright (c) 2018 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.
//
// Get basic type definitions.
#define IPC_MESSAGE_IMPL
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
// Generate constructors.
#include "ipc/struct_constructor_macros.h"
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
// Generate destructors.
#include "ipc/struct_destructor_macros.h"
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
// Generate param traits write methods.
#include "ipc/param_traits_write_macros.h"
namespace IPC {
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
} // namespace IPC
// Generate param traits read methods.
#include "ipc/param_traits_read_macros.h"
namespace IPC {
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
} // namespace IPC
// Generate param traits log methods.
#include "ipc/param_traits_log_macros.h"
namespace IPC {
#undef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#include "chromecast/common/extensions_api/cast_extension_messages.h"
#include "content/public/common/common_param_traits.h"
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#error "Failed to include header chromecast/common/extensions_api/"
"chrome_extension_messages.h"
#endif
} // namespace IPC
// Copyright 2014 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.
#ifndef CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
#define CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
// Cast-specific IPC messages for extensions.
// Extension-related messages that aren't specific to Chromecast live in
// extensions/common/extension_messages.h.
#include <stdint.h>
#include <string>
#include "base/strings/string16.h"
#include "base/values.h"
#include "chromecast/common/extensions_api/automation_internal.h"
#include "extensions/common/stack_frame.h"
#include "ipc/ipc_message_macros.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_relative_bounds.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/gfx/transform.h"
#include "url/gurl.h"
#define IPC_MESSAGE_START ChromeExtensionMsgStart
// Messages sent from the browser to the renderer.
IPC_STRUCT_TRAITS_BEGIN(ui::AXNodeData)
IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(role)
IPC_STRUCT_TRAITS_MEMBER(state)
IPC_STRUCT_TRAITS_MEMBER(actions)
IPC_STRUCT_TRAITS_MEMBER(location)
IPC_STRUCT_TRAITS_MEMBER(transform)
IPC_STRUCT_TRAITS_MEMBER(string_attributes)
IPC_STRUCT_TRAITS_MEMBER(int_attributes)
IPC_STRUCT_TRAITS_MEMBER(float_attributes)
IPC_STRUCT_TRAITS_MEMBER(bool_attributes)
IPC_STRUCT_TRAITS_MEMBER(intlist_attributes)
IPC_STRUCT_TRAITS_MEMBER(stringlist_attributes)
IPC_STRUCT_TRAITS_MEMBER(html_attributes)
IPC_STRUCT_TRAITS_MEMBER(child_ids)
IPC_STRUCT_TRAITS_MEMBER(offset_container_id)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ui::AXTreeData)
IPC_STRUCT_TRAITS_MEMBER(tree_id)
IPC_STRUCT_TRAITS_MEMBER(parent_tree_id)
IPC_STRUCT_TRAITS_MEMBER(focused_tree_id)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(mimetype)
IPC_STRUCT_TRAITS_MEMBER(doctype)
IPC_STRUCT_TRAITS_MEMBER(loaded)
IPC_STRUCT_TRAITS_MEMBER(loading_progress)
IPC_STRUCT_TRAITS_MEMBER(focus_id)
IPC_STRUCT_TRAITS_MEMBER(sel_anchor_object_id)
IPC_STRUCT_TRAITS_MEMBER(sel_anchor_offset)
IPC_STRUCT_TRAITS_MEMBER(sel_anchor_affinity)
IPC_STRUCT_TRAITS_MEMBER(sel_focus_object_id)
IPC_STRUCT_TRAITS_MEMBER(sel_focus_offset)
IPC_STRUCT_TRAITS_MEMBER(sel_focus_affinity)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ui::AXTreeUpdate)
IPC_STRUCT_TRAITS_MEMBER(has_tree_data)
IPC_STRUCT_TRAITS_MEMBER(tree_data)
IPC_STRUCT_TRAITS_MEMBER(node_id_to_clear)
IPC_STRUCT_TRAITS_MEMBER(root_id)
IPC_STRUCT_TRAITS_MEMBER(nodes)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityEventParams)
// ID of the accessibility tree that this event applies to.
IPC_STRUCT_MEMBER(int, tree_id)
// The tree update.
IPC_STRUCT_MEMBER(ui::AXTreeUpdate, update)
// Type of event.
IPC_STRUCT_MEMBER(ax::mojom::Event, event_type)
// ID of the node that the event applies to.
IPC_STRUCT_MEMBER(int, id)
// The source of this event.
IPC_STRUCT_MEMBER(ax::mojom::EventFrom, event_from)
// The mouse location in screen coordinates.
IPC_STRUCT_MEMBER(gfx::Point, mouse_location)
// ID of the action request triggering this event.
IPC_STRUCT_MEMBER(int, action_request_id)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityLocationChangeParams)
// ID of the accessibility tree that this event applies to.
IPC_STRUCT_MEMBER(int, tree_id)
// ID of the object whose location is changing.
IPC_STRUCT_MEMBER(int, id)
// The object's new location info.
IPC_STRUCT_MEMBER(ui::AXRelativeBounds, new_location)
IPC_STRUCT_END()
// Forward an accessibility message to an extension process where an
// extension is using the automation API to listen for accessibility events.
IPC_MESSAGE_CONTROL2(
ExtensionMsg_AccessibilityEvents,
std::vector<ExtensionMsg_AccessibilityEventParams> /* events */,
bool /* is_active_profile */)
// Forward an accessibility location change message to an extension process
// where an extension is using the automation API to listen for
// accessibility events.
IPC_MESSAGE_CONTROL1(ExtensionMsg_AccessibilityLocationChange,
ExtensionMsg_AccessibilityLocationChangeParams)
#endif // CHROMECAST_COMMON_EXTENSIONS_API_CAST_EXTENSION_MESSAGES_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment