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

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: rebase 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"
11 #include "content/public/renderer/render_view.h" 17 #include "content/public/renderer/render_view.h"
18 #include "content/public/renderer/v8_value_converter.h"
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::HandleScope handle_scope;
125 v8::Local<v8::Value> result = v8::Local<v8::Value>::New(
126 web_frame->executeScriptAndReturnValue(
127 WebKit::WebScriptSource(UTF8ToUTF16(script))));
128 if (!result.IsEmpty()) {
129 v8::Local<v8::Context> context = web_frame->mainWorldScriptContext();
130 v8::Context::Scope context_scope(context);
131 scoped_ptr<content::V8ValueConverter> converter(
132 content::V8ValueConverter::create());
133 return scoped_ptr<base::Value>(converter->FromV8Value(result, context));
134 } else {
135 return scoped_ptr<base::Value>(base::Value::CreateNullValue());
136 }
137 }
138
139 WebFrame* FrameFromXPath(WebView* view, const string16& frame_xpath) {
140 WebFrame* frame = view->mainFrame();
141 if (frame_xpath.empty())
142 return frame;
143
144 std::vector<string16> xpaths;
145 base::SplitString(frame_xpath, '\n', &xpaths);
146 for (std::vector<string16>::const_iterator i = xpaths.begin();
147 frame && i != xpaths.end(); ++i) {
148 frame = frame->findChildByExpression(*i);
149 }
150 return frame;
151 }
152
153 bool EvaluateScriptChainHelper(
154 WebView* web_view,
155 const std::string& script,
156 const std::string& frame_xpath,
157 scoped_ptr<base::DictionaryValue>* result,
158 std::string* error_msg) {
159 WebFrame* web_frame = FrameFromXPath(web_view, UTF8ToUTF16(frame_xpath));
160 if (!web_frame) {
161 *error_msg = "Failed to locate frame by xpath: " + frame_xpath;
162 return false;
163 }
164 scoped_ptr<base::Value> script_value =
165 EvaluateScriptInFrame(web_frame, script);
166 base::DictionaryValue* dict;
167 if (!script_value.get() || !script_value->GetAsDictionary(&dict)) {
168 *error_msg = "Script did not return an object";
169 return false;
170 }
171 base::Value* error_value;
172 if (dict->Get("error", &error_value)) {
173 base::JSONWriter::Write(error_value, error_msg);
174 return false;
175 }
176 result->reset(static_cast<base::DictionaryValue*>(script_value.release()));
177 return true;
178 }
179
180 } // namespace
181
182 bool AutomationRendererHelper::EvaluateScriptChain(
183 const std::vector<ScriptEvaluationRequest>& script_chain,
184 scoped_ptr<base::DictionaryValue>* result,
185 std::string* error_msg) {
186 CHECK(!script_chain.empty());
187 WebView* web_view = render_view()->GetWebView();
188 scoped_ptr<base::DictionaryValue> temp_result;
189 for (size_t i = 0; i < script_chain.size(); ++i) {
190 std::string args_utf8 = "null";
191 if (temp_result.get())
192 base::JSONWriter::Write(temp_result.get(), &args_utf8);
193 std::string wrapper_script = base::StringPrintf(
194 "(function(){return %s\n}).apply(null, [%s])",
195 script_chain[i].script.c_str(), args_utf8.c_str());
196 if (!EvaluateScriptChainHelper(web_view, wrapper_script,
197 script_chain[i].frame_xpath,
198 &temp_result, error_msg)) {
199 return false;
200 }
201 }
202 std::string result_str;
203 base::JSONWriter::Write(temp_result.get(), &result_str);
204 result->reset(temp_result.release());
205 return true;
206 }
207
208 bool AutomationRendererHelper::ProcessMouseEvent(
209 const AutomationMouseEvent& event,
210 std::string* error_msg) {
211 WebView* web_view = render_view()->GetWebView();
212 if (!web_view) {
213 *error_msg = "Failed to process mouse event because webview does not exist";
214 return false;
215 }
216 WebKit::WebMouseEvent mouse_event = event.mouse_event;
217 if (!event.location_script_chain.empty()) {
218 scoped_ptr<base::DictionaryValue> result;
219 if (!EvaluateScriptChain(event.location_script_chain, &result, error_msg))
220 return false;
221 int x, y;
222 if (!result->GetInteger("x", &x) ||
223 !result->GetInteger("y", &y)) {
224 *error_msg = "Script did not return an (x,y) location";
225 return false;
226 }
227 mouse_event.x = x;
228 mouse_event.y = y;
229 }
230 Send(new AutomationMsg_WillProcessMouseEventAt(
231 routing_id(),
232 gfx::Point(mouse_event.x, mouse_event.y)));
233 web_view->handleInputEvent(mouse_event);
234 return true;
235 }
236
109 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 237 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
110 void AutomationRendererHelper::OnHeapProfilerDump(const std::string& reason) { 238 void AutomationRendererHelper::OnHeapProfilerDump(const std::string& reason) {
111 if (!::IsHeapProfilerRunning()) { 239 if (!::IsHeapProfilerRunning()) {
112 return; 240 return;
113 } 241 }
114 ::HeapProfilerDump(reason.c_str()); 242 ::HeapProfilerDump(reason.c_str());
115 } 243 }
116 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 244 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
117 245
118 bool AutomationRendererHelper::OnMessageReceived(const IPC::Message& message) { 246 bool AutomationRendererHelper::OnMessageReceived(const IPC::Message& message) {
119 bool handled = true; 247 bool handled = true;
120 bool deserialize_success = true; 248 bool deserialize_success = true;
121 IPC_BEGIN_MESSAGE_MAP_EX(AutomationRendererHelper, message, 249 IPC_BEGIN_MESSAGE_MAP_EX(AutomationRendererHelper, message,
122 deserialize_success) 250 deserialize_success)
123 IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePage, OnSnapshotEntirePage) 251 IPC_MESSAGE_HANDLER(AutomationMsg_SnapshotEntirePage, OnSnapshotEntirePage)
124 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 252 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
125 IPC_MESSAGE_HANDLER(AutomationMsg_HeapProfilerDump, OnHeapProfilerDump) 253 IPC_MESSAGE_HANDLER(AutomationMsg_HeapProfilerDump, OnHeapProfilerDump)
126 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 254 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
255 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessMouseEvent, OnProcessMouseEvent)
127 IPC_MESSAGE_UNHANDLED(handled = false) 256 IPC_MESSAGE_UNHANDLED(handled = false)
128 IPC_END_MESSAGE_MAP_EX() 257 IPC_END_MESSAGE_MAP_EX()
129 if (!deserialize_success) { 258 if (!deserialize_success) {
130 LOG(ERROR) << "Failed to deserialize an IPC message"; 259 LOG(ERROR) << "Failed to deserialize an IPC message";
131 } 260 }
132 return handled; 261 return handled;
133 } 262 }
134 263
135 void AutomationRendererHelper::WillPerformClientRedirect( 264 void AutomationRendererHelper::WillPerformClientRedirect(
136 WebFrame* frame, const WebURL& from, const WebURL& to, double interval, 265 WebFrame* frame, const WebURL& from, const WebURL& to, double interval,
137 double fire_time) { 266 double fire_time) {
138 Send(new AutomationMsg_WillPerformClientRedirect( 267 Send(new AutomationMsg_WillPerformClientRedirect(
139 routing_id(), frame->identifier(), interval)); 268 routing_id(), frame->identifier(), interval));
140 } 269 }
141 270
142 void AutomationRendererHelper::DidCancelClientRedirect(WebFrame* frame) { 271 void AutomationRendererHelper::DidCancelClientRedirect(WebFrame* frame) {
143 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect( 272 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect(
144 routing_id(), frame->identifier())); 273 routing_id(), frame->identifier()));
145 } 274 }
146 275
147 void AutomationRendererHelper::DidCompleteClientRedirect( 276 void AutomationRendererHelper::DidCompleteClientRedirect(
148 WebFrame* frame, const WebURL& from) { 277 WebFrame* frame, const WebURL& from) {
149 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect( 278 Send(new AutomationMsg_DidCompleteOrCancelClientRedirect(
150 routing_id(), frame->identifier())); 279 routing_id(), frame->identifier()));
151 } 280 }
281
282 void AutomationRendererHelper::OnProcessMouseEvent(
283 const AutomationMouseEvent& event) {
284 std::string error_msg;
285 bool success = ProcessMouseEvent(event, &error_msg);
286 Send(new AutomationMsg_ProcessMouseEventACK(
287 routing_id(), success, error_msg));
288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698