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

Side by Side Diff: chrome/browser/devtools/devtools_adb_bridge.cc

Issue 22536006: chrome://inspect: Better support for multiple browsers and older versions of mobile Chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 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
OLDNEW
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/browser/devtools/devtools_adb_bridge.h" 5 #include "chrome/browser/devtools/devtools_adb_bridge.h"
6 6
7 #include <map> 7 #include <map>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
(...skipping 29 matching lines...) Expand all
40 40
41 using content::BrowserThread; 41 using content::BrowserThread;
42 42
43 namespace { 43 namespace {
44 44
45 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread"; 45 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
46 static const char kHostDevicesCommand[] = "host:devices"; 46 static const char kHostDevicesCommand[] = "host:devices";
47 static const char kHostTransportCommand[] = "host:transport:%s|%s"; 47 static const char kHostTransportCommand[] = "host:transport:%s|%s";
48 static const char kLocalAbstractCommand[] = "localabstract:%s"; 48 static const char kLocalAbstractCommand[] = "localabstract:%s";
49 static const char kDeviceModelCommand[] = "shell:getprop ro.product.model"; 49 static const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
50 static const char kUnknownModel[] = "Unknown"; 50 static const char kLocalChrome[] = "Local Chrome";
51 static const char kChrome[] = "Chrome";
51 static const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix"; 52 static const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
52 53
53 static const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n"; 54 static const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
54 static const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n"; 55 static const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
55 static const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n"; 56 static const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n";
56 static const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n"; 57 static const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n";
57 const int kAdbPort = 5037; 58 const int kAdbPort = 5037;
58 const int kBufferSize = 16 * 1024; 59 const int kBufferSize = 16 * 1024;
59 const int kAdbPollingIntervalMs = 1000; 60 const int kAdbPollingIntervalMs = 1000;
60 61
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 BrowserThread::UI, FROM_HERE, 206 BrowserThread::UI, FROM_HERE,
206 base::Bind(&AdbPagesCommand::Respond, this)); 207 base::Bind(&AdbPagesCommand::Respond, this));
207 return; 208 return;
208 } 209 }
209 210
210 #if defined(DEBUG_DEVTOOLS) 211 #if defined(DEBUG_DEVTOOLS)
211 // For desktop remote debugging. 212 // For desktop remote debugging.
212 if (devices_.back()->serial().empty()) { 213 if (devices_.back()->serial().empty()) {
213 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = 214 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device =
214 devices_.back(); 215 devices_.back();
215 sockets_.push_back(std::string()); 216 device->set_model(kLocalChrome);
216 device->set_model(kUnknownModel);
217 remote_devices_->push_back( 217 remote_devices_->push_back(
218 new DevToolsAdbBridge::RemoteDevice(bridge_, device)); 218 new DevToolsAdbBridge::RemoteDevice(bridge_, device));
219 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
220 new DevToolsAdbBridge::RemoteBrowser(bridge_, device, std::string());
221 remote_browser->set_product(kChrome);
222 remote_devices_->back()->AddBrowser(remote_browser);
223 browsers_.push_back(remote_browser);
219 device->HttpQuery( 224 device->HttpQuery(
220 std::string(), kVersionRequest, 225 std::string(), kVersionRequest,
221 base::Bind(&AdbPagesCommand::ReceivedVersion, this)); 226 base::Bind(&AdbPagesCommand::ReceivedVersion, this));
222 return; 227 return;
223 } 228 }
224 #endif // defined(DEBUG_DEVTOOLS) 229 #endif // defined(DEBUG_DEVTOOLS)
225 230
226 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back(); 231 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
227 device->RunCommand(kDeviceModelCommand, 232 device->RunCommand(kDeviceModelCommand,
228 base::Bind(&AdbPagesCommand::ReceivedModel, this)); 233 base::Bind(&AdbPagesCommand::ReceivedModel, this));
(...skipping 17 matching lines...) Expand all
246 void ReceivedSockets(int result, 251 void ReceivedSockets(int result,
247 const std::string& response) { 252 const std::string& response) {
248 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current()); 253 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
249 if (result < 0) { 254 if (result < 0) {
250 devices_.pop_back(); 255 devices_.pop_back();
251 ProcessSerials(); 256 ProcessSerials();
252 return; 257 return;
253 } 258 }
254 259
255 ParseSocketsList(response); 260 ParseSocketsList(response);
256 if (sockets_.size() == 0) { 261 if (browsers_.size() == 0) {
257 devices_.pop_back(); 262 devices_.pop_back();
258 ProcessSerials(); 263 ProcessSerials();
259 } else { 264 } else {
260 ProcessSockets(); 265 ProcessSockets();
261 } 266 }
262 } 267 }
263 268
264 void ProcessSockets() { 269 void ProcessSockets() {
265 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current()); 270 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
266 if (sockets_.size() == 0) { 271 if (browsers_.size() == 0) {
267 devices_.pop_back(); 272 devices_.pop_back();
268 ProcessSerials(); 273 ProcessSerials();
269 } else { 274 } else {
270 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back(); 275 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
271 device->HttpQuery(sockets_.back(), kVersionRequest, 276 device->HttpQuery(browsers_.back()->socket(), kVersionRequest,
272 base::Bind(&AdbPagesCommand::ReceivedVersion, this)); 277 base::Bind(&AdbPagesCommand::ReceivedVersion, this));
273 } 278 }
274 } 279 }
275 280
276 void ReceivedVersion(int result, 281 void ReceivedVersion(int result,
277 const std::string& response) { 282 const std::string& response) {
278 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current()); 283 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
279 if (result < 0) { 284 if (result < 0) {
280 sockets_.pop_back(); 285 browsers_.pop_back();
281 ProcessSockets(); 286 ProcessSockets();
282 return; 287 return;
283 } 288 }
284 289
285 // Parse version, append to package name if available, 290 // Parse version, append to package name if available,
286 scoped_ptr<base::Value> value(base::JSONReader::Read(response)); 291 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
287 base::DictionaryValue* dict; 292 base::DictionaryValue* dict;
288 if (value && value->GetAsDictionary(&dict)) { 293 if (value && value->GetAsDictionary(&dict)) {
289 std::string browser; 294 std::string browser;
290 if (dict->GetString("Browser", &browser)) { 295 if (dict->GetString("Browser", &browser)) {
291 socket_to_package_[sockets_.back()] = base::StringPrintf( 296 std::vector<std::string> parts;
292 "%s (%s)", socket_to_package_[sockets_.back()].c_str(), 297 Tokenize(browser, "/", &parts);
293 browser.c_str()); 298 if (parts.size() == 2) {
299 if (parts[0] != "Version") // WebView has this for legacy reasons.
300 browsers_.back()->set_product(parts[0]);
301 browsers_.back()->set_version(parts[1]);
302 } else {
303 browsers_.back()->set_version(browser);
304 }
294 } 305 }
295 } 306 }
296 307
297 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back(); 308 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
298 device->HttpQuery(sockets_.back(), kPageListRequest, 309 device->HttpQuery(browsers_.back()->socket(), kPageListRequest,
299 base::Bind(&AdbPagesCommand::ReceivedPages, this)); 310 base::Bind(&AdbPagesCommand::ReceivedPages, this));
300 } 311 }
301 312
302 void ReceivedPages(int result, 313 void ReceivedPages(int result,
303 const std::string& response) { 314 const std::string& response) {
304 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current()); 315 DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
305 std::string socket = sockets_.back(); 316 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> browser = browsers_.back();
306 sockets_.pop_back(); 317 browsers_.pop_back();
307 if (result < 0) { 318 if (result < 0) {
308 ProcessSockets(); 319 ProcessSockets();
309 return; 320 return;
310 } 321 }
311 322
312 scoped_ptr<base::Value> value(base::JSONReader::Read(response)); 323 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
313 base::ListValue* list_value; 324 base::ListValue* list_value;
314 if (!value || !value->GetAsList(&list_value)) { 325 if (!value || !value->GetAsList(&list_value)) {
315 ProcessSockets(); 326 ProcessSockets();
316 return; 327 return;
317 } 328 }
318 329
319 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device = devices_.back();
320 base::Value* item; 330 base::Value* item;
321 331
322 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
323 new DevToolsAdbBridge::RemoteBrowser(
324 bridge_, device, socket, socket_to_package_[socket]);
325 remote_devices_->back()->AddBrowser(remote_browser);
326
327 for (size_t i = 0; i < list_value->GetSize(); ++i) { 332 for (size_t i = 0; i < list_value->GetSize(); ++i) {
328 list_value->Get(i, &item); 333 list_value->Get(i, &item);
329 base::DictionaryValue* dict; 334 base::DictionaryValue* dict;
330 if (!item || !item->GetAsDictionary(&dict)) 335 if (!item || !item->GetAsDictionary(&dict))
331 continue; 336 continue;
332 remote_browser->AddPage(new DevToolsAdbBridge::RemotePage( 337 browser->AddPage(new DevToolsAdbBridge::RemotePage(
333 bridge_, device, remote_browser->socket(), *dict)); 338 bridge_, browser->device(), browser->socket(), *dict));
334 } 339 }
335 ProcessSockets(); 340 ProcessSockets();
336 } 341 }
337 342
338 void Respond() { 343 void Respond() {
339 callback_.Run(remote_devices_.release()); 344 callback_.Run(remote_devices_.release());
340 } 345 }
341 346
342 void ParseSocketsList(const std::string& response) { 347 void ParseSocketsList(const std::string& response) {
343 // On Android, '/proc/net/unix' looks like this: 348 // On Android, '/proc/net/unix' looks like this:
344 // 349 //
345 // Num RefCount Protocol Flags Type St Inode Path 350 // Num RefCount Protocol Flags Type St Inode Path
346 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote 351 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote
347 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote 352 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote
348 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote 353 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote
349 // 354 //
350 // We need to find records with paths starting from '@' (abstract socket) 355 // We need to find records with paths starting from '@' (abstract socket)
351 // and containing "devtools_remote". We have to extract the inode number 356 // and containing "devtools_remote". We have to extract the inode number
352 // in order to find the owning process name. 357 // in order to find the owning process name.
353 358
354 socket_to_package_.clear(); 359 scoped_refptr<DevToolsAdbBridge::RemoteDevice> remote_device =
360 remote_devices_->back();
361
355 std::vector<std::string> entries; 362 std::vector<std::string> entries;
356 Tokenize(response, "\n", &entries); 363 Tokenize(response, "\n", &entries);
357 const std::string channel_pattern = 364 const std::string channel_pattern =
358 base::StringPrintf(kDevToolsChannelNameFormat, ""); 365 base::StringPrintf(kDevToolsChannelNameFormat, "");
359 for (size_t i = 1; i < entries.size(); ++i) { 366 for (size_t i = 1; i < entries.size(); ++i) {
360 std::vector<std::string> fields; 367 std::vector<std::string> fields;
361 Tokenize(entries[i], " ", &fields); 368 Tokenize(entries[i], " ", &fields);
362 if (fields.size() < 8) 369 if (fields.size() < 8)
363 continue; 370 continue;
364 if (fields[3] != "00010000" || fields[5] != "01") 371 if (fields[3] != "00010000" || fields[5] != "01")
365 continue; 372 continue;
366 std::string path_field = fields[7]; 373 std::string path_field = fields[7];
367 if (path_field.size() < 1 || path_field[0] != '@') 374 if (path_field.size() < 1 || path_field[0] != '@')
368 continue; 375 continue;
369 size_t socket_name_pos = path_field.find(channel_pattern); 376 size_t socket_name_pos = path_field.find(channel_pattern);
370 if (socket_name_pos == std::string::npos) 377 if (socket_name_pos == std::string::npos)
371 continue; 378 continue;
372 std::string socket = path_field.substr(1, path_field.size() - 2); 379 std::string socket = path_field.substr(1, path_field.size() - 2);
373 sockets_.push_back(socket);
374 std::string package = path_field.substr(1, socket_name_pos - 1); 380 std::string package = path_field.substr(1, socket_name_pos - 1);
375 if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) { 381 if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) {
376 package += path_field.substr( 382 package += path_field.substr(
377 socket_name_pos + channel_pattern.size(), path_field.size() - 1); 383 socket_name_pos + channel_pattern.size(), path_field.size() - 1);
378 } 384 }
379 package[0] = base::ToUpperASCII(package[0]); 385 package[0] = base::ToUpperASCII(package[0]);
380 socket_to_package_[socket] = package; 386 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser =
387 new DevToolsAdbBridge::RemoteBrowser(
388 bridge_, remote_device->device(), socket);
389 remote_browser->set_product(package);
390 remote_device->AddBrowser(remote_browser);
381 } 391 }
392 browsers_ = remote_device->browsers();
382 } 393 }
383 394
384 scoped_refptr<DevToolsAdbBridge> bridge_; 395 scoped_refptr<DevToolsAdbBridge> bridge_;
385 Callback callback_; 396 Callback callback_;
386 AndroidDevices devices_; 397 AndroidDevices devices_;
387 std::vector<std::string> sockets_; 398 DevToolsAdbBridge::RemoteBrowsers browsers_;
388 std::map<std::string, std::string> socket_to_package_;
389 scoped_ptr<DevToolsAdbBridge::RemoteDevices> remote_devices_; 399 scoped_ptr<DevToolsAdbBridge::RemoteDevices> remote_devices_;
390 }; 400 };
391 401
392 // AdbProtocolCommand --------------------------------------------------------- 402 // AdbProtocolCommand ---------------------------------------------------------
393 403
394 class AdbProtocolCommand : public AdbWebSocket::Delegate { 404 class AdbProtocolCommand : public AdbWebSocket::Delegate {
395 public: 405 public:
396 AdbProtocolCommand( 406 AdbProtocolCommand(
397 scoped_refptr<DevToolsAdbBridge> bridge_, 407 scoped_refptr<DevToolsAdbBridge> bridge_,
398 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device, 408 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 new AdbProtocolCommand( 686 new AdbProtocolCommand(
677 bridge_, device_, socket_, debug_url_, command.Serialize()); 687 bridge_, device_, socket_, debug_url_, command.Serialize());
678 } 688 }
679 689
680 DevToolsAdbBridge::RemotePage::~RemotePage() { 690 DevToolsAdbBridge::RemotePage::~RemotePage() {
681 } 691 }
682 692
683 DevToolsAdbBridge::RemoteBrowser::RemoteBrowser( 693 DevToolsAdbBridge::RemoteBrowser::RemoteBrowser(
684 scoped_refptr<DevToolsAdbBridge> bridge, 694 scoped_refptr<DevToolsAdbBridge> bridge,
685 scoped_refptr<AndroidDevice> device, 695 scoped_refptr<AndroidDevice> device,
686 const std::string& socket, 696 const std::string& socket)
687 const std::string& name)
688 : bridge_(bridge), 697 : bridge_(bridge),
689 device_(device), 698 device_(device),
690 socket_(socket), 699 socket_(socket) {
691 name_(name) {
692 } 700 }
693 701
694 void DevToolsAdbBridge::RemoteBrowser::Open(const std::string& url) { 702 void DevToolsAdbBridge::RemoteBrowser::Open(const std::string& url) {
695 bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE, 703 bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
696 base::Bind(&AndroidDevice::HttpQuery, 704 base::Bind(&AndroidDevice::HttpQuery,
697 device_, socket_, kNewPageRequest, 705 device_, socket_, kNewPageRequest,
698 base::Bind(&RemoteBrowser::PageCreatedOnHandlerThread, this, url))); 706 base::Bind(&RemoteBrowser::PageCreatedOnHandlerThread, this, url)));
699 } 707 }
700 708
701 void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnHandlerThread( 709 void DevToolsAdbBridge::RemoteBrowser::PageCreatedOnHandlerThread(
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 897
890 if (listeners_.empty()) 898 if (listeners_.empty())
891 return; 899 return;
892 900
893 BrowserThread::PostDelayedTask( 901 BrowserThread::PostDelayedTask(
894 BrowserThread::UI, 902 BrowserThread::UI,
895 FROM_HERE, 903 FROM_HERE,
896 base::Bind(&DevToolsAdbBridge::RequestRemoteDevices, this), 904 base::Bind(&DevToolsAdbBridge::RequestRemoteDevices, this),
897 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); 905 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs));
898 } 906 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/devtools_adb_bridge.h ('k') | chrome/browser/resources/inspect/inspect.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698