Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/test/chromedriver/chrome_impl.h" | 5 #include "chrome/test/chromedriver/chrome_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <list> | 8 #include <list> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 12 #include "base/string_split.h" | 12 #include "base/string_split.h" |
| 13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/threading/platform_thread.h" | 15 #include "base/threading/platform_thread.h" |
| 16 #include "base/time.h" | 16 #include "base/time.h" |
| 17 #include "base/values.h" | 17 #include "base/values.h" |
| 18 #include "chrome/test/chromedriver/devtools_client_impl.h" | 18 #include "chrome/test/chromedriver/devtools_client_impl.h" |
| 19 #include "chrome/test/chromedriver/javascript_dialog_manager.h" | 19 #include "chrome/test/chromedriver/javascript_dialog_manager.h" |
| 20 #include "chrome/test/chromedriver/net/net_util.h" | 20 #include "chrome/test/chromedriver/net/net_util.h" |
| 21 #include "chrome/test/chromedriver/net/sync_websocket_impl.h" | 21 #include "chrome/test/chromedriver/net/sync_websocket_impl.h" |
| 22 #include "chrome/test/chromedriver/net/url_request_context_getter.h" | 22 #include "chrome/test/chromedriver/net/url_request_context_getter.h" |
| 23 #include "chrome/test/chromedriver/status.h" | 23 #include "chrome/test/chromedriver/status.h" |
| 24 #include "chrome/test/chromedriver/version.h" | 24 #include "chrome/test/chromedriver/version.h" |
| 25 #include "chrome/test/chromedriver/web_view_impl.h" | 25 #include "chrome/test/chromedriver/web_view_impl.h" |
| 26 #include "googleurl/src/gurl.h" | 26 #include "googleurl/src/gurl.h" |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 typedef std::list<internal::WebViewInfo> WebViewInfoList; | |
| 31 | |
| 30 Status FetchVersionInfo(URLRequestContextGetter* context_getter, | 32 Status FetchVersionInfo(URLRequestContextGetter* context_getter, |
| 31 int port, | 33 int port, |
| 32 std::string* version) { | 34 std::string* version) { |
| 33 std::string url = base::StringPrintf( | 35 std::string url = base::StringPrintf( |
| 34 "http://127.0.0.1:%d/json/version", port); | 36 "http://127.0.0.1:%d/json/version", port); |
| 35 std::string data; | 37 std::string data; |
| 36 if (!FetchUrl(GURL(url), context_getter, &data)) | 38 if (!FetchUrl(GURL(url), context_getter, &data)) |
| 37 return Status(kChromeNotReachable); | 39 return Status(kChromeNotReachable); |
| 38 return internal::ParseVersionInfo(data, version); | 40 return internal::ParseVersionInfo(data, version); |
| 39 } | 41 } |
| 40 | 42 |
| 41 Status FetchPagesInfo(URLRequestContextGetter* context_getter, | 43 Status FetchWebViewsInfo(URLRequestContextGetter* context_getter, |
| 42 int port, | 44 int port, |
| 43 std::list<std::string>* page_ids) { | 45 WebViewInfoList* web_view_info_list) { |
| 44 std::string url = base::StringPrintf("http://127.0.0.1:%d/json", port); | 46 std::string url = base::StringPrintf("http://127.0.0.1:%d/json", port); |
| 45 std::string data; | 47 std::string data; |
| 46 if (!FetchUrl(GURL(url), context_getter, &data)) | 48 if (!FetchUrl(GURL(url), context_getter, &data)) |
| 47 return Status(kChromeNotReachable); | 49 return Status(kChromeNotReachable); |
| 48 return internal::ParsePagesInfo(data, page_ids); | 50 |
| 51 return ParsePagesInfo(data, web_view_info_list); | |
|
kkania
2013/03/05 17:01:13
how does this know which function without the inte
kkania
2013/03/05 17:01:13
adjust the naming here too
chrisgao (Use stgao instead)
2013/03/06 01:19:54
Done.
chrisgao (Use stgao instead)
2013/03/06 01:19:54
whooops...the compiler even didn't raise an error.
| |
| 52 } | |
| 53 | |
| 54 bool DoesWebViewExist(const std::string& web_view_id, | |
|
kkania
2013/03/05 17:01:13
You could change this to:
WebViewInfo* GetWebViewI
chrisgao (Use stgao instead)
2013/03/06 01:19:54
Done.
| |
| 55 const WebViewInfoList& info_list) { | |
|
kkania
2013/03/05 17:01:13
indent
chrisgao (Use stgao instead)
2013/03/06 01:19:54
Done.
| |
| 56 for (WebViewInfoList::const_iterator it = info_list.begin(); | |
| 57 it != info_list.end(); ++it) { | |
| 58 if (it->id == web_view_id) | |
| 59 return true; | |
| 60 } | |
| 61 return false; | |
| 49 } | 62 } |
| 50 | 63 |
| 51 Status CloseWebView(URLRequestContextGetter* context_getter, | 64 Status CloseWebView(URLRequestContextGetter* context_getter, |
| 52 int port, | 65 int port, |
| 53 const std::string& web_view_id) { | 66 const std::string& web_view_id) { |
| 54 std::list<std::string> ids; | 67 WebViewInfoList web_view_info_list; |
| 55 Status status = FetchPagesInfo(context_getter, port, &ids); | 68 Status status = FetchWebViewsInfo(context_getter, port, &web_view_info_list); |
| 56 if (status.IsError()) | 69 if (status.IsError()) |
| 57 return status; | 70 return status; |
| 58 if (std::find(ids.begin(), ids.end(), web_view_id) == ids.end()) | 71 if (!DoesWebViewExist(web_view_id, web_view_info_list)) |
| 59 return Status(kOk); | 72 return Status(kOk); |
| 60 | 73 |
| 61 bool is_last_web_view = ids.size() == 1; | 74 bool is_last_web_view = web_view_info_list.size() == 1u; |
| 62 | 75 |
| 63 std::string url = base::StringPrintf( | 76 std::string url = base::StringPrintf( |
| 64 "http://127.0.0.1:%d/json/close/%s", port, web_view_id.c_str()); | 77 "http://127.0.0.1:%d/json/close/%s", port, web_view_id.c_str()); |
| 65 std::string data; | 78 std::string data; |
| 66 if (!FetchUrl(GURL(url), context_getter, &data)) | 79 if (!FetchUrl(GURL(url), context_getter, &data)) |
| 67 return is_last_web_view ? Status(kOk) : Status(kChromeNotReachable); | 80 return is_last_web_view ? Status(kOk) : Status(kChromeNotReachable); |
| 68 if (data != "Target is closing") | 81 if (data != "Target is closing") |
| 69 return Status(kOk); | 82 return Status(kOk); |
| 70 | 83 |
| 71 // Wait for the target window to be completely closed. | 84 // Wait for the target window to be completely closed. |
| 72 base::Time deadline = base::Time::Now() + base::TimeDelta::FromSeconds(20); | 85 base::Time deadline = base::Time::Now() + base::TimeDelta::FromSeconds(20); |
| 73 while (base::Time::Now() < deadline) { | 86 while (base::Time::Now() < deadline) { |
| 74 ids.clear(); | 87 web_view_info_list.clear(); |
| 75 status = FetchPagesInfo(context_getter, port, &ids); | 88 status = FetchWebViewsInfo(context_getter, port, &web_view_info_list); |
| 76 if (is_last_web_view && status.code() == kChromeNotReachable) | 89 if (is_last_web_view && status.code() == kChromeNotReachable) |
| 77 return Status(kOk); // Closing the last web view leads chrome to quit. | 90 return Status(kOk); // Closing the last web view leads chrome to quit. |
| 78 if (status.IsError()) | 91 if (status.IsError()) |
| 79 return status; | 92 return status; |
| 80 if (std::find(ids.begin(), ids.end(), web_view_id) == ids.end()) | 93 if (!DoesWebViewExist(web_view_id, web_view_info_list)) |
| 81 return Status(kOk); | 94 return Status(kOk); |
| 82 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); | 95 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); |
| 83 } | 96 } |
| 84 | 97 |
| 85 return Status(kUnknownError, "failed to close window in 20 seconds"); | 98 return Status(kUnknownError, "failed to close window in 20 seconds"); |
| 86 } | 99 } |
| 87 | 100 |
| 101 Status FakeCloseWebView() { | |
| 102 // This is for the docked DevTools frontend only. | |
| 103 return Status(kUnknownError, | |
| 104 "docked DevTools frontend should be closed by Javascript"); | |
| 105 } | |
| 106 | |
| 107 Status FakeCloseDevToolsFrontend() { | |
| 108 // This is for the docked DevTools frontend only. | |
| 109 return Status(kOk); | |
| 110 } | |
| 111 | |
| 112 Status CloseDevToolsFrontend(ChromeImpl* chrome, | |
| 113 const SyncWebSocketFactory& socket_factory, | |
| 114 URLRequestContextGetter* context_getter, | |
| 115 int port, | |
| 116 const std::string& web_view_id) { | |
| 117 WebViewInfoList web_view_info_list; | |
| 118 Status status = FetchWebViewsInfo(context_getter, port, &web_view_info_list); | |
| 119 if (status.IsError()) | |
| 120 return status; | |
| 121 | |
| 122 std::list<std::string> tab_frontend_ids; | |
| 123 std::list<std::string> docked_frontend_ids; | |
| 124 // Filter out DevTools frontend. | |
| 125 for (WebViewInfoList::const_iterator it = web_view_info_list.begin(); | |
| 126 it != web_view_info_list.end(); ++it) { | |
| 127 if (it->url.find("chrome-devtools://") == 0u) { | |
| 128 if (it->type == internal::WebViewInfo::kPage) | |
| 129 tab_frontend_ids.push_back(it->id); | |
| 130 else if (it->type == internal::WebViewInfo::kOther) | |
| 131 docked_frontend_ids.push_back(it->id); | |
| 132 else | |
| 133 return Status(kUnknownError, "unknown type of DevTools frontend"); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 // Close tab DevTools frontend as if closing a normal web view. | |
| 138 for (std::list<std::string>::const_iterator it = tab_frontend_ids.begin(); | |
| 139 it != tab_frontend_ids.end(); ++it) { | |
| 140 status = CloseWebView(context_getter, port, *it); | |
| 141 if (status.IsError()) | |
| 142 return status; | |
| 143 } | |
| 144 | |
| 145 // Close docked DevTools frontend by Javascript. | |
| 146 for (std::list<std::string>::const_iterator it = docked_frontend_ids.begin(); | |
| 147 it != docked_frontend_ids.end(); ++it) { | |
| 148 std::string ws_url = base::StringPrintf( | |
| 149 "ws://127.0.0.1:%d/devtools/page/%s", port, it->c_str()); | |
| 150 scoped_ptr<WebViewImpl> web_view(new WebViewImpl( | |
| 151 *it, | |
| 152 new DevToolsClientImpl(socket_factory, ws_url, | |
| 153 base::Bind(&FakeCloseDevToolsFrontend)), | |
| 154 chrome, base::Bind(&FakeCloseWebView))); | |
| 155 | |
| 156 status = web_view->ConnectIfNecessary(); | |
| 157 if (status.IsError()) | |
| 158 return status; | |
| 159 | |
| 160 scoped_ptr<base::Value> result; | |
| 161 status = web_view->EvaluateScript( | |
| 162 "", "document.getElementById('close-button-right').click();", &result); | |
| 163 // Ignore disconnected error, because the DevTools frontend is closed. | |
| 164 if (status.IsError() && status.code() != kDisconnected) | |
| 165 return status; | |
| 166 } | |
| 167 | |
| 168 // Wait until DevTools UI disconnects from the given web view. | |
| 169 base::Time deadline = base::Time::Now() + base::TimeDelta::FromSeconds(20); | |
| 170 bool web_view_still_open = false; | |
| 171 while (base::Time::Now() < deadline) { | |
| 172 web_view_info_list.clear(); | |
| 173 status = FetchWebViewsInfo(context_getter, port, &web_view_info_list); | |
| 174 if (status.IsError()) | |
| 175 return status; | |
| 176 | |
| 177 web_view_still_open = false; | |
| 178 for (WebViewInfoList::const_iterator it = web_view_info_list.begin(); | |
| 179 it != web_view_info_list.end(); ++it) { | |
| 180 if (it->id == web_view_id) { | |
| 181 if (!it->debugger_url.empty()) | |
| 182 return Status(kOk); | |
| 183 web_view_still_open = true; | |
| 184 break; | |
| 185 } | |
| 186 } | |
| 187 if (!web_view_still_open) | |
| 188 return Status(kUnknownError, "window closed while closing devtools"); | |
| 189 | |
| 190 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); | |
| 191 } | |
| 192 | |
| 193 return Status(kUnknownError, "failed to close DevTools frontend"); | |
| 194 } | |
| 195 | |
| 88 } // namespace | 196 } // namespace |
| 89 | 197 |
| 90 ChromeImpl::ChromeImpl(URLRequestContextGetter* context_getter, | 198 ChromeImpl::ChromeImpl(URLRequestContextGetter* context_getter, |
| 91 int port, | 199 int port, |
| 92 const SyncWebSocketFactory& socket_factory) | 200 const SyncWebSocketFactory& socket_factory) |
| 93 : context_getter_(context_getter), | 201 : context_getter_(context_getter), |
| 94 port_(port), | 202 port_(port), |
| 95 socket_factory_(socket_factory), | 203 socket_factory_(socket_factory), |
| 96 version_("unknown version"), | 204 version_("unknown version"), |
| 97 build_no_(0) {} | 205 build_no_(0) {} |
| 98 | 206 |
| 99 ChromeImpl::~ChromeImpl() { | 207 ChromeImpl::~ChromeImpl() { |
| 100 web_view_map_.clear(); | 208 web_view_map_.clear(); |
| 101 } | 209 } |
| 102 | 210 |
| 103 std::string ChromeImpl::GetVersion() { | 211 std::string ChromeImpl::GetVersion() { |
| 104 return version_; | 212 return version_; |
| 105 } | 213 } |
| 106 | 214 |
| 107 Status ChromeImpl::GetWebViews(std::list<WebView*>* web_views) { | 215 Status ChromeImpl::GetWebViews(std::list<WebView*>* web_views) { |
| 108 std::list<std::string> ids; | 216 WebViewInfoList web_view_info_list; |
| 109 Status status = FetchPagesInfo(context_getter_, port_, &ids); | 217 Status status = FetchWebViewsInfo( |
| 218 context_getter_, port_, &web_view_info_list); | |
| 110 if (status.IsError()) | 219 if (status.IsError()) |
| 111 return status; | 220 return status; |
| 112 | 221 |
| 113 std::list<WebView*> internal_web_views; | 222 std::list<WebView*> internal_web_views; |
| 114 for (std::list<std::string>::const_iterator it = ids.begin(); | 223 for (WebViewInfoList::const_iterator it = web_view_info_list.begin(); |
| 115 it != ids.end(); ++it) { | 224 it != web_view_info_list.end(); ++it) { |
| 116 WebViewMap::const_iterator found = web_view_map_.find(*it); | 225 WebViewMap::const_iterator found = web_view_map_.find(it->id); |
| 117 if (found != web_view_map_.end()) { | 226 if (found != web_view_map_.end()) { |
| 118 internal_web_views.push_back(found->second.get()); | 227 internal_web_views.push_back(found->second.get()); |
| 119 continue; | 228 continue; |
| 120 } | 229 } |
| 121 | 230 |
| 122 std::string ws_url = base::StringPrintf( | 231 std::string ws_url = base::StringPrintf( |
| 123 "ws://127.0.0.1:%d/devtools/page/%s", port_, it->c_str()); | 232 "ws://127.0.0.1:%d/devtools/page/%s", port_, it->id.c_str()); |
| 124 web_view_map_[*it] = make_linked_ptr(new WebViewImpl( | 233 DevToolsClientImpl::FrontendCloserFunc frontend_closer_func = base::Bind( |
| 125 *it, new DevToolsClientImpl(socket_factory_, ws_url), | 234 &CloseDevToolsFrontend, this, socket_factory_, |
| 126 this, base::Bind(&CloseWebView, context_getter_, port_, *it))); | 235 context_getter_, port_, it->id); |
| 127 internal_web_views.push_back(web_view_map_[*it].get()); | 236 web_view_map_[it->id] = make_linked_ptr(new WebViewImpl( |
| 237 it->id, | |
| 238 new DevToolsClientImpl(socket_factory_, ws_url, frontend_closer_func), | |
| 239 this, | |
| 240 base::Bind(&CloseWebView, context_getter_, port_, it->id))); | |
| 241 internal_web_views.push_back(web_view_map_[it->id].get()); | |
| 128 } | 242 } |
| 129 | 243 |
| 130 web_views->swap(internal_web_views); | 244 web_views->swap(internal_web_views); |
| 131 return Status(kOk); | 245 return Status(kOk); |
| 132 } | 246 } |
| 133 | 247 |
| 134 Status ChromeImpl::IsJavaScriptDialogOpen(bool* is_open) { | 248 Status ChromeImpl::IsJavaScriptDialogOpen(bool* is_open) { |
| 135 JavaScriptDialogManager* manager; | 249 JavaScriptDialogManager* manager; |
| 136 Status status = GetDialogManagerForOpenDialog(&manager); | 250 Status status = GetDialogManagerForOpenDialog(&manager); |
| 137 if (status.IsError()) | 251 if (status.IsError()) |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 break; | 291 break; |
| 178 if (status.code() != kChromeNotReachable) | 292 if (status.code() != kChromeNotReachable) |
| 179 return status; | 293 return status; |
| 180 } | 294 } |
| 181 if (status.IsError()) | 295 if (status.IsError()) |
| 182 return status; | 296 return status; |
| 183 status = ParseAndCheckVersion(version); | 297 status = ParseAndCheckVersion(version); |
| 184 if (status.IsError()) | 298 if (status.IsError()) |
| 185 return status; | 299 return status; |
| 186 | 300 |
| 187 std::list<std::string> page_ids; | 301 WebViewInfoList web_view_info_list; |
| 188 while (base::Time::Now() < deadline) { | 302 while (base::Time::Now() < deadline) { |
| 189 FetchPagesInfo(context_getter_, port_, &page_ids); | 303 FetchWebViewsInfo(context_getter_, port_, &web_view_info_list); |
| 190 if (page_ids.empty()) | 304 if (web_view_info_list.empty()) |
| 191 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 305 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
| 192 else | 306 else |
| 193 break; | 307 return Status(kOk); |
| 194 } | 308 } |
| 195 if (page_ids.empty()) | 309 return Status(kUnknownError, "unable to discover open pages"); |
| 196 return Status(kUnknownError, "unable to discover open pages"); | |
| 197 | |
| 198 return Status(kOk); | |
| 199 } | 310 } |
| 200 | 311 |
| 201 int ChromeImpl::GetPort() const { | 312 int ChromeImpl::GetPort() const { |
| 202 return port_; | 313 return port_; |
| 203 } | 314 } |
| 204 | 315 |
| 205 Status ChromeImpl::GetDialogManagerForOpenDialog( | 316 Status ChromeImpl::GetDialogManagerForOpenDialog( |
| 206 JavaScriptDialogManager** manager) { | 317 JavaScriptDialogManager** manager) { |
| 207 std::list<WebView*> web_views; | 318 std::list<WebView*> web_views; |
| 208 Status status = GetWebViews(&web_views); | 319 Status status = GetWebViews(&web_views); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 return Status(kUnknownError, "Chrome version must be >= " + | 356 return Status(kUnknownError, "Chrome version must be >= " + |
| 246 GetMinimumSupportedChromeVersion()); | 357 GetMinimumSupportedChromeVersion()); |
| 247 } | 358 } |
| 248 version_ = stripped_version; | 359 version_ = stripped_version; |
| 249 build_no_ = build_no; | 360 build_no_ = build_no; |
| 250 return Status(kOk); | 361 return Status(kOk); |
| 251 } | 362 } |
| 252 | 363 |
| 253 namespace internal { | 364 namespace internal { |
| 254 | 365 |
| 366 WebViewInfo::WebViewInfo(const std::string& id, | |
| 367 const std::string& debugger_url, | |
| 368 const std::string& url, | |
| 369 Type type) | |
| 370 : id(id), debugger_url(debugger_url), url(url), type(type) {} | |
| 371 | |
| 255 Status ParsePagesInfo(const std::string& data, | 372 Status ParsePagesInfo(const std::string& data, |
| 256 std::list<std::string>* page_ids) { | 373 std::list<WebViewInfo>* web_view_info_list) { |
| 257 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); | 374 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); |
| 258 if (!value.get()) | 375 if (!value.get()) |
| 259 return Status(kUnknownError, "DevTools returned invalid JSON"); | 376 return Status(kUnknownError, "DevTools returned invalid JSON"); |
| 260 base::ListValue* list; | 377 base::ListValue* list; |
| 261 if (!value->GetAsList(&list)) | 378 if (!value->GetAsList(&list)) |
| 262 return Status(kUnknownError, "DevTools did not return list"); | 379 return Status(kUnknownError, "DevTools did not return list"); |
| 263 | 380 |
| 264 std::list<std::string> ids; | 381 std::list<WebViewInfo> web_view_info_list_tmp; |
| 265 for (size_t i = 0; i < list->GetSize(); ++i) { | 382 for (size_t i = 0; i < list->GetSize(); ++i) { |
| 266 base::DictionaryValue* info; | 383 base::DictionaryValue* info; |
| 267 if (!list->GetDictionary(i, &info)) | 384 if (!list->GetDictionary(i, &info)) |
| 268 return Status(kUnknownError, "DevTools contains non-dictionary item"); | 385 return Status(kUnknownError, "DevTools contains non-dictionary item"); |
| 386 std::string id; | |
| 387 if (!info->GetString("id", &id)) | |
| 388 return Status(kUnknownError, "DevTools did not include id"); | |
| 269 std::string type; | 389 std::string type; |
| 270 if (!info->GetString("type", &type)) | 390 if (!info->GetString("type", &type)) |
| 271 return Status(kUnknownError, "DevTools did not include type"); | 391 return Status(kUnknownError, "DevTools did not include type"); |
| 272 if (type != "page") | 392 std::string url; |
| 273 continue; | 393 if (!info->GetString("url", &url)) |
| 274 std::string id; | 394 return Status(kUnknownError, "DevTools did not include url"); |
| 275 if (!info->GetString("id", &id)) | 395 std::string debugger_url; |
| 276 return Status(kUnknownError, "DevTools did not include id"); | 396 info->GetString("webSocketDebuggerUrl", &debugger_url); |
| 277 ids.push_back(id); | 397 if (type == "page") |
| 398 web_view_info_list_tmp.push_back( | |
| 399 WebViewInfo(id, debugger_url, url, internal::WebViewInfo::kPage)); | |
| 400 else if (type == "other") | |
| 401 web_view_info_list_tmp.push_back( | |
| 402 WebViewInfo(id, debugger_url, url, internal::WebViewInfo::kOther)); | |
| 403 else | |
| 404 return Status(kUnknownError, "DevTools returned unknown type:" + type); | |
| 278 } | 405 } |
| 279 page_ids->swap(ids); | 406 web_view_info_list->swap(web_view_info_list_tmp); |
| 280 return Status(kOk); | 407 return Status(kOk); |
| 281 } | 408 } |
| 282 | 409 |
| 283 Status ParseVersionInfo(const std::string& data, | 410 Status ParseVersionInfo(const std::string& data, |
| 284 std::string* version) { | 411 std::string* version) { |
| 285 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); | 412 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); |
| 286 if (!value.get()) | 413 if (!value.get()) |
| 287 return Status(kUnknownError, "version info not in JSON"); | 414 return Status(kUnknownError, "version info not in JSON"); |
| 288 base::DictionaryValue* dict; | 415 base::DictionaryValue* dict; |
| 289 if (!value->GetAsDictionary(&dict)) | 416 if (!value->GetAsDictionary(&dict)) |
| 290 return Status(kUnknownError, "version info not a dictionary"); | 417 return Status(kUnknownError, "version info not a dictionary"); |
| 291 if (!dict->GetString("Browser", version)) { | 418 if (!dict->GetString("Browser", version)) { |
| 292 return Status( | 419 return Status( |
| 293 kUnknownError, "Chrome version must be >= 26", | 420 kUnknownError, "Chrome version must be >= 26", |
| 294 Status(kUnknownError, "version info doesn't include string 'Browser'")); | 421 Status(kUnknownError, "version info doesn't include string 'Browser'")); |
| 295 } | 422 } |
| 296 return Status(kOk); | 423 return Status(kOk); |
| 297 } | 424 } |
| 298 | 425 |
| 299 } // namespace internal | 426 } // namespace internal |
| OLD | NEW |