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

Side by Side Diff: chrome/test/webdriver/session.cc

Issue 3064012: Base implementation of WebDriver for Chrome. This checkin includes... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 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
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/session_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/test/webdriver/session_manager.h"
6
7 #ifdef OS_POSIX
8 #include <unistd.h>
9 #endif
10 #ifdef OS_WIN
11 #include <windows.h>
12 #include <shellapi.h>
13 #endif
14
15 #include <stdlib.h>
16 #include <vector>
17
18 #include "base/command_line.h"
19 #include "base/logging.h"
20 #include "base/process.h"
21 #include "base/process_util.h"
22 #include "base/string_util.h"
23 #include "base/json/json_reader.h"
24 #include "base/json/json_writer.h"
25
26 #include "chrome/app/chrome_dll_resource.h"
27 #include "chrome/common/chrome_constants.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/test/webdriver/utility_functions.h"
30
31 #include "third_party/webdriver/atoms.h"
32
33 namespace webdriver {
34
35 #ifdef OS_WIN
36 namespace {
37 std::string GetTempPath() {
38 DWORD result = ::GetTempPath(0, L"");
39 if (result == 0)
40 LOG(ERROR) << "Could not get system temp path" << std::endl;
41
42 std::vector<TCHAR> tempPath(result + 1);
43 result = ::GetTempPath(static_cast<DWORD>(tempPath.size()), &tempPath[0]);
44 if ((result == 0) || (result >= tempPath.size())) {
45 LOG(ERROR) << "Could not get system temp path" << std::endl;
46 NOTREACHED();
47 }
48 return std::string(tempPath.begin(),
49 tempPath.begin() + static_cast<std::size_t>(result));
50 }
51 } // namespace
52 #endif
53
54 Session::Session(const std::string& id, AutomationProxy* proxy)
55 : id_(id), proxy_(proxy), process_(base::kNullProcessHandle),
56 window_num_(0), implicit_wait_(0), current_frame_xpath_(L"") {
57 }
58
59 bool Session::Init(base::ProcessHandle process_handle) {
60 CHECK(process_.handle() == base::kNullProcessHandle)
61 << "Session has already been initialized";
62 process_.set_handle(process_handle);
63
64 if (!proxy_->WaitForInitialLoads()) {
65 LOG(WARNING) << "Failed to wait for initial loads" << std::endl;
66 return false;
67 }
68
69 if (!WaitForLaunch()) {
70 return false;
71 }
72
73 return LoadProxies();
74 }
75
76 scoped_refptr<WindowProxy> Session::GetWindow() {
77 return ActivateTab() ? browser_->GetWindow() : NULL;
78 }
79
80 scoped_refptr<TabProxy> Session::ActivateTab() {
81 int tab_index;
82 if (!tab_->GetTabIndex(&tab_index) ||
83 !browser_->ActivateTab(tab_index)) {
84 LOG(ERROR) << "Failed to session tab";
85 return NULL;
86 }
87 return tab_;
88 }
89
90 bool Session::WaitForLaunch() {
91 AutomationLaunchResult result = proxy_->WaitForAppLaunch();
92 if (result == AUTOMATION_SUCCESS) {
93 LOG(INFO) << "Automation setup is a success" << std::endl;
94 } else if (result == AUTOMATION_TIMEOUT) {
95 LOG(WARNING) << "Timeout, automation setup failed" << std::endl;
96 return false;
97 } else {
98 LOG(WARNING) << "Failure in automation setup" << std::endl;
99 return false;
100 }
101
102 LOG(INFO) << proxy_->channel_id() << std::endl;
103 if (!proxy_->OpenNewBrowserWindow(Browser::TYPE_NORMAL, true)) {
104 LOG(WARNING) << "Failed to open a new browser window" << std::endl;
105 return false;
106 }
107 return true;
108 }
109
110 bool Session::LoadProxies() {
111 scoped_refptr<BrowserProxy> browser = proxy_->GetBrowserWindow(0);
112 if (!browser.get()) {
113 LOG(WARNING) << "Failed to get browser window.";
114 return false;
115 }
116
117 scoped_refptr<TabProxy> tab = browser->GetActiveTab();
118 if (!tab->NavigateToURL(GURL("about://config/"))) {
119 LOG(WARNING) << "Could not navigate to about://config/" << std::endl;
120 return false;
121 }
122
123 SetBrowserAndTab(0, browser, tab);
124 return true;
125 }
126
127 void Session::SetBrowserAndTab(const int window_num,
128 const scoped_refptr<BrowserProxy>& browser,
129 const scoped_refptr<TabProxy>& tab) {
130 window_num_ = window_num;
131 browser_ = browser;
132 tab_ = tab;
133 current_frame_xpath_ = L"";
134
135 int tab_num;
136 LOG_IF(WARNING, !tab->GetTabIndex(&tab_num) || !browser->ActivateTab(tab_num))
137 << "Failed to activate tab";
138 }
139
140 bool Session::CreateTemporaryProfileDirectory() {
141 memset(tmp_profile_dir_, 0, sizeof tmp_profile_dir_);
142 #ifdef OS_POSIX
143 strncat(tmp_profile_dir_, "/tmp/webdriverXXXXXX", sizeof tmp_profile_dir_);
144 if (mkdtemp(tmp_profile_dir_) == NULL) {
145 LOG(ERROR) << "mkdtemp failed";
146 return false;
147 }
148 #elif OS_WIN
149 DWORD ret;
150 ProfileDir temp_dir;
151
152 ret = GetTempPathA(sizeof temp_dir, temp_dir);
153 if (ret == 0 || ret > sizeof temp_dir) {
154 LOG(ERROR) << "Could not find the temp directory" << std::endl;
155 return false;
156 }
157
158 ret = GetTempFileNameA(temp_dir, // directory for tmp files
159 "webdriver", // temp file name prefix
160 static_cast<int>(time(NULL)) % 65535 + 1,
161 tmp_profile_dir_); // buffer for name
162
163 if (ret ==0) {
164 LOG(ERROR) << "Could not generate temp directory name" << std::endl;
165 return false;
166 }
167
168 if (!CreateDirectoryA(tmp_profile_dir_, NULL)) {
169 DWORD dw = GetLastError();
170 LOG(ERROR) << "Error code: " << dw << std::endl;
171 return false;
172 }
173 #endif
174 LOG(INFO) << "Using temporary profile directory: " << tmp_profile_dir_;
175 return true;
176 }
177
178 #ifdef OS_WIN
179 bool DeleteDirectory(const char* directory) {
180 SHFILEOPSTRUCT fileop;
181 size_t convertedChars;
182 int len = strlen(directory);
183 wchar_t *pszFrom = new wchar_t[len+2];
184 memset(&fileop, 0, sizeof fileop);
185 memset(pszFrom, 0, sizeof pszFrom);
186
187 mbstowcs_s(&convertedChars, pszFrom, len+2, directory, len);
188 fileop.wFunc = FO_DELETE; // delete operation
189 // source file name as double null terminated string
190 fileop.pFrom = (LPCWSTR) pszFrom;
191 fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; // do not prompt the user
192 fileop.fAnyOperationsAborted = FALSE;
193
194 int ret = SHFileOperation(&fileop);
195 delete pszFrom;
196 return (ret == 0);
197 }
198 #endif
199
200 void Session::Terminate() {
201 if (!proxy_->SetFilteredInet(false)) {
202 LOG(ERROR) << "Error in closing down session" << std::endl;
203 }
204
205 #ifdef OS_WIN
206 if (!DeleteDirectory(tmp_profile_dir_)) {
207 LOG(ERROR) << "Could not clean up temp directory: "
208 << tmp_profile_dir_ << std::endl;
209 }
210 #else
211 if (rmdir(tmp_profile_dir_)) {
212 LOG(ERROR) << "Could not clean up temp directory: "
213 << tmp_profile_dir_ << std::endl;
214 }
215 #endif
216 process_.Terminate(EXIT_SUCCESS);
217 }
218
219 ErrorCode Session::ExecuteScript(const std::wstring& script,
220 const ListValue* const args,
221 Value** value) {
222 std::string args_as_json;
223 base::JSONWriter::Write(static_cast<const Value* const>(args),
224 /*pretty_print=*/false,
225 &args_as_json);
226
227 std::wstring jscript = L"window.domAutomationController.send(";
228 jscript.append(L"(function(){")
229 // Every injected script is fed through the executeScript atom. This atom
230 // will catch any errors that are thrown and convert them to the
231 // appropriate JSON structure.
232 .append(build_atom(EXECUTE_SCRIPT, sizeof EXECUTE_SCRIPT))
233 .append(L"var result = executeScript(function(){")
234 .append(script)
235 .append(L"},")
236 .append(ASCIIToWide(args_as_json))
237 .append(L");return JSON.stringify(result);})());");
238
239 // Should we also log the script that's being executed? It could be several KB
240 // in size and will add lots of noise to the logs.
241 LOG(INFO) << "Executing script in frame: " << current_frame_xpath_;
242
243 std::wstring result;
244 scoped_refptr<TabProxy> tab = ActivateTab();
245 if (!tab->ExecuteAndExtractString(current_frame_xpath_, jscript, &result)) {
246 *value = Value::CreateStringValue(
247 "Unknown internal script execution failure");
248 return kUnknownError;
249 }
250
251 LOG(INFO) << "...script result: " << result;
252 std::string temp = WideToASCII(result);
253 scoped_ptr<Value> r(base::JSONReader::ReadAndReturnError(
254 temp, true, NULL, NULL));
255 if (!r.get()) {
256 *value = Value::CreateStringValue(
257 "Internal script execution error: failed to parse script result");
258 return kUnknownError;
259 }
260
261 if (r->GetType() != Value::TYPE_DICTIONARY) {
262 std::ostringstream stream;
263 stream << "Internal script execution error: script result must be a "
264 << print_valuetype(Value::TYPE_DICTIONARY)
265 << ", but was "
266 << print_valuetype(r->GetType()) << ": " << result;
267 *value = Value::CreateStringValue(stream.str());
268 return kUnknownError;
269 }
270
271 DictionaryValue* result_dict = static_cast<DictionaryValue*>(r.get());
272
273 Value* tmp;
274 if (result_dict->Get("value", &tmp)) {
275 // result_dict owns the returned value, so we need to make a copy.
276 *value = tmp->DeepCopy();
277 } else {
278 // "value" was not defined in the returned dictionary, set to null.
279 *value = Value::CreateNullValue();
280 }
281
282 int status;
283 if (!result_dict->GetInteger("status", &status)) {
284 NOTREACHED() << "...script did not return a status flag.";
285 }
286 return static_cast<ErrorCode>(status);
287 }
288 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/session_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698