This source file includes following definitions.
- DispatchEvent
- AccessibilityEventReceived
- AddNodeData
- RunImpl
- RunImpl
#include "chrome/browser/extensions/api/automation_internal/automation_internal_api.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/automation_internal.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_thread.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 "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_system.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_node_data.h"
namespace extensions {
class AutomationWebContentsObserver;
}
DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::AutomationWebContentsObserver);
namespace extensions {
using ui::AXNodeData;
namespace {
void DispatchEvent(content::BrowserContext* context,
const std::string& event_name,
scoped_ptr<base::ListValue> args) {
if (context && extensions::ExtensionSystem::Get(context)->event_router()) {
scoped_ptr<Event> event(new Event(event_name, args.Pass()));
event->restrict_to_browser_context = context;
ExtensionSystem::Get(context)->event_router()->BroadcastEvent(event.Pass());
}
}
}
class AutomationWebContentsObserver
: public content::WebContentsObserver,
public content::WebContentsUserData<AutomationWebContentsObserver> {
public:
virtual ~AutomationWebContentsObserver() {}
virtual void AccessibilityEventReceived(
const std::vector<content::AXEventNotificationDetails>& details)
OVERRIDE {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAutomationAPI)) {
return;
}
std::vector<content::AXEventNotificationDetails>::const_iterator iter =
details.begin();
for (; iter != details.end(); iter++) {
scoped_ptr<base::ListValue> args(new base::ListValue());
const content::AXEventNotificationDetails& event = *iter;
int process_id = event.process_id;
int routing_id = event.routing_id;
base::DictionaryValue* axTreeUpdate = new base::DictionaryValue();
axTreeUpdate->Set("processID",
base::Value::CreateIntegerValue(process_id));
axTreeUpdate->Set("routingID",
base::Value::CreateIntegerValue(routing_id));
axTreeUpdate->SetString("eventType", ToString(iter->event_type));
base::ListValue* nodes = new base::ListValue();
axTreeUpdate->Set("nodes", nodes);
for (size_t i = 0; i < event.nodes.size(); i++) {
const ui::AXNodeData& node = event.nodes[i];
AddNodeData(node, nodes);
}
args->Append(axTreeUpdate);
DispatchEvent(browser_context_,
api::automation_internal::OnAccessibilityEvent::kEventName,
args.Pass());
}
return;
}
private:
friend class content::WebContentsUserData<AutomationWebContentsObserver>;
AutomationWebContentsObserver(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
browser_context_(web_contents->GetBrowserContext()) {}
void AddNodeData(const ui::AXNodeData& node,
base::ListValue* nodes) {
base::DictionaryValue* axNodeData = new base::DictionaryValue();
axNodeData->SetInteger("id", node.id);
axNodeData->SetString("role", ToString(node.role));
base::DictionaryValue* state_dict = new base::DictionaryValue();
uint32 state_pos = 0, state_shifter = node.state;
while (state_shifter) {
if (state_shifter & 1)
state_dict->SetBoolean(ToString(static_cast<ui::AXState>(state_pos)),
true);
state_shifter = state_shifter >> 1;
state_pos++;
}
axNodeData->Set("state", state_dict);
if (!node.bool_attributes.empty()) {
base::DictionaryValue* bool_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.bool_attributes.size(); ++i) {
std::pair<ui::AXBoolAttribute, bool> attr = node.bool_attributes[i];
bool_attributes->SetBoolean(ToString(attr.first), attr.second);
}
axNodeData->Set("boolAttributes", bool_attributes);
}
if (!node.float_attributes.empty()) {
base::DictionaryValue* float_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.float_attributes.size(); ++i) {
std::pair<ui::AXFloatAttribute, float> attr = node.float_attributes[i];
float_attributes->SetDouble(ToString(attr.first), attr.second);
}
axNodeData->Set("floatAttributes", float_attributes);
}
if (!node.html_attributes.empty()) {
base::DictionaryValue* html_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.html_attributes.size(); ++i) {
std::pair<std::string, std::string> attr = node.html_attributes[i];
html_attributes->SetString(attr.first, attr.second);
}
axNodeData->Set("htmlAttributes", html_attributes);
}
if (!node.int_attributes.empty()) {
base::DictionaryValue* int_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.int_attributes.size(); ++i) {
std::pair<ui::AXIntAttribute, int> attr = node.int_attributes[i];
int_attributes->SetInteger(ToString(attr.first), attr.second);
}
axNodeData->Set("intAttributes", int_attributes);
}
if (!node.intlist_attributes.empty()) {
base::DictionaryValue* intlist_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.intlist_attributes.size(); ++i) {
std::pair<ui::AXIntListAttribute, std::vector<int32> > attr =
node.intlist_attributes[i];
base::ListValue* intlist = new base::ListValue();
for (size_t j = 0; j < attr.second.size(); j++)
intlist->AppendInteger(attr.second[j]);
intlist_attributes->Set(ToString(attr.first), intlist);
}
axNodeData->Set("intlistAttributes", intlist_attributes);
}
if (!node.string_attributes.empty()) {
base::DictionaryValue* string_attributes = new base::DictionaryValue();
for (size_t i = 0; i < node.string_attributes.size(); ++i) {
std::pair<ui::AXStringAttribute, std::string> attr =
node.string_attributes[i];
string_attributes->SetString(ToString(attr.first), attr.second);
}
axNodeData->Set("stringAttributes", string_attributes);
}
base::ListValue* child_ids = new base::ListValue();
for (size_t i = 0; i < node.child_ids.size(); ++i) {
child_ids->AppendInteger(node.child_ids[i]);
}
axNodeData->Set("childIDs", child_ids);
nodes->Append(axNodeData);
}
content::BrowserContext* browser_context_;
DISALLOW_COPY_AND_ASSIGN(AutomationWebContentsObserver);
};
bool AutomationInternalEnableCurrentTabFunction::RunImpl() {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAutomationAPI)) {
return false;
}
Browser* current_browser = GetCurrentBrowser();
TabStripModel* tab_strip = current_browser->tab_strip_model();
content::WebContents* contents =
tab_strip->GetWebContentsAt(tab_strip->active_index());
if (!contents)
return false;
content::RenderWidgetHost* rwh =
contents->GetRenderWidgetHostView()->GetRenderWidgetHost();
if (!rwh)
return false;
AutomationWebContentsObserver::CreateForWebContents(contents);
rwh->EnableTreeOnlyAccessibilityMode();
results_ = api::automation_internal::EnableCurrentTab::Results::Create(
rwh->GetProcess()->GetID(), rwh->GetRoutingID());
SendResponse(true);
return true;
}
bool AutomationInternalPerformActionFunction::RunImpl() {
using api::automation_internal::PerformAction::Params;
scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
content::RenderWidgetHost* rwh =
content::RenderWidgetHost::FromID(params->args.process_id,
params->args.routing_id);
switch (params->args.action_type) {
case api::automation_internal::ACTION_TYPE_DO_DEFAULT:
rwh->AccessibilityDoDefaultAction(params->args.automation_node_id);
break;
case api::automation_internal::ACTION_TYPE_FOCUS:
rwh->AccessibilitySetFocus(params->args.automation_node_id);
break;
case api::automation_internal::ACTION_TYPE_MAKE_VISIBLE:
rwh->AccessibilityScrollToMakeVisible(params->args.automation_node_id,
gfx::Rect());
break;
case api::automation_internal::ACTION_TYPE_SET_SELECTION: {
extensions::api::automation_internal::SetSelectionParams selection_params;
EXTENSION_FUNCTION_VALIDATE(
extensions::api::automation_internal::SetSelectionParams::Populate(
params->opt_args.additional_properties, &selection_params));
rwh->AccessibilitySetTextSelection(params->args.automation_node_id,
selection_params.start_index,
selection_params.end_index);
break;
}
default:
NOTREACHED();
}
return true;
}
}