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

Side by Side 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, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/automation_internal/automation_internal_ api.h" 5 #include "chrome/browser/extensions/api/automation_internal/automation_internal_ api.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/extensions/api/automation_internal/automation_action_ad apter.h" 11 #include "chrome/browser/extensions/api/automation_internal/automation_action_ad apter.h"
11 #include "chrome/browser/extensions/api/automation_internal/automation_util.h" 12 #include "chrome/browser/extensions/api/automation_internal/automation_util.h"
12 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 13 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
13 #include "chrome/browser/extensions/extension_tab_util.h" 14 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" 17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/extensions/api/automation_internal.h" 18 #include "chrome/common/extensions/api/automation_internal.h"
18 #include "chrome/common/extensions/manifest_handlers/automation.h" 19 #include "chrome/common/extensions/manifest_handlers/automation.h"
19 #include "content/public/browser/ax_event_notification_details.h" 20 #include "content/public/browser/ax_event_notification_details.h"
20 #include "content/public/browser/render_frame_host.h" 21 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_process_host.h" 22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/render_widget_host.h" 24 #include "content/public/browser/render_widget_host.h"
23 #include "content/public/browser/render_widget_host_view.h" 25 #include "content/public/browser/render_widget_host_view.h"
24 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
27 #include "extensions/common/extension_messages.h"
25 #include "extensions/common/permissions/permissions_data.h" 28 #include "extensions/common/permissions/permissions_data.h"
26 29
27 #if defined(OS_CHROMEOS) 30 #if defined(OS_CHROMEOS)
28 #include "chrome/browser/ui/ash/accessibility/automation_manager_ash.h" 31 #include "chrome/browser/ui/ash/accessibility/automation_manager_ash.h"
29 #endif 32 #endif
30 33
31 namespace extensions { 34 namespace extensions {
32 class AutomationWebContentsObserver; 35 class AutomationWebContentsObserver;
33 } // namespace extensions 36 } // namespace extensions
34 37
35 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::AutomationWebContentsObserver); 38 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::AutomationWebContentsObserver);
36 39
37 namespace { 40 namespace {
38 const int kDesktopProcessID = 0; 41 const int kDesktopProcessID = 0;
39 const int kDesktopRoutingID = 0; 42 const int kDesktopRoutingID = 0;
40 43
41 const char kCannotRequestAutomationOnPage[] = 44 const char kCannotRequestAutomationOnPage[] =
42 "Cannot request automation tree on url \"*\". " 45 "Cannot request automation tree on url \"*\". "
43 "Extension manifest must request permission to access this host."; 46 "Extension manifest must request permission to access this host.";
47 const char kRendererDestroyed[] = "The tab was closed.";
48
49 class QuerySelectorHandler : public content::WebContentsObserver {
Devlin 2014/10/28 21:05:09 document
aboxhall 2014/10/28 23:43:56 Done.
50 public:
51 QuerySelectorHandler(
52 content::WebContents* web_contents,
53 int request_id,
54 int acc_obj_id,
55 base::string16& query,
Devlin 2014/10/28 21:05:09 const
aboxhall 2014/10/28 23:43:55 Done.
56 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
57 : content::WebContentsObserver(web_contents),
58 request_id_(request_id),
59 callback_(callback) {
60 content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
61 rvh->Send(new ExtensionMsg_AutomationQuerySelector(
62 rvh->GetRoutingID(), request_id, acc_obj_id, query));
63 }
64
65 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
66
67 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.
68 if (message.type() != ExtensionHostMsg_AutomationQuerySelector_Result::ID)
69 return false;
70
71 // 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/
72 int unused_result_acc_obj_id;
73 int message_request_id;
74 PickleIterator iter(message);
75 CHECK(message.ReadInt(&iter, &unused_result_acc_obj_id));
76 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
77
78 if (message_request_id != request_id_)
79 return false;
80
81 IPC_BEGIN_MESSAGE_MAP(QuerySelectorHandler, message)
82 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AutomationQuerySelector_Result,
83 OnQueryResponse)
84 IPC_END_MESSAGE_MAP()
85 return true;
86 }
87
88 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
89 callback_.Run(kRendererDestroyed, 0);
90 delete this;
91 }
92
93 private:
94 void OnQueryResponse(int request_id,
95 const std::string& error,
96 int result_acc_obj_id) {
97 callback_.Run(error, result_acc_obj_id);
98 delete this;
99 }
100
101 int request_id_;
102 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
103 };
104
44 } // namespace 105 } // namespace
45 106
46 namespace extensions { 107 namespace extensions {
47 108
48 bool CanRequestAutomation(const Extension* extension, 109 bool CanRequestAutomation(const Extension* extension,
49 const AutomationInfo* automation_info, 110 const AutomationInfo* automation_info,
50 const content::WebContents* contents) { 111 const content::WebContents* contents) {
51 if (automation_info->desktop) 112 if (automation_info->desktop)
52 return true; 113 return true;
53 114
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 221
161 if (!CanRequestAutomation(extension(), automation_info, contents)) { 222 if (!CanRequestAutomation(extension(), automation_info, contents)) {
162 return RespondNow( 223 return RespondNow(
163 Error(kCannotRequestAutomationOnPage, contents->GetURL().spec())); 224 Error(kCannotRequestAutomationOnPage, contents->GetURL().spec()));
164 } 225 }
165 AutomationWebContentsObserver::CreateForWebContents(contents); 226 AutomationWebContentsObserver::CreateForWebContents(contents);
166 contents->EnableTreeOnlyAccessibilityMode(); 227 contents->EnableTreeOnlyAccessibilityMode();
167 return RespondNow( 228 return RespondNow(
168 ArgumentList(api::automation_internal::EnableTab::Results::Create( 229 ArgumentList(api::automation_internal::EnableTab::Results::Create(
169 rfh->GetProcess()->GetID(), rfh->GetRoutingID()))); 230 rfh->GetProcess()->GetID(), rfh->GetRoutingID())));
170 } 231 }
171 232
172 ExtensionFunction::ResponseAction 233 ExtensionFunction::ResponseAction
173 AutomationInternalPerformActionFunction::Run() { 234 AutomationInternalPerformActionFunction::Run() {
174 const AutomationInfo* automation_info = AutomationInfo::Get(extension()); 235 const AutomationInfo* automation_info = AutomationInfo::Get(extension());
175 EXTENSION_FUNCTION_VALIDATE(automation_info && automation_info->interact); 236 EXTENSION_FUNCTION_VALIDATE(automation_info && automation_info->interact);
176 237
177 using api::automation_internal::PerformAction::Params; 238 using api::automation_internal::PerformAction::Params;
178 scoped_ptr<Params> params(Params::Create(*args_)); 239 scoped_ptr<Params> params(Params::Create(*args_));
179 EXTENSION_FUNCTION_VALIDATE(params.get()); 240 EXTENSION_FUNCTION_VALIDATE(params.get());
180 241
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 if (!automation_info || !automation_info->desktop) 305 if (!automation_info || !automation_info->desktop)
245 return RespondNow(Error("desktop permission must be requested")); 306 return RespondNow(Error("desktop permission must be requested"));
246 307
247 AutomationManagerAsh::GetInstance()->Enable(browser_context()); 308 AutomationManagerAsh::GetInstance()->Enable(browser_context());
248 return RespondNow(NoArguments()); 309 return RespondNow(NoArguments());
249 #else 310 #else
250 return RespondNow(Error("getDesktop is unsupported by this platform")); 311 return RespondNow(Error("getDesktop is unsupported by this platform"));
251 #endif // defined(OS_CHROMEOS) 312 #endif // defined(OS_CHROMEOS)
252 } 313 }
253 314
315 // static
316 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
317
318 ExtensionFunction::ResponseAction
319 AutomationInternalQuerySelectorFunction::Run() {
320 const AutomationInfo* automation_info = AutomationInfo::Get(extension());
321 EXTENSION_FUNCTION_VALIDATE(automation_info);
322
323 using api::automation_internal::QuerySelector::Params;
324 scoped_ptr<Params> params(Params::Create(*args_));
325 EXTENSION_FUNCTION_VALIDATE(params.get());
326
327 if (params->args.process_id == kDesktopProcessID &&
328 params->args.routing_id == kDesktopRoutingID) {
329 return RespondNow(
330 Error("querySelector queries may not be used on the desktop."));
331 }
332 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
333 params->args.process_id, params->args.routing_id);
334 if (!rfh)
335 return RespondNow(Error("querySelector query sent on destroyed node"));
336
337 content::WebContents* contents =
338 content::WebContents::FromRenderFrameHost(rfh);
339
340 int request_id = query_request_id_counter_++;
341 base::string16 selector = base::UTF8ToUTF16(params->args.selector);
342
343 new QuerySelectorHandler(
Devlin 2014/10/28 21:05:10 nit: comment that QuerySelectorHandler handles its
aboxhall 2014/10/28 23:43:56 Done.
344 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
345 base::Bind(&AutomationInternalQuerySelectorFunction::OnResponse, this));
346 return RespondLater();
347 }
348
349 void AutomationInternalQuerySelectorFunction::OnResponse(
350 const std::string& error,
351 int result_acc_obj_id) {
352 if (!error.empty()) {
353 Respond(Error(error));
354 return;
355 }
356
357 Respond(OneArgument(new base::FundamentalValue(result_acc_obj_id)));
358 }
359
254 } // namespace extensions 360 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698