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

Side by Side Diff: chrome/renderer/automation/automation_renderer_helper.cc

Issue 10384023: Determine the element location and click synchronously on the renderer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/renderer/automation/automation_renderer_helper.h" 5 #include "chrome/renderer/automation/automation_renderer_helper.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/json/json_writer.h"
11 #include "base/stringprintf.h"
12 #include "base/string_split.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/common/automation_events.h"
10 #include "chrome/common/automation_messages.h" 16 #include "chrome/common/automation_messages.h"
17 #include "content/public/renderer/v8_value_converter.h"
11 #include "content/public/renderer/render_view.h" 18 #include "content/public/renderer/render_view.h"
dennis_jeffrey 2012/05/08 19:18:49 swap the above 2 lines to keep them in alphabetica
kkania 2012/05/09 18:19:59 Done.
12 #include "skia/ext/platform_canvas.h" 19 #include "skia/ext/platform_canvas.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
17 #include "ui/gfx/codec/png_codec.h" 26 #include "ui/gfx/codec/png_codec.h"
27 #include "ui/gfx/point.h"
18 #include "ui/gfx/rect.h" 28 #include "ui/gfx/rect.h"
29 #include "v8/include/v8.h"
19 #include "webkit/glue/webkit_glue.h" 30 #include "webkit/glue/webkit_glue.h"
20 31
21 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 32 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
22 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 33 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
23 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 34 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
24 35
25 using WebKit::WebFrame; 36 using WebKit::WebFrame;
26 using WebKit::WebSize; 37 using WebKit::WebSize;
27 using WebKit::WebURL; 38 using WebKit::WebURL;
28 using WebKit::WebView; 39 using WebKit::WebView;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 // message data. 110 // message data.
100 if (success && png_data.size() > IPC::Channel::kMaximumMessageSize - 1024) { 111 if (success && png_data.size() > IPC::Channel::kMaximumMessageSize - 1024) {
101 png_data.clear(); 112 png_data.clear();
102 success = false; 113 success = false;
103 error_msg = "image is too large to be transferred over ipc"; 114 error_msg = "image is too large to be transferred over ipc";
104 } 115 }
105 Send(new AutomationMsg_SnapshotEntirePageACK( 116 Send(new AutomationMsg_SnapshotEntirePageACK(
106 routing_id(), success, png_data, error_msg)); 117 routing_id(), success, png_data, error_msg));
107 } 118 }
108 119
120 namespace {
121
122 scoped_ptr<base::Value> EvaluateScriptInFrame(WebFrame* web_frame,
123 const std::string& script) {
124 v8::Handle<v8::Value> result = web_frame->executeScriptAndReturnValue(
125 WebKit::WebScriptSource(UTF8ToUTF16(script)));
126 if (!result.IsEmpty()) {
127 v8::HandleScope handle_scope;
128 v8::Local<v8::Context> context = web_frame->mainWorldScriptContext();
129 v8::Context::Scope context_scope(context);
130 scoped_ptr<content::V8ValueConverter> converter(
131 content::V8ValueConverter::create());
132 return scoped_ptr<base::Value>(converter->FromV8Value(result, context));
133 } else {
134 return scoped_ptr<base::Value>(base::Value::CreateNullValue());
135 }
136 }
137
138 WebFrame* FrameFromXPath(WebView* view, const string16& frame_xpath) {
139 WebFrame* frame = view->mainFrame();
140 if (frame_xpath.empty())
141 return frame;
142
143 std::vector<string16> xpaths;
144 base::SplitString(frame_xpath, '\n', &xpaths);
145 for (std::vector<string16>::const_iterator i = xpaths.begin();
146 frame && i != xpaths.end(); ++i) {
147 frame = frame->findChildByExpression(*i);
148 }
149 return frame;
150 }
151
152 bool EvaluateScriptChainHelper(
153 WebView* web_view,
154 const std::string& script,
155 const std::string& frame_xpath,
156 scoped_ptr<base::DictionaryValue>* result,
157 std::string* error_msg) {
158 WebFrame* web_frame = FrameFromXPath(web_view, UTF8ToUTF16(frame_xpath));
159 if (!web_frame) {
160 *error_msg = "Failed to locate frame by xpath: " + frame_xpath;
161 return false;
162 }
163 scoped_ptr<base::Value> script_value =
164 EvaluateScriptInFrame(web_frame, script);
165 base::DictionaryValue* dict;
166 if (!script_value.get() || !script_value->GetAsDictionary(&dict)) {
167 *error_msg = "Script did not return an object";
168 return false;
169 }
170 base::Value* error_value;
171 if (dict->Get("error", &error_value)) {
172 base::JSONWriter::Write(error_value, error_msg);
173 return false;
174 }
175 result->reset(static_cast<base::DictionaryValue*>(script_value.release()));
176 return true;
177 }
178
179 } // namespace
180
181 bool AutomationRendererHelper::EvaluateScriptChain(
182 const std::vector<ScriptEvaluationRequest>& script_chain,
183 scoped_ptr<base::DictionaryValue>* result,
184 std::string* error_msg) {
185 CHECK(!script_chain.empty());
186 WebView* web_view = render_view()->GetWebView();
187 scoped_ptr<base::DictionaryValue> temp_result;
188 for (size_t i = 0; i < script_chain.size(); ++i) {
189 std::string args_utf8 = "null";
190 if (temp_result.get())
191 base::JSONWriter::Write(temp_result.get(), &args_utf8);
192 std::string wrapper_script = base::StringPrintf(
193 "(function(){return %s\n}).apply(null, [%s])",
194 script_chain[i].script.c_str(), args_utf8.c_str());
195 if (!EvaluateScriptChainHelper(web_view, wrapper_script,
196 script_chain[i].frame_xpath,
197 &temp_result, error_msg)) {
198 return false;
199 }
200 }
201 std::string result_str;
202 base::JSONWriter::Write(temp_result.get(), &result_str);
203 result->reset(temp_result.release());
204 return true;
205 }
206
207 bool AutomationRendererHelper::ProcessMouseEvent(
208 const AutomationMouseEvent& event,
209 std::string* error_msg) {
210 WebView* web_view = render_view()->GetWebView();
211 if (!web_view) {
212 *error_msg = "Failed to process mouse event because webview does not exist";
213 return false;
214 }
215 WebKit::WebMouseEvent mouse_event = event.mouse_event;
216 if (!event.location_script_chain.empty()) {
217 scoped_ptr<base::DictionaryValue> result;
218 if (!EvaluateScriptChain(event.location_script_chain, &result, error_msg))
219 return false;
220 int x, y;
221 if (!result->GetInteger("x", &x) ||
222 !result->GetInteger("y", &y)) {
223 *error_msg = "Script did not return an (x,y) location";
224 return false;
225 }
226 mouse_event.x = x;
227 mouse_event.y = y;
228 }
229 Send(new AutomationMsg_WillProcessMouseEventAt(
230 routing_id(),
231 gfx::Point(mouse_event.x, mouse_event.y)));
232 web_view->handleInputEvent(mouse_event);
233 return true;
234 }
235
109 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 236 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
110 void AutomationRendererHelper::OnHeapProfilerDump(const std::string& reason) { 237 void AutomationRendererHelper::OnHeapProfilerDump(const std::string& reason) {
111 if (!::IsHeapProfilerRunning()) { 238 if (!::IsHeapProfilerRunning()) {
112 return; 239 return;
113 } 240 }
114 ::HeapProfilerDump(reason.c_str()); 241 ::HeapProfilerDump(reason.c_str());
115 } 242 }
116 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 243 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
117 244
118 bool AutomationRendererHelper::OnMessageReceived(const IPC::Message& message) { 245 bool AutomationRendererHelper::OnMessageReceived(const IPC::Message& message) {
119 bool handled = true; 246 bool handled = true;
120 bool deserialize_success = true; 247 bool deserialize_success = true;
121 IPC_BEGIN_MESSAGE_MAP_EX(AutomationRendererHelper, message, 248 IPC_BEGIN_MESSAGE_MAP_EX(AutomationRendererHelper, message,
122 deserialize_success) 249 deserialize_success)
123 IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePage, OnSnapshotEntirePage) 250 IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePage, OnSnapshotEntirePage)
124 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 251 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
125 IPC_MESSAGE_HANDLER(AutomationMsg_HeapProfilerDump, OnHeapProfilerDump) 252 IPC_MESSAGE_HANDLER(AutomationMsg_HeapProfilerDump, OnHeapProfilerDump)
126 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 253 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
254 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessMouseEvent, OnProcessMouseEvent)
127 IPC_MESSAGE_UNHANDLED(handled = false) 255 IPC_MESSAGE_UNHANDLED(handled = false)
128 IPC_END_MESSAGE_MAP_EX() 256 IPC_END_MESSAGE_MAP_EX()
129 if (!deserialize_success) { 257 if (!deserialize_success) {
130 LOG(ERROR) << "Failed to deserialize an IPC message"; 258 LOG(ERROR) << "Failed to deserialize an IPC message";
131 } 259 }
132 return handled; 260 return handled;
133 } 261 }
134 262
135 void AutomationRendererHelper::WillPerformClientRedirect( 263 void AutomationRendererHelper::WillPerformClientRedirect(
136 WebFrame* frame, const WebURL& from, const WebURL& to, double interval, 264 WebFrame* frame, const WebURL& from, const WebURL& to, double interval,
137 double fire_time) { 265 double fire_time) {
138 Send(new AutomationMsg_WillPerformClientRedirect( 266 Send(new AutomationMsg_WillPerformClientRedirect(
139 routing_id(), frame->identifier(), interval)); 267 routing_id(), frame->identifier(), interval));
140 } 268 }
141 269
142 void AutomationRendererHelper::DidCancelClientRedirect(WebFrame* frame) { 270 void AutomationRendererHelper::DidCancelClientRedirect(WebFrame* frame) {
143 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect( 271 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect(
144 routing_id(), frame->identifier())); 272 routing_id(), frame->identifier()));
145 } 273 }
146 274
147 void AutomationRendererHelper::DidCompleteClientRedirect( 275 void AutomationRendererHelper::DidCompleteClientRedirect(
148 WebFrame* frame, const WebURL& from) { 276 WebFrame* frame, const WebURL& from) {
149 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect( 277 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect(
150 routing_id(), frame->identifier())); 278 routing_id(), frame->identifier()));
151 } 279 }
280
281 void AutomationRendererHelper::OnProcessMouseEvent(
282 const AutomationMouseEvent& event) {
283 std::string error_msg;
284 bool success = ProcessMouseEvent(event, &error_msg);
285 Send(new AutomationMsg_ProcessMouseEventACK(
286 routing_id(), success, error_msg));
287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698