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

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: 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..e6c770ba90bfe1c1224a801a0da0d52fb554ff2d 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)
@@ -41,6 +44,64 @@ const int kDesktopRoutingID = 0;
const char kCannotRequestAutomationOnPage[] =
"Cannot request automation tree on url \"*\". "
"Extension manifest must request permission to access this host.";
+const char kRendererDestroyed[] = "The tab was closed.";
+
+class QuerySelectorHandler : public content::WebContentsObserver {
Devlin 2014/10/28 21:05:09 document
aboxhall 2014/10/28 23:43:56 Done.
+ public:
+ QuerySelectorHandler(
+ content::WebContents* web_contents,
+ int request_id,
+ int acc_obj_id,
+ base::string16& query,
Devlin 2014/10/28 21:05:09 const
aboxhall 2014/10/28 23:43:55 Done.
+ extensions::AutomationInternalQuerySelectorFunction::Callback callback)
Devlin 2014/10/28 21:05:09 const &
aboxhall 2014/10/28 23:43:56 I don't think this makes sense.
Devlin 2014/10/29 16:09:03 Sure it does - you can copy callbacks just like an
aboxhall 2014/10/29 16:35:19 I realise I'm making a copy, but I think that's th
aboxhall 2014/10/29 17:05:20 Ah right, but then I copy it again. Will fix.
Devlin 2014/10/29 17:05:36 One copy is good, but right now there could be two
+ : 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));
+ }
+
+ virtual ~QuerySelectorHandler() {}
Devlin 2014/10/28 21:05:09 nit: ~QuerySelectorHandler() override {}
aboxhall 2014/10/28 23:43:55 Why override?
Devlin 2014/10/29 16:09:03 C++ 11 style. TL;DR: virtual + override is redund
aboxhall 2014/10/29 16:35:19 Got it, thanks. (https://groups.google.com/a/chrom
+
+ virtual bool OnMessageReceived(const IPC::Message& message) override {
Devlin 2014/10/28 21:05:09 nit: no virtual (also for other methods)
aboxhall 2014/10/28 23:43:56 I don't understand; this is overriding a virtual m
Devlin 2014/10/29 16:09:03 See above - no virtual, just override. i.e. bool
aboxhall 2014/10/29 16:35:19 Done.
+ if (message.type() != ExtensionHostMsg_AutomationQuerySelector_Result::ID)
+ return false;
+
+ // There may be several requests in flight; check that this response matches
Devlin 2014/10/28 21:05:10 nit: End the sentence with a period.
aboxhall 2014/10/28 23:43:56 I don't think it's worth wrapping onto a new line.
Devlin 2014/10/29 16:09:03 Sadly, style rules. :/ (My personal preference wo
aboxhall 2014/10/29 16:35:19 I don't see it in the style guide. I don't think w
Devlin 2014/10/29 17:05:36 http://google-styleguide.googlecode.com/svn/trunk/
+ int unused_result_acc_obj_id;
+ int message_request_id;
+ PickleIterator iter(message);
+ CHECK(message.ReadInt(&iter, &unused_result_acc_obj_id));
+ CHECK(message.ReadInt(&iter, &message_request_id));
Devlin 2014/10/28 21:05:09 I'm not super familiar with the inner workings of
aboxhall 2014/10/28 23:43:55 Good question. This was actually several flavours
+
+ 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;
+ }
+
+ virtual void WebContentsDestroyed() override {
Devlin 2014/10/28 21:05:09 It's good that we watch the web contents, but shou
aboxhall 2014/10/28 23:43:56 I'm not sure; I copied this pattern from extension
+ 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_;
+ extensions::AutomationInternalQuerySelectorFunction::Callback callback_;
Devlin 2014/10/28 21:05:09 Why not just put the class in extensions::?
aboxhall 2014/10/28 23:43:56 Which class?
Devlin 2014/10/29 16:09:03 QuerySelectorHandler. Basically, move the namespac
aboxhall 2014/10/29 16:35:19 Moved this into extensions:: below the const decla
+};
+
} // namespace
namespace extensions {
@@ -167,7 +228,7 @@ AutomationInternalEnableTabFunction::Run() {
return RespondNow(
ArgumentList(api::automation_internal::EnableTab::Results::Create(
rfh->GetProcess()->GetID(), rfh->GetRoutingID())));
- }
+}
ExtensionFunction::ResponseAction
AutomationInternalPerformActionFunction::Run() {
@@ -251,4 +312,49 @@ AutomationInternalEnableDesktopFunction::Run() {
#endif // defined(OS_CHROMEOS)
}
+// static
+int AutomationInternalQuerySelectorFunction::query_request_id_counter_ = 0;
Devlin 2014/10/28 21:05:09 why not put this in an anonymous namespace? Is it
aboxhall 2014/10/28 23:43:56 It's scoped and private to the class which uses it
Devlin 2014/10/29 16:09:03 Reduces the header import size by 0.000001%. :P M
aboxhall 2014/10/29 16:35:19 I don't feel particularly strongly, but I do think
+
+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 node"));
+
+ content::WebContents* contents =
+ content::WebContents::FromRenderFrameHost(rfh);
+
+ int request_id = query_request_id_counter_++;
+ base::string16 selector = base::UTF8ToUTF16(params->args.selector);
+
+ new QuerySelectorHandler(
Devlin 2014/10/28 21:05:10 nit: comment that QuerySelectorHandler handles its
aboxhall 2014/10/28 23:43:56 Done.
+ contents, request_id, params->args.automation_node_id, selector,
Devlin 2014/10/28 21:05:09 nit: one arg per line (even though it's long)
aboxhall 2014/10/28 23:43:56 This is how clang-format formats it, I'd rather le
Devlin 2014/10/29 16:09:03 Dang - they keep changing clang format's style (be
+ 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