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

Side by Side Diff: chrome/browser/devtools/adb/android_usb_device.cc

Issue 23953002: DevTools: request usb permission on ChromeOS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | « no previous file | chrome/browser/devtools/devtools_adb_bridge.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/adb/android_usb_device.h" 5 #include "chrome/browser/devtools/adb/android_usb_device.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/barrier_closure.h"
9 #include "base/base64.h" 10 #include "base/base64.h"
10 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
12 #include "base/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
15 #include "chrome/browser/devtools/adb/android_rsa.h" 16 #include "chrome/browser/devtools/adb/android_rsa.h"
16 #include "chrome/browser/devtools/adb/android_usb_socket.h" 17 #include "chrome/browser/devtools/adb/android_usb_socket.h"
17 #include "chrome/browser/usb/usb_device.h" 18 #include "chrome/browser/usb/usb_device.h"
18 #include "chrome/browser/usb/usb_interface.h" 19 #include "chrome/browser/usb/usb_interface.h"
(...skipping 15 matching lines...) Expand all
34 const int kUsbTimeout = 0; 35 const int kUsbTimeout = 0;
35 36
36 const uint32 kMaxPayload = 4096; 37 const uint32 kMaxPayload = 4096;
37 const uint32 kVersion = 0x01000000; 38 const uint32 kVersion = 0x01000000;
38 39
39 static const char kHostConnectMessage[] = "host::"; 40 static const char kHostConnectMessage[] = "host::";
40 41
41 using content::BrowserThread; 42 using content::BrowserThread;
42 43
43 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices; 44 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
45 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet;
44 46
45 base::LazyInstance<AndroidUsbDevices>::Leaky g_devices = 47 base::LazyInstance<AndroidUsbDevices>::Leaky g_devices =
46 LAZY_INSTANCE_INITIALIZER; 48 LAZY_INSTANCE_INITIALIZER;
47 49
48 scoped_refptr<AndroidUsbDevice> ClaimInterface( 50 bool IsAndroidInterface(
49 crypto::RSAPrivateKey* rsa_key, 51 scoped_refptr<const UsbInterfaceDescriptor> interface) {
50 scoped_refptr<UsbDeviceHandle> usb_device,
51 scoped_refptr<const UsbInterfaceDescriptor> interface,
52 int interface_id) {
53 if (interface->GetNumAltSettings() == 0) 52 if (interface->GetNumAltSettings() == 0)
54 return NULL; 53 return false;
55 54
56 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc = 55 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
57 interface->GetAltSetting(0); 56 interface->GetAltSetting(0);
58 57
59 if (idesc->GetInterfaceClass() != kAdbClass || 58 if (idesc->GetInterfaceClass() != kAdbClass ||
60 idesc->GetInterfaceSubclass() != kAdbSubclass || 59 idesc->GetInterfaceSubclass() != kAdbSubclass ||
61 idesc->GetInterfaceProtocol() != kAdbProtocol || 60 idesc->GetInterfaceProtocol() != kAdbProtocol ||
62 idesc->GetNumEndpoints() != 2) { 61 idesc->GetNumEndpoints() != 2) {
63 return NULL; 62 return false;
64 } 63 }
64 return true;
65 }
66
67 scoped_refptr<AndroidUsbDevice> ClaimInterface(
68 crypto::RSAPrivateKey* rsa_key,
69 scoped_refptr<UsbDeviceHandle> usb_handle,
70 scoped_refptr<const UsbInterfaceDescriptor> interface,
71 int interface_id) {
72 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
73 interface->GetAltSetting(0);
65 74
66 int inbound_address = 0; 75 int inbound_address = 0;
67 int outbound_address = 0; 76 int outbound_address = 0;
68 int zero_mask = 0; 77 int zero_mask = 0;
69 78
70 for (size_t i = 0; i < idesc->GetNumEndpoints(); ++i) { 79 for (size_t i = 0; i < idesc->GetNumEndpoints(); ++i) {
71 scoped_refptr<const UsbEndpointDescriptor> edesc = 80 scoped_refptr<const UsbEndpointDescriptor> edesc =
72 idesc->GetEndpoint(i); 81 idesc->GetEndpoint(i);
73 if (edesc->GetTransferType() != USB_TRANSFER_BULK) 82 if (edesc->GetTransferType() != USB_TRANSFER_BULK)
74 continue; 83 continue;
75 if (edesc->GetDirection() == USB_DIRECTION_INBOUND) 84 if (edesc->GetDirection() == USB_DIRECTION_INBOUND)
76 inbound_address = edesc->GetAddress(); 85 inbound_address = edesc->GetAddress();
77 else 86 else
78 outbound_address = edesc->GetAddress(); 87 outbound_address = edesc->GetAddress();
79 zero_mask = edesc->GetMaximumPacketSize() - 1; 88 zero_mask = edesc->GetMaximumPacketSize() - 1;
80 } 89 }
81 90
82 if (inbound_address == 0 || outbound_address == 0) 91 if (inbound_address == 0 || outbound_address == 0)
83 return NULL; 92 return NULL;
84 93
85 if (!usb_device->ClaimInterface(interface_id)) 94 if (!usb_handle->ClaimInterface(interface_id))
86 return NULL; 95 return NULL;
87 96
88 base::string16 serial; 97 base::string16 serial;
89 if (!usb_device->GetSerial(&serial) || serial.empty()) 98 if (!usb_handle->GetSerial(&serial) || serial.empty())
90 return NULL; 99 return NULL;
91 100
92 return new AndroidUsbDevice(rsa_key, usb_device, UTF16ToASCII(serial), 101 return new AndroidUsbDevice(rsa_key, usb_handle, UTF16ToASCII(serial),
93 inbound_address, outbound_address, zero_mask); 102 inbound_address, outbound_address, zero_mask);
94 } 103 }
95 104
96 uint32 Checksum(const std::string& data) { 105 uint32 Checksum(const std::string& data) {
97 unsigned char* x = (unsigned char*)data.data(); 106 unsigned char* x = (unsigned char*)data.data();
98 int count = data.length(); 107 int count = data.length();
99 uint32 sum = 0; 108 uint32 sum = 0;
100 while (count-- > 0) 109 while (count-- > 0)
101 sum += *x++; 110 sum += *x++;
102 return sum; 111 return sum;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 const std::string& body) 153 const std::string& body)
145 : command(command), 154 : command(command),
146 arg0(arg0), 155 arg0(arg0),
147 arg1(arg1), 156 arg1(arg1),
148 body(body) { 157 body(body) {
149 } 158 }
150 159
151 AdbMessage::~AdbMessage() { 160 AdbMessage::~AdbMessage() {
152 } 161 }
153 162
163 static void RespondOnUIThread(const AndroidUsbDevicesCallback& callback,
164 const AndroidUsbDevices& devices) {
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166 callback.Run(devices);
167 }
168
169 static void RespondOnFileThread(const AndroidUsbDevicesCallback& callback) {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
171 // Copy g_devices.Get() on file thread.
172 BrowserThread::PostTask(
173 BrowserThread::UI, FROM_HERE,
174 base::Bind(&RespondOnUIThread, callback, g_devices.Get()));
175 }
176
177 static void OpenAndroidDevicesOnFileThread(
178 crypto::RSAPrivateKey* rsa_key,
179 const base::Closure& barrier,
180 scoped_refptr<UsbDevice> device,
181 int interface_id,
182 bool success) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
184 if (success) {
185 scoped_refptr<UsbConfigDescriptor> config = device->ListInterfaces();
186 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
187 if (usb_handle) {
188 scoped_refptr<AndroidUsbDevice> device =
189 ClaimInterface(rsa_key, usb_handle, config->GetInterface(interface_id),
190 interface_id);
191 if (device.get())
192 g_devices.Get().push_back(device);
193 else
194 usb_handle->Close();
195 }
196 }
197 barrier.Run();
198 }
199
154 static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key, 200 static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key,
155 AndroidUsbDevices* result) { 201 const AndroidUsbDevicesCallback& callback) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
157 203
158 UsbService* service = UsbService::GetInstance(); 204 UsbService* service = UsbService::GetInstance();
159 AndroidUsbDevices& devices = g_devices.Get();
160
161 UsbDevices usb_devices; 205 UsbDevices usb_devices;
162 service->GetDevices(&usb_devices); 206 service->GetDevices(&usb_devices);
163 207
208 AndroidUsbDevices& devices = g_devices.Get();
209
164 // GC Android devices with no actual usb device. 210 // GC Android devices with no actual usb device.
165 AndroidUsbDevices::iterator it = devices.begin(); 211 AndroidUsbDevices::iterator it = devices.begin();
166 std::set<UsbDevice*> claimed_devices; 212 UsbDeviceSet claimed_devices;
167 while (it != devices.end()) { 213 while (it != devices.end()) {
168 bool found_device = false; 214 bool found_device = false;
169 for (UsbDevices::iterator it2 = usb_devices.begin(); 215 for (UsbDevices::iterator it2 = usb_devices.begin();
170 it2 != usb_devices.end() && !found_device; ++it2) { 216 it2 != usb_devices.end() && !found_device; ++it2) {
171 UsbDevice* usb_device = it2->get(); 217 UsbDevice* usb_device = it2->get();
172 AndroidUsbDevice* device = it->get(); 218 AndroidUsbDevice* device = it->get();
173 if (usb_device == device->usb_device()->device()) { 219 if (usb_device == device->usb_device()->device()) {
174 found_device = true; 220 found_device = true;
175 claimed_devices.insert(usb_device); 221 claimed_devices.insert(usb_device);
176 } 222 }
177 } 223 }
178 224
179 if (!found_device) 225 if (!found_device)
180 it = devices.erase(it); 226 it = devices.erase(it);
181 else 227 else
182 ++it; 228 ++it;
183 } 229 }
184 230
185 // Add new devices. 231 // Add new devices.
232 base::Closure barrier = base::BarrierClosure(
233 usb_devices.size(), base::Bind(&RespondOnFileThread, callback));
234
186 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end(); 235 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
187 ++it) { 236 ++it) {
188 if (ContainsKey(claimed_devices, it->get())) 237 if (ContainsKey(claimed_devices, it->get())) {
238 barrier.Run();
189 continue; 239 continue;
240 }
190 241
191 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces(); 242 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces();
192 if (!config) 243 if (!config) {
244 barrier.Run();
193 continue; 245 continue;
246 }
194 247
195 scoped_refptr<UsbDeviceHandle> usb_device = (*it)->Open(); 248 bool has_android_interface = false;
196 if (!usb_device) 249 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
197 continue; 250 if (!IsAndroidInterface(config->GetInterface(j)))
251 continue;
198 252
199 bool claimed = false; 253 // Request permission on Chrome OS.
200 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) { 254 #if defined(OS_CHROMEOS)
201 scoped_refptr<AndroidUsbDevice> device = 255 (*it)->RequestUsbAcess(j, base::Bind(&OpenAndroidDevicesOnFileThread,
202 ClaimInterface(rsa_key, usb_device, config->GetInterface(j), j); 256 rsa_key, barrier, *it, j));
203 if (device.get()) { 257 #else
204 devices.push_back(device); 258 OpenAndroidDevicesOnFileThread(rsa_key, barrier, *it, j, true);
205 claimed = true; 259 #endif // defined(OS_CHROMEOS)
206 } 260
261 has_android_interface = true;
262 break;
207 } 263 }
208 if (!claimed) 264 if (!has_android_interface)
209 usb_device->Close(); 265 barrier.Run();
210 } 266 }
211
212 *result = devices;
213 }
214
215 static void InitDevicesOnCallerThread(
216 AndroidUsbDevices* devices,
217 const AndroidUsbDevicesCallback& callback) {
218 for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end();
219 ++it) {
220 (*it)->InitOnCallerThread();
221 }
222 callback.Run(*devices);
223 delete devices;
224 } 267 }
225 268
226 // static 269 // static
227 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key, 270 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
228 const AndroidUsbDevicesCallback& callback) { 271 const AndroidUsbDevicesCallback& callback) {
229 AndroidUsbDevices* devices = new AndroidUsbDevices(); 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230 BrowserThread::PostTaskAndReply( 273 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
231 BrowserThread::FILE, FROM_HERE, 274 base::Bind(&EnumerateOnFileThread, rsa_key,
232 base::Bind(&EnumerateOnFileThread, rsa_key, devices), 275 callback));
233 base::Bind(&InitDevicesOnCallerThread, devices, callback));
234 } 276 }
235 277
236 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key, 278 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
237 scoped_refptr<UsbDeviceHandle> usb_device, 279 scoped_refptr<UsbDeviceHandle> usb_device,
238 const std::string& serial, 280 const std::string& serial,
239 int inbound_address, 281 int inbound_address,
240 int outbound_address, 282 int outbound_address,
241 int zero_mask) 283 int zero_mask)
242 : message_loop_(NULL), 284 : message_loop_(NULL),
243 rsa_key_(rsa_key->Copy()), 285 rsa_key_(rsa_key->Copy()),
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 // Delay open request if not yet connected. 318 // Delay open request if not yet connected.
277 if (!is_connected_) { 319 if (!is_connected_) {
278 pending_messages_.push_back(m); 320 pending_messages_.push_back(m);
279 return; 321 return;
280 } 322 }
281 Queue(m); 323 Queue(m);
282 } 324 }
283 325
284 AndroidUsbDevice::~AndroidUsbDevice() { 326 AndroidUsbDevice::~AndroidUsbDevice() {
285 Terminate(); 327 Terminate();
328 usb_device_->AddRef();
329 BrowserThread::ReleaseSoon(BrowserThread::FILE, FROM_HERE,
330 usb_device_.get());
286 } 331 }
287 332
288 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) { 333 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) {
289 // Queue header. 334 // Queue header.
290 std::vector<uint32> header; 335 std::vector<uint32> header;
291 header.push_back(message->command); 336 header.push_back(message->command);
292 header.push_back(message->arg0); 337 header.push_back(message->arg0);
293 header.push_back(message->arg1); 338 header.push_back(message->arg1);
294 bool append_zero = true; 339 bool append_zero = true;
295 if (message->body.empty()) 340 if (message->body.empty())
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 } 552 }
508 553
509 BrowserThread::PostTask( 554 BrowserThread::PostTask(
510 BrowserThread::FILE, FROM_HERE, 555 BrowserThread::FILE, FROM_HERE,
511 base::Bind(&ReleaseInterface, usb_device_)); 556 base::Bind(&ReleaseInterface, usb_device_));
512 } 557 }
513 558
514 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) { 559 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
515 sockets_.erase(socket_id); 560 sockets_.erase(socket_id);
516 } 561 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/devtools/devtools_adb_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698