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

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

Issue 655273005: Implement AutomationNode.querySelector(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Use assertEq instead of assertTrue in testQuerySelectorFromRemovedNode() Created 6 years, 2 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_internal_api.cc
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 40e184bbf3b64d5776b523af8abb94ca9feb063d..e23b7efada896317c510991dbfe27307574ae1c6 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/api/automation_internal/automation_action_adapter.h"
#include "chrome/browser/extensions/api/automation_internal/automation_util.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
@@ -19,9 +20,11 @@
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/render_frame_host.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_view.h"
#include "content/public/browser/web_contents.h"
+#include "extensions/common/extension_messages.h"
#include "extensions/common/permissions/permissions_data.h"
#if defined(OS_CHROMEOS)
@@ -34,6 +37,8 @@ class AutomationWebContentsObserver;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::AutomationWebContentsObserver);
+namespace extensions {
+
namespace {
const int kDesktopProcessID = 0;
const int kDesktopRoutingID = 0;
@@ -41,9 +46,65 @@ const int kDesktopRoutingID = 0;
const char kCannotRequestAutomationOnPage[] =
"Cannot request automation tree on url \"*\". "
"Extension manifest must request permission to access this host.";
-} // namespace
+const char kRendererDestroyed[] = "The tab was closed.";
-namespace extensions {
+// Handles sending and receiving IPCs for a single querySelector request. On
+// creation, sends the request IPC, and is destroyed either when the response is
+// received or the renderer is destroyed.
+class QuerySelectorHandler : public content::WebContentsObserver {
+ public:
+ QuerySelectorHandler(
+ content::WebContents* web_contents,
+ int request_id,
+ int acc_obj_id,
+ const base::string16& query,
+ const extensions::AutomationInternalQuerySelectorFunction::Callback&
+ callback)
+ : content::WebContentsObserver(web_contents),
+ request_id_(request_id),
+ callback_(callback) {
+ content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
+ rvh->Send(new ExtensionMsg_AutomationQuerySelector(
+ rvh->GetRoutingID(), request_id, acc_obj_id, query));
+ }
+
+ ~QuerySelectorHandler() override {}
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ if (message.type() != ExtensionHostMsg_AutomationQuerySelector_Result::ID)
+ return false;
+
+ // There may be several requests in flight; check this response matches.
+ int message_request_id = 0;
+ PickleIterator iter(message);
+ CHECK(message.ReadInt(&iter, &message_request_id));
+
+ if (message_request_id != request_id_)
+ return false;
+
+ IPC_BEGIN_MESSAGE_MAP(QuerySelectorHandler, message)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_AutomationQuerySelector_Result,
+ OnQueryResponse)
+ IPC_END_MESSAGE_MAP()
+ return true;
+ }
+
+ void WebContentsDestroyed() override {
+ callback_.Run(kRendererDestroyed, 0);
+ delete this;
+ }
+
+ private:
+ void OnQueryResponse(int request_id,
+ const std::string& error,
+ int result_acc_obj_id) {
+ callback_.Run(error, result_acc_obj_id);
+ delete this;
+ }
+
+ int request_id_;
+ const extensions::AutomationInternalQuerySelectorFunction::Callback callback_;
+};
bool CanRequestAutomation(const Extension* extension,
const AutomationInfo* automation_info,
@@ -64,6 +125,35 @@ bool CanRequestAutomation(const Extension* extension,
extension, url, url, tab_id, process_id, &unused_error);
}
+// Helper class that implements an action adapter for a |RenderFrameHost|.
+class RenderFrameHostActionAdapter : public AutomationActionAdapter {
+ public:
+ explicit RenderFrameHostActionAdapter(content::RenderFrameHost* rfh)
+ : rfh_(rfh) {}
+
+ virtual ~RenderFrameHostActionAdapter() {}
+
+ // AutomationActionAdapter implementation.
+ void DoDefault(int32 id) override { rfh_->AccessibilityDoDefaultAction(id); }
+
+ void Focus(int32 id) override { rfh_->AccessibilitySetFocus(id); }
+
+ void MakeVisible(int32 id) override {
+ rfh_->AccessibilityScrollToMakeVisible(id, gfx::Rect());
+ }
+
+ void SetSelection(int32 id, int32 start, int32 end) override {
+ rfh_->AccessibilitySetTextSelection(id, start, end);
+ }
+
+ private:
+ content::RenderFrameHost* rfh_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostActionAdapter);
+};
+
+} // namespace
+
// Helper class that receives accessibility data from |WebContents|.
class AutomationWebContentsObserver
: public content::WebContentsObserver,
@@ -101,33 +191,6 @@ class AutomationWebContentsObserver
DISALLOW_COPY_AND_ASSIGN(AutomationWebContentsObserver);
};
-// Helper class that implements an action adapter for a |RenderFrameHost|.
-class RenderFrameHostActionAdapter : public AutomationActionAdapter {
- public:
- explicit RenderFrameHostActionAdapter(content::RenderFrameHost* rfh)
- : rfh_(rfh) {}
-
- virtual ~RenderFrameHostActionAdapter() {}
-
- // AutomationActionAdapter implementation.
- void DoDefault(int32 id) override { rfh_->AccessibilityDoDefaultAction(id); }
-
- void Focus(int32 id) override { rfh_->AccessibilitySetFocus(id); }
-
- void MakeVisible(int32 id) override {
- rfh_->AccessibilityScrollToMakeVisible(id, gfx::Rect());
- }
-
- void SetSelection(int32 id, int32 start, int32 end) override {
- rfh_->AccessibilitySetTextSelection(id, start, end);
- }
-
- private:
- content::RenderFrameHost* rfh_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderFrameHostActionAdapter);
-};
-
ExtensionFunction::ResponseAction
AutomationInternalEnableTabFunction::Run() {
const AutomationInfo* automation_info = AutomationInfo::Get(extension());
@@ -167,7 +230,7 @@ AutomationInternalEnableTabFunction::Run() {
return RespondNow(
ArgumentList(api::automation_internal::EnableTab::Results::Create(
rfh->GetProcess()->GetID(), rfh->GetRoutingID())));
- }
+}
ExtensionFunction::ResponseAction
AutomationInternalPerformActionFunction::Run() {
@@ -251,4 +314,51 @@ AutomationInternalEnableDesktopFunction::Run() {
#endif // defined(OS_CHROMEOS)
}
+// static
+int AutomationInternalQuerySelectorFunction::query_request_id_counter_ = 0;
+
+ExtensionFunction::ResponseAction
+AutomationInternalQuerySelectorFunction::Run() {
+ const AutomationInfo* automation_info = AutomationInfo::Get(extension());
+ EXTENSION_FUNCTION_VALIDATE(automation_info);
+
+ using api::automation_internal::QuerySelector::Params;
+ scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ if (params->args.process_id == kDesktopProcessID &&
+ params->args.routing_id == kDesktopRoutingID) {
+ return RespondNow(
+ Error("querySelector queries may not be used on the desktop."));
+ }
+ content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
+ params->args.process_id, params->args.routing_id);
+ if (!rfh)
+ return RespondNow(Error("querySelector query sent on destroyed tree."));
+
+ content::WebContents* contents =
+ content::WebContents::FromRenderFrameHost(rfh);
+
+ int request_id = query_request_id_counter_++;
+ base::string16 selector = base::UTF8ToUTF16(params->args.selector);
Devlin 2014/10/31 22:11:28 #include "base/strings/string16.h"
aboxhall 2014/10/31 23:06:48 Done.
+
+ // QuerySelectorHandler handles IPCs and deletes itself on completion.
+ new QuerySelectorHandler(
+ contents, request_id, params->args.automation_node_id, selector,
+ base::Bind(&AutomationInternalQuerySelectorFunction::OnResponse, this));
+
+ return RespondLater();
+}
+
+void AutomationInternalQuerySelectorFunction::OnResponse(
+ const std::string& error,
+ int result_acc_obj_id) {
+ if (!error.empty()) {
+ Respond(Error(error));
+ return;
+ }
+
+ Respond(OneArgument(new base::FundamentalValue(result_acc_obj_id)));
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698