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

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

Issue 18137007: DevTools: add about:flag for ADB-less remote debugging. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: For landing Created 7 years, 5 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/browser/devtools/devtools_adb_bridge.h ('k') | chrome/browser/ui/webui/inspect_ui.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h"
12 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
13 #include "base/json/json_reader.h" 14 #include "base/json/json_reader.h"
14 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/singleton.h"
16 #include "base/message_loop/message_loop_proxy.h" 18 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/rand_util.h" 19 #include "base/rand_util.h"
18 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
21 #include "base/threading/thread.h" 23 #include "base/threading/thread.h"
22 #include "base/values.h" 24 #include "base/values.h"
25 #include "chrome/browser/devtools/adb/android_rsa.h"
23 #include "chrome/browser/devtools/adb/android_usb_device.h" 26 #include "chrome/browser/devtools/adb/android_usb_device.h"
24 #include "chrome/browser/devtools/adb_client_socket.h" 27 #include "chrome/browser/devtools/adb_client_socket.h"
25 #include "chrome/browser/devtools/devtools_window.h" 28 #include "chrome/browser/devtools/devtools_window.h"
26 #include "chrome/browser/devtools/tethering_adb_filter.h" 29 #include "chrome/browser/devtools/tethering_adb_filter.h"
27 #include "chrome/browser/profiles/profile.h" 30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "components/browser_context_keyed_service/browser_context_dependency_ma nager.h"
28 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/devtools_agent_host.h" 34 #include "content/public/browser/devtools_agent_host.h"
30 #include "content/public/browser/devtools_client_host.h" 35 #include "content/public/browser/devtools_client_host.h"
31 #include "content/public/browser/devtools_external_agent_proxy.h" 36 #include "content/public/browser/devtools_external_agent_proxy.h"
32 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" 37 #include "content/public/browser/devtools_external_agent_proxy_delegate.h"
33 #include "content/public/browser/devtools_manager.h" 38 #include "content/public/browser/devtools_manager.h"
39 #include "crypto/rsa_private_key.h"
34 #include "net/base/net_errors.h" 40 #include "net/base/net_errors.h"
35 #include "net/server/web_socket.h" 41 #include "net/server/web_socket.h"
36 42
37 using content::BrowserThread; 43 using content::BrowserThread;
38 using net::WebSocket; 44 using net::WebSocket;
39 45
40 namespace { 46 namespace {
41 47
42 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread"; 48 static const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
43 static const char kHostDevicesCommand[] = "host:devices"; 49 static const char kHostDevicesCommand[] = "host:devices";
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 184 }
179 185
180 void Respond(int result, const std::string& response) { 186 void Respond(int result, const std::string& response) {
181 callback_.Run(result, response); 187 callback_.Run(result, response);
182 } 188 }
183 189
184 std::string query_; 190 std::string query_;
185 Callback callback_; 191 Callback callback_;
186 }; 192 };
187 193
188 static void ReceivedDevices(const AndroidDevicesCallback& callback,
189 Profile* profile,
190 int result,
191 const std::string& response) {
192 AndroidDevices devices;
193 #if defined(DEBUG_DEVTOOLS)
194 devices.push_back(new AdbDeviceImpl("")); // For desktop remote debugging.
195 std::vector<scoped_refptr<AndroidUsbDevice> > usb_devices;
196 AndroidUsbDevice::Enumerate(profile, &usb_devices);
197 for (size_t i = 0; i < usb_devices.size(); ++i)
198 devices.push_back(new UsbDeviceImpl(usb_devices[i]));
199 #endif // defined(DEBUG_DEVTOOLS)
200 if (result != net::OK) {
201 callback.Run(devices);
202 return;
203 }
204
205 std::vector<std::string> serials;
206 Tokenize(response, "\n", &serials);
207 for (size_t i = 0; i < serials.size(); ++i) {
208 std::vector<std::string> tokens;
209 Tokenize(serials[i], "\t ", &tokens);
210 devices.push_back(new AdbDeviceImpl(tokens[0]));
211 }
212 callback.Run(devices);
213 }
214
215 static void EnumerateDevices(Profile* profile,
216 const AndroidDevicesCallback& callback) {
217 AdbClientSocket::AdbQuery(
218 kAdbPort, kHostDevicesCommand,
219 base::Bind(&ReceivedDevices, callback, profile));
220 }
221
222 class AdbPagesCommand : public base::RefCounted<AdbPagesCommand> { 194 class AdbPagesCommand : public base::RefCounted<AdbPagesCommand> {
223 public: 195 public:
224 explicit AdbPagesCommand(const PagesCallback& callback) 196 explicit AdbPagesCommand(DevToolsAdbBridge* bridge,
225 : callback_(callback) { 197 const PagesCallback& callback)
198 : bridge_(bridge),
199 callback_(callback) {
226 pages_.reset(new DevToolsAdbBridge::RemotePages()); 200 pages_.reset(new DevToolsAdbBridge::RemotePages());
227 } 201 }
228 202
229 void Run(Profile* profile) { 203 void Run() {
230 EnumerateDevices(profile, 204 bridge_->EnumerateDevices(base::Bind(&AdbPagesCommand::ReceivedDevices,
231 base::Bind(&AdbPagesCommand::ReceivedDevices, this)); 205 this));
232 } 206 }
233 207
234 private: 208 private:
235 friend class base::RefCounted<AdbPagesCommand>; 209 friend class base::RefCounted<AdbPagesCommand>;
236 virtual ~AdbPagesCommand() {} 210 virtual ~AdbPagesCommand() {}
237 211
238 void ReceivedDevices(const AndroidDevices& devices) { 212 void ReceivedDevices(const AndroidDevices& devices) {
239 devices_ = devices; 213 devices_ = devices;
240 ProcessSerials(); 214 ProcessSerials();
241 } 215 }
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 std::string package = path_field.substr(1, socket_name_pos - 2); 377 std::string package = path_field.substr(1, socket_name_pos - 2);
404 if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) { 378 if (socket_name_pos + channel_pattern.size() < path_field.size() - 1) {
405 package += path_field.substr( 379 package += path_field.substr(
406 socket_name_pos + channel_pattern.size(), path_field.size() - 1); 380 socket_name_pos + channel_pattern.size(), path_field.size() - 1);
407 } 381 }
408 package[0] = base::ToUpperASCII(package[0]); 382 package[0] = base::ToUpperASCII(package[0]);
409 socket_to_package_[socket] = package; 383 socket_to_package_[socket] = package;
410 } 384 }
411 } 385 }
412 386
387 scoped_refptr<DevToolsAdbBridge> bridge_;
413 PagesCallback callback_; 388 PagesCallback callback_;
414 AndroidDevices devices_; 389 AndroidDevices devices_;
415 std::vector<std::string> sockets_; 390 std::vector<std::string> sockets_;
416 std::map<std::string, std::string> socket_to_package_; 391 std::map<std::string, std::string> socket_to_package_;
417 scoped_ptr<DevToolsAdbBridge::RemotePages> pages_; 392 scoped_ptr<DevToolsAdbBridge::RemotePages> pages_;
418 }; 393 };
419 394
420 } // namespace 395 } // namespace
421 396
422 const char kDevToolsChannelNameFormat[] = "%s_devtools_remote"; 397 const char kDevToolsChannelNameFormat[] = "%s_devtools_remote";
423 398
424 class AgentHostDelegate; 399 class AgentHostDelegate;
425 400
426 typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates; 401 typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates;
427 402
428 base::LazyInstance<AgentHostDelegates>::Leaky g_host_delegates = 403 base::LazyInstance<AgentHostDelegates>::Leaky g_host_delegates =
429 LAZY_INSTANCE_INITIALIZER; 404 LAZY_INSTANCE_INITIALIZER;
430 405
406 DevToolsAdbBridge::Wrapper::Wrapper(Profile* profile)
407 : bridge_(new DevToolsAdbBridge(profile)) {
408 }
409
410 DevToolsAdbBridge::Wrapper::~Wrapper() {
411 }
412
413 DevToolsAdbBridge* DevToolsAdbBridge::Wrapper::Get() {
414 return bridge_.get();
415 }
416
417 // static
418 DevToolsAdbBridge::Factory* DevToolsAdbBridge::Factory::GetInstance() {
419 return Singleton<DevToolsAdbBridge::Factory>::get();
420 }
421
422 // static
423 DevToolsAdbBridge* DevToolsAdbBridge::Factory::GetForProfile(
424 Profile* profile) {
425 return static_cast<DevToolsAdbBridge::Wrapper*>(
426 GetInstance()->GetServiceForBrowserContext(profile, true))->Get();
427 }
428
429 DevToolsAdbBridge::Factory::Factory()
430 : BrowserContextKeyedServiceFactory(
431 "DevToolsAdbBridge",
432 BrowserContextDependencyManager::GetInstance()) {}
433
434 DevToolsAdbBridge::Factory::~Factory() {}
435
436 BrowserContextKeyedService*
437 DevToolsAdbBridge::Factory::BuildServiceInstanceFor(
438 content::BrowserContext* context) const {
439 return new DevToolsAdbBridge::Wrapper(Profile::FromBrowserContext(context));
440 }
441
431 DevToolsAdbBridge::AndroidDevice::AndroidDevice(const std::string& serial) 442 DevToolsAdbBridge::AndroidDevice::AndroidDevice(const std::string& serial)
432 : serial_(serial) { 443 : serial_(serial) {
433 } 444 }
434 445
435 void DevToolsAdbBridge::AndroidDevice::HttpQuery( 446 void DevToolsAdbBridge::AndroidDevice::HttpQuery(
436 const std::string& la_name, 447 const std::string& la_name,
437 const std::string& request, 448 const std::string& request,
438 const CommandCallback& callback) { 449 const CommandCallback& callback) {
439 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this, 450 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this,
440 request, callback)); 451 request, callback));
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 scoped_refptr<DevToolsAdbBridge::RefCountedAdbThread> adb_thread_; 640 scoped_refptr<DevToolsAdbBridge::RefCountedAdbThread> adb_thread_;
630 scoped_ptr<net::StreamSocket> socket_; 641 scoped_ptr<net::StreamSocket> socket_;
631 scoped_ptr<content::DevToolsExternalAgentProxy> proxy_; 642 scoped_ptr<content::DevToolsExternalAgentProxy> proxy_;
632 std::string response_buffer_; 643 std::string response_buffer_;
633 TetheringAdbFilter tethering_adb_filter_; 644 TetheringAdbFilter tethering_adb_filter_;
634 DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate); 645 DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
635 }; 646 };
636 647
637 class AdbAttachCommand : public base::RefCounted<AdbAttachCommand> { 648 class AdbAttachCommand : public base::RefCounted<AdbAttachCommand> {
638 public: 649 public:
639 AdbAttachCommand(const base::WeakPtr<DevToolsAdbBridge>& bridge, 650 AdbAttachCommand(DevToolsAdbBridge* bridge,
640 const std::string& serial, 651 const std::string& serial,
641 const std::string& socket, 652 const std::string& socket,
642 const std::string& debug_url, 653 const std::string& debug_url,
643 const std::string& frontend_url) 654 const std::string& frontend_url)
644 : bridge_(bridge), 655 : bridge_(bridge),
645 serial_(serial), 656 serial_(serial),
646 socket_(socket), 657 socket_(socket),
647 debug_url_(debug_url), 658 debug_url_(debug_url),
648 frontend_url_(frontend_url) { 659 frontend_url_(frontend_url) {
649 } 660 }
650 661
651 void Run(Profile* profile) { 662 void Run() {
652 663 bridge_->EnumerateDevices(base::Bind(&AdbAttachCommand::ReceivedDevices,
653 // scoped_refptr<DevToolsAdbBridge::AndroidDevice> device =
654 // new AdbDeviceImpl(serial_);
655
656 DevToolsAdbBridge* bridge = bridge_.get();
657 if (!bridge)
658 return;
659
660 EnumerateDevices(profile, base::Bind(&AdbAttachCommand::ReceivedDevices,
661 this)); 664 this));
662 } 665 }
663 666
664 private: 667 private:
665 friend class base::RefCounted<AdbAttachCommand>; 668 friend class base::RefCounted<AdbAttachCommand>;
666 virtual ~AdbAttachCommand() {} 669 virtual ~AdbAttachCommand() {}
667 670
668 void ReceivedDevices(const AndroidDevices& devices) { 671 void ReceivedDevices(const AndroidDevices& devices) {
669 for (AndroidDevices::const_iterator it = devices.begin(); 672 for (AndroidDevices::const_iterator it = devices.begin();
670 it != devices.end(); ++it) { 673 it != devices.end(); ++it) {
(...skipping 11 matching lines...) Expand all
682 if (result != net::OK || socket == NULL) 685 if (result != net::OK || socket == NULL)
683 return; 686 return;
684 687
685 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 688 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
686 base::Bind(&AdbAttachCommand::OpenDevToolsWindow, this, socket)); 689 base::Bind(&AdbAttachCommand::OpenDevToolsWindow, this, socket));
687 } 690 }
688 691
689 void OpenDevToolsWindow(net::StreamSocket* socket) { 692 void OpenDevToolsWindow(net::StreamSocket* socket) {
690 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 693 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
691 694
692 DevToolsAdbBridge* bridge = bridge_.get();
693 if (!bridge)
694 return;
695
696 std::string id = base::StringPrintf("%s:%s", serial_.c_str(), 695 std::string id = base::StringPrintf("%s:%s", serial_.c_str(),
697 debug_url_.c_str()); 696 debug_url_.c_str());
698 AgentHostDelegates::iterator it = g_host_delegates.Get().find(id); 697 AgentHostDelegates::iterator it = g_host_delegates.Get().find(id);
699 AgentHostDelegate* delegate; 698 AgentHostDelegate* delegate;
700 if (it != g_host_delegates.Get().end()) 699 if (it != g_host_delegates.Get().end())
701 delegate = it->second; 700 delegate = it->second;
702 else 701 else
703 delegate = new AgentHostDelegate(id, serial_, bridge->adb_thread_, 702 delegate = new AgentHostDelegate(id, serial_, bridge_->adb_thread_,
704 socket); 703 socket);
705 DevToolsWindow::OpenExternalFrontend( 704 DevToolsWindow::OpenExternalFrontend(
706 bridge->profile_, frontend_url_, delegate->GetAgentHost().get()); 705 bridge_->profile_, frontend_url_, delegate->GetAgentHost().get());
707 } 706 }
708 707
709 base::WeakPtr<DevToolsAdbBridge> bridge_; 708 scoped_refptr<DevToolsAdbBridge> bridge_;
710 std::string serial_; 709 std::string serial_;
711 std::string socket_; 710 std::string socket_;
712 std::string debug_url_; 711 std::string debug_url_;
713 std::string frontend_url_; 712 std::string frontend_url_;
714 }; 713 };
715 714
716 DevToolsAdbBridge::RemotePage::RemotePage(const std::string& serial, 715 DevToolsAdbBridge::RemotePage::RemotePage(const std::string& serial,
717 const std::string& model, 716 const std::string& model,
718 const std::string& package, 717 const std::string& package,
719 const std::string& socket, 718 const std::string& socket,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 return; 783 return;
785 // Shut down thread on FILE thread to join into IO. 784 // Shut down thread on FILE thread to join into IO.
786 BrowserThread::PostTask( 785 BrowserThread::PostTask(
787 BrowserThread::FILE, FROM_HERE, 786 BrowserThread::FILE, FROM_HERE,
788 base::Bind(&RefCountedAdbThread::StopThread, thread_)); 787 base::Bind(&RefCountedAdbThread::StopThread, thread_));
789 } 788 }
790 789
791 DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile) 790 DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
792 : profile_(profile), 791 : profile_(profile),
793 adb_thread_(RefCountedAdbThread::GetInstance()), 792 adb_thread_(RefCountedAdbThread::GetInstance()),
794 weak_factory_(this),
795 has_message_loop_(adb_thread_->message_loop() != NULL) { 793 has_message_loop_(adb_thread_->message_loop() != NULL) {
794 rsa_key_.reset(AndroidRSAPrivateKey(profile));
796 } 795 }
797 796
798 DevToolsAdbBridge::~DevToolsAdbBridge() { 797 void DevToolsAdbBridge::EnumerateDevices(
799 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 798 const AndroidDevicesCallback& callback) {
799 AdbClientSocket::AdbQuery(
800 kAdbPort, kHostDevicesCommand,
801 base::Bind(&DevToolsAdbBridge::ReceivedDevices, this, callback));
800 } 802 }
801 803
802 void DevToolsAdbBridge::Query( 804 void DevToolsAdbBridge::Query(
803 const std::string query, 805 const std::string query,
804 const Callback& callback) { 806 const Callback& callback) {
805 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 807 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
806 if (!has_message_loop_) { 808 if (!has_message_loop_) {
807 callback.Run(net::ERR_FAILED, "Could not start ADB thread"); 809 callback.Run(net::ERR_FAILED, "Could not start ADB thread");
808 return; 810 return;
809 } 811 }
810 scoped_refptr<AdbQueryCommand> command(new AdbQueryCommand(query, callback)); 812 scoped_refptr<AdbQueryCommand> command(new AdbQueryCommand(query, callback));
811 adb_thread_->message_loop()->PostTask(FROM_HERE, 813 adb_thread_->message_loop()->PostTask(FROM_HERE,
812 base::Bind(&AdbQueryCommand::Run, command)); 814 base::Bind(&AdbQueryCommand::Run, command));
813 } 815 }
814 816
815 void DevToolsAdbBridge::Pages(const PagesCallback& callback) { 817 void DevToolsAdbBridge::Pages(const PagesCallback& callback) {
816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
817 if (!has_message_loop_) 819 if (!has_message_loop_)
818 return; 820 return;
819 821
820 scoped_refptr<AdbPagesCommand> command( 822 scoped_refptr<AdbPagesCommand> command(
821 new AdbPagesCommand(callback)); 823 new AdbPagesCommand(this, callback));
822 adb_thread_->message_loop()->PostTask(FROM_HERE, 824 adb_thread_->message_loop()->PostTask(FROM_HERE,
823 base::Bind(&AdbPagesCommand::Run, command, profile_)); 825 base::Bind(&AdbPagesCommand::Run, command));
824 } 826 }
825 827
826 void DevToolsAdbBridge::Attach(const std::string& serial, 828 void DevToolsAdbBridge::Attach(const std::string& serial,
827 const std::string& socket, 829 const std::string& socket,
828 const std::string& debug_url, 830 const std::string& debug_url,
829 const std::string& frontend_url) { 831 const std::string& frontend_url) {
830 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 832 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
831 if (!has_message_loop_) 833 if (!has_message_loop_)
832 return; 834 return;
833 835
834 scoped_refptr<AdbAttachCommand> command( 836 scoped_refptr<AdbAttachCommand> command(
835 new AdbAttachCommand(weak_factory_.GetWeakPtr(), serial, socket, 837 new AdbAttachCommand(this, serial, socket,
836 debug_url, frontend_url)); 838 debug_url, frontend_url));
837 adb_thread_->message_loop()->PostTask( 839 adb_thread_->message_loop()->PostTask(
838 FROM_HERE, 840 FROM_HERE,
839 base::Bind(&AdbAttachCommand::Run, command, profile_)); 841 base::Bind(&AdbAttachCommand::Run, command));
840 } 842 }
843
844 DevToolsAdbBridge::~DevToolsAdbBridge() {
845 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
846 }
847
848 void DevToolsAdbBridge::ReceivedDevices(const AndroidDevicesCallback& callback,
849 int result,
850 const std::string& response) {
851 AndroidDevices devices;
852 #if defined(DEBUG_DEVTOOLS)
853 devices.push_back(new AdbDeviceImpl("")); // For desktop remote debugging.
854 #endif // defined(DEBUG_DEVTOOLS)
855
856 if (CommandLine::ForCurrentProcess()->HasSwitch(
857 switches::kRemoteDebuggingRawUSB)) {
858 AndroidUsbDevices usb_devices;
859 AndroidUsbDevice::Enumerate(profile_, rsa_key_.get(), &usb_devices);
860 for (AndroidUsbDevices::iterator it = usb_devices.begin();
861 it != usb_devices.end(); ++it) {
862 devices.push_back(new UsbDeviceImpl(*it));
863 }
864 }
865
866 if (result != net::OK) {
867 callback.Run(devices);
868 return;
869 }
870
871 std::vector<std::string> serials;
872 Tokenize(response, "\n", &serials);
873 for (size_t i = 0; i < serials.size(); ++i) {
874 std::vector<std::string> tokens;
875 Tokenize(serials[i], "\t ", &tokens);
876 devices.push_back(new AdbDeviceImpl(tokens[0]));
877 }
878 callback.Run(devices);
879 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/devtools_adb_bridge.h ('k') | chrome/browser/ui/webui/inspect_ui.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698