Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/test/chromedriver/chrome/devtools_http_client.h" | 5 #include "chrome/test/chromedriver/chrome/devtools_http_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
| 12 #include "base/strings/string_util.h" | |
| 12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 13 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
| 14 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 15 #include "base/values.h" | 16 #include "base/values.h" |
| 16 #include "chrome/test/chromedriver/chrome/device_metrics.h" | 17 #include "chrome/test/chromedriver/chrome/device_metrics.h" |
| 17 #include "chrome/test/chromedriver/chrome/devtools_client_impl.h" | 18 #include "chrome/test/chromedriver/chrome/devtools_client_impl.h" |
| 18 #include "chrome/test/chromedriver/chrome/log.h" | 19 #include "chrome/test/chromedriver/chrome/log.h" |
| 19 #include "chrome/test/chromedriver/chrome/status.h" | 20 #include "chrome/test/chromedriver/chrome/status.h" |
| 20 #include "chrome/test/chromedriver/chrome/version.h" | 21 #include "chrome/test/chromedriver/chrome/version.h" |
| 21 #include "chrome/test/chromedriver/chrome/web_view_impl.h" | 22 #include "chrome/test/chromedriver/chrome/web_view_impl.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 socket_factory_(socket_factory), | 67 socket_factory_(socket_factory), |
| 67 server_url_("http://" + address.ToString()), | 68 server_url_("http://" + address.ToString()), |
| 68 web_socket_url_prefix_(base::StringPrintf( | 69 web_socket_url_prefix_(base::StringPrintf( |
| 69 "ws://%s/devtools/page/", address.ToString().c_str())), | 70 "ws://%s/devtools/page/", address.ToString().c_str())), |
| 70 device_metrics_(device_metrics.Pass()) {} | 71 device_metrics_(device_metrics.Pass()) {} |
| 71 | 72 |
| 72 DevToolsHttpClient::~DevToolsHttpClient() {} | 73 DevToolsHttpClient::~DevToolsHttpClient() {} |
| 73 | 74 |
| 74 Status DevToolsHttpClient::Init(const base::TimeDelta& timeout) { | 75 Status DevToolsHttpClient::Init(const base::TimeDelta& timeout) { |
| 75 base::TimeTicks deadline = base::TimeTicks::Now() + timeout; | 76 base::TimeTicks deadline = base::TimeTicks::Now() + timeout; |
| 76 std::string browser_version; | 77 std::string version_url = server_url_ + "/json/version"; |
| 77 std::string blink_version; | 78 std::string data; |
| 78 | 79 |
| 79 while (true) { | 80 while (!FetchUrlAndLog(version_url, context_getter_.get(), &data)) { |
|
stgao
2014/09/29 23:09:54
I see once the returned data is empty.
Add "|| dat
samuong
2014/09/30 04:03:49
Done.
| |
| 80 Status status = GetVersion(&browser_version, &blink_version); | 81 if (base::TimeTicks::Now() > deadline) |
| 81 if (status.IsOk()) | 82 return Status(kChromeNotReachable); |
| 82 break; | |
| 83 if (status.code() != kChromeNotReachable || | |
| 84 base::TimeTicks::Now() > deadline) { | |
| 85 return status; | |
| 86 } | |
| 87 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); | 83 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); |
| 88 } | 84 } |
| 89 | 85 |
| 90 // |blink_version| is should look something like "537.36 (@159105)", and for | 86 return internal::ParseBrowserInfo(data, &browser_info_); |
| 91 // this example |blink_revision| should be 159105 | |
| 92 size_t before = blink_version.find('@'); | |
| 93 size_t after = blink_version.find(')'); | |
| 94 if (before == std::string::npos || after == std::string::npos) { | |
| 95 return Status(kUnknownError, | |
| 96 "unrecognized Blink version: " + blink_version); | |
| 97 } | |
| 98 | |
| 99 std::string blink_revision_string = blink_version.substr(before + 1, | |
| 100 after - before - 1); | |
| 101 int blink_revision_int; | |
| 102 if (!base::StringToInt(blink_revision_string, &blink_revision_int)) { | |
| 103 return Status(kUnknownError, | |
| 104 "unrecognized Blink revision: " + blink_revision_string); | |
| 105 } | |
| 106 | |
| 107 browser_info_.blink_revision = blink_revision_int; | |
| 108 | |
| 109 if (browser_version.empty()) { | |
| 110 browser_info_.browser_name = "content shell"; | |
| 111 return Status(kOk); | |
| 112 } | |
| 113 if (browser_version.find("Version/") == 0u) { | |
| 114 browser_info_.browser_name = "webview"; | |
| 115 return Status(kOk); | |
| 116 } | |
| 117 std::string prefix = "Chrome/"; | |
| 118 if (browser_version.find(prefix) != 0u) { | |
| 119 return Status(kUnknownError, | |
| 120 "unrecognized Chrome version: " + browser_version); | |
| 121 } | |
| 122 | |
| 123 std::string stripped_version = browser_version.substr(prefix.length()); | |
| 124 int temp_build_no; | |
| 125 std::vector<std::string> version_parts; | |
| 126 base::SplitString(stripped_version, '.', &version_parts); | |
| 127 if (version_parts.size() != 4 || | |
| 128 !base::StringToInt(version_parts[2], &temp_build_no)) { | |
| 129 return Status(kUnknownError, | |
| 130 "unrecognized Chrome version: " + browser_version); | |
| 131 } | |
| 132 | |
| 133 browser_info_.browser_name = "chrome"; | |
| 134 browser_info_.browser_version = stripped_version; | |
| 135 browser_info_.build_no = temp_build_no; | |
| 136 | |
| 137 return Status(kOk); | |
| 138 } | 87 } |
| 139 | 88 |
| 140 Status DevToolsHttpClient::GetWebViewsInfo(WebViewsInfo* views_info) { | 89 Status DevToolsHttpClient::GetWebViewsInfo(WebViewsInfo* views_info) { |
| 141 std::string data; | 90 std::string data; |
| 142 if (!FetchUrlAndLog(server_url_ + "/json", context_getter_.get(), &data)) | 91 if (!FetchUrlAndLog(server_url_ + "/json", context_getter_.get(), &data)) |
| 143 return Status(kChromeNotReachable); | 92 return Status(kChromeNotReachable); |
| 144 | 93 |
| 145 return internal::ParseWebViewsInfo(data, views_info); | 94 return internal::ParseWebViewsInfo(data, views_info); |
| 146 } | 95 } |
| 147 | 96 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 } | 137 } |
| 189 | 138 |
| 190 const BrowserInfo* DevToolsHttpClient::browser_info() { | 139 const BrowserInfo* DevToolsHttpClient::browser_info() { |
| 191 return &browser_info_; | 140 return &browser_info_; |
| 192 } | 141 } |
| 193 | 142 |
| 194 const DeviceMetrics* DevToolsHttpClient::device_metrics() { | 143 const DeviceMetrics* DevToolsHttpClient::device_metrics() { |
| 195 return device_metrics_.get(); | 144 return device_metrics_.get(); |
| 196 } | 145 } |
| 197 | 146 |
| 198 Status DevToolsHttpClient::GetVersion(std::string* browser_version, | |
| 199 std::string* blink_version) { | |
| 200 std::string data; | |
| 201 if (!FetchUrlAndLog( | |
| 202 server_url_ + "/json/version", context_getter_.get(), &data)) | |
| 203 return Status(kChromeNotReachable); | |
| 204 | |
| 205 return internal::ParseVersionInfo(data, browser_version, blink_version); | |
| 206 } | |
| 207 | |
| 208 Status DevToolsHttpClient::CloseFrontends(const std::string& for_client_id) { | 147 Status DevToolsHttpClient::CloseFrontends(const std::string& for_client_id) { |
| 209 WebViewsInfo views_info; | 148 WebViewsInfo views_info; |
| 210 Status status = GetWebViewsInfo(&views_info); | 149 Status status = GetWebViewsInfo(&views_info); |
| 211 if (status.IsError()) | 150 if (status.IsError()) |
| 212 return status; | 151 return status; |
| 213 | 152 |
| 214 // Close frontends. Usually frontends are docked in the same page, although | 153 // Close frontends. Usually frontends are docked in the same page, although |
| 215 // some may be in tabs (undocked, chrome://inspect, the DevTools | 154 // some may be in tabs (undocked, chrome://inspect, the DevTools |
| 216 // discovery page, etc.). Tabs can be closed via the DevTools HTTP close | 155 // discovery page, etc.). Tabs can be closed via the DevTools HTTP close |
| 217 // URL, but docked frontends can only be closed, by design, by connecting | 156 // URL, but docked frontends can only be closed, by design, by connecting |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 type = WebViewInfo::kOther; | 275 type = WebViewInfo::kOther; |
| 337 else | 276 else |
| 338 return Status(kUnknownError, | 277 return Status(kUnknownError, |
| 339 "DevTools returned unknown type:" + type_as_string); | 278 "DevTools returned unknown type:" + type_as_string); |
| 340 temp_views_info.push_back(WebViewInfo(id, debugger_url, url, type)); | 279 temp_views_info.push_back(WebViewInfo(id, debugger_url, url, type)); |
| 341 } | 280 } |
| 342 *views_info = WebViewsInfo(temp_views_info); | 281 *views_info = WebViewsInfo(temp_views_info); |
| 343 return Status(kOk); | 282 return Status(kOk); |
| 344 } | 283 } |
| 345 | 284 |
| 346 Status ParseVersionInfo(const std::string& data, | 285 Status ParseBrowserInfo(const std::string& data, BrowserInfo* browser_info) { |
| 347 std::string* browser_version, | |
| 348 std::string* blink_version) { | |
| 349 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); | 286 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); |
| 350 if (!value.get()) | 287 if (!value.get()) |
| 351 return Status(kUnknownError, "version info not in JSON"); | 288 return Status(kUnknownError, "version info not in JSON"); |
| 289 | |
| 352 base::DictionaryValue* dict; | 290 base::DictionaryValue* dict; |
| 353 if (!value->GetAsDictionary(&dict)) | 291 if (!value->GetAsDictionary(&dict)) |
| 354 return Status(kUnknownError, "version info not a dictionary"); | 292 return Status(kUnknownError, "version info not a dictionary"); |
| 355 if (!dict->GetString("Browser", browser_version)) { | 293 |
| 356 return Status( | 294 std::string browser; |
| 357 kUnknownError, | 295 if (!dict->GetString("Browser", &browser)) { |
| 358 "Chrome version must be >= " + GetMinimumSupportedChromeVersion(), | 296 return Status(kUnknownError, |
| 359 Status(kUnknownError, "version info doesn't include string 'Browser'")); | 297 "version info doesn't include string 'Browser'"); |
| 360 } | 298 } |
| 361 if (!dict->GetString("WebKit-Version", blink_version)) { | 299 |
| 300 std::string blink_version; | |
| 301 if (!dict->GetString("WebKit-Version", &blink_version)) { | |
| 362 return Status(kUnknownError, | 302 return Status(kUnknownError, |
| 363 "version info doesn't include string 'WebKit-Version'"); | 303 "version info doesn't include string 'WebKit-Version'"); |
| 364 } | 304 } |
| 305 | |
| 306 Status status = internal::ParseBrowserString(browser, | |
| 307 &browser_info->browser_name, | |
| 308 &browser_info->browser_version, | |
| 309 &browser_info->build_no); | |
| 310 | |
| 311 if (status.IsError()) | |
| 312 return status; | |
| 313 | |
| 314 return internal::ParseBlinkVersionString(blink_version, | |
| 315 &browser_info->blink_revision); | |
| 316 } | |
| 317 | |
| 318 Status ParseBrowserString(const std::string& browser_string, | |
| 319 std::string* browser_name, | |
| 320 std::string* browser_version, | |
| 321 int* build_no) { | |
| 322 if (browser_string.empty()) { | |
| 323 *browser_name = "content shell"; | |
| 324 return Status(kOk); | |
| 325 } | |
| 326 | |
| 327 if (browser_string.find("Version/") == 0u) { | |
| 328 *browser_name = "webview"; | |
| 329 return Status(kOk); | |
| 330 } | |
| 331 | |
| 332 std::string prefix = "Chrome/"; | |
| 333 if (browser_string.find(prefix) == 0u) { | |
| 334 *browser_name = std::string("chrome"); | |
|
stgao
2014/09/29 23:09:54
remove std::string?
samuong
2014/09/30 04:03:49
Done.
| |
| 335 *browser_version = browser_string.substr(prefix.length()); | |
| 336 | |
| 337 std::vector<std::string> version_parts; | |
| 338 base::SplitString(*browser_version, '.', &version_parts); | |
| 339 if (version_parts.size() != 4 || | |
| 340 !base::StringToInt(version_parts[2], build_no)) { | |
| 341 return Status(kUnknownError, | |
| 342 "unrecognized Chrome version: " + *browser_version); | |
| 343 } | |
| 344 | |
| 345 return Status(kOk); | |
| 346 } | |
| 347 | |
| 348 return Status(kUnknownError, | |
| 349 "unrecognized Chrome version: " + browser_string); | |
| 350 } | |
| 351 | |
| 352 Status ParseBlinkVersionString(const std::string& blink_version, | |
| 353 int* blink_revision) { | |
| 354 size_t before = blink_version.find('@'); | |
| 355 size_t after = blink_version.find(')'); | |
| 356 if (before == std::string::npos || after == std::string::npos) { | |
| 357 return Status(kUnknownError, | |
| 358 "unrecognized Blink version string: " + blink_version); | |
| 359 } | |
| 360 | |
| 361 // Chrome OS reports its Blink revision as a (non-abbreviated) git hash. In | |
| 362 // this case, ignore it and use the default blink revision, otherwise convert | |
|
stgao
2014/09/29 23:09:54
Will using the default blink revision support back
samuong
2014/09/30 04:03:48
This is just the code to parse the version json an
| |
| 363 // the svn revision number to an int. | |
| 364 std::string revision = blink_version.substr(before + 1, after - before - 1); | |
| 365 if (!IsGitHash(revision) && !base::StringToInt(revision, blink_revision)) { | |
| 366 return Status(kUnknownError, "unrecognized Blink revision: " + revision); | |
| 367 } | |
| 368 | |
| 365 return Status(kOk); | 369 return Status(kOk); |
| 366 } | 370 } |
| 367 | 371 |
| 372 bool IsGitHash(const std::string& revision) { | |
| 373 const int kGitHashLength = 40; | |
|
stgao
2014/09/29 23:09:54
Constant variable could be defined outside of meth
samuong
2014/09/30 04:03:48
Is there any reason you prefer this? Defining it i
stgao
2014/09/30 18:13:37
The style guide says it is optional, not required.
| |
| 374 return revision.size() == kGitHashLength | |
| 375 && base::ContainsOnlyChars(revision, "0123456789abcdef"); | |
|
stgao
2014/09/29 23:09:54
Does the function test with uppercase and lowercas
samuong
2014/09/30 04:03:48
Done.
| |
| 376 } | |
| 377 | |
| 368 } // namespace internal | 378 } // namespace internal |
| OLD | NEW |