OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/api/device_permissions_manager.h" | 5 #include "extensions/browser/api/device_permissions_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 result.insert(new DevicePermissionEntry(vendor_id, product_id, | 226 result.insert(new DevicePermissionEntry(vendor_id, product_id, |
227 serial_number, manufacturer_string, | 227 serial_number, manufacturer_string, |
228 product_string, last_used)); | 228 product_string, last_used)); |
229 } | 229 } |
230 return result; | 230 return result; |
231 } | 231 } |
232 | 232 |
233 } // namespace | 233 } // namespace |
234 | 234 |
235 DevicePermissionEntry::DevicePermissionEntry( | 235 DevicePermissionEntry::DevicePermissionEntry( |
236 scoped_refptr<device::UsbDevice> device, | 236 scoped_refptr<device::UsbDevice> device) |
237 const base::string16& serial_number, | |
238 const base::string16& manufacturer_string, | |
239 const base::string16& product_string) | |
240 : device_(device), | 237 : device_(device), |
241 vendor_id_(device->vendor_id()), | 238 vendor_id_(device->vendor_id()), |
242 product_id_(device->product_id()), | 239 product_id_(device->product_id()), |
243 serial_number_(serial_number), | 240 serial_number_(device->serial_number()), |
244 manufacturer_string_(manufacturer_string), | 241 manufacturer_string_(device->manufacturer_string()), |
245 product_string_(product_string) { | 242 product_string_(device->product_string()) { |
246 } | 243 } |
247 | 244 |
248 DevicePermissionEntry::DevicePermissionEntry( | 245 DevicePermissionEntry::DevicePermissionEntry( |
249 uint16_t vendor_id, | 246 uint16_t vendor_id, |
250 uint16_t product_id, | 247 uint16_t product_id, |
251 const base::string16& serial_number, | 248 const base::string16& serial_number, |
252 const base::string16& manufacturer_string, | 249 const base::string16& manufacturer_string, |
253 const base::string16& product_string, | 250 const base::string16& product_string, |
254 const base::Time& last_used) | 251 const base::Time& last_used) |
255 : vendor_id_(vendor_id), | 252 : vendor_id_(vendor_id), |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 } | 331 } |
335 } else { | 332 } else { |
336 return product_string_; | 333 return product_string_; |
337 } | 334 } |
338 } | 335 } |
339 | 336 |
340 DevicePermissions::~DevicePermissions() { | 337 DevicePermissions::~DevicePermissions() { |
341 } | 338 } |
342 | 339 |
343 scoped_refptr<DevicePermissionEntry> DevicePermissions::FindEntry( | 340 scoped_refptr<DevicePermissionEntry> DevicePermissions::FindEntry( |
344 scoped_refptr<device::UsbDevice> device, | 341 scoped_refptr<device::UsbDevice> device) const { |
345 const base::string16& serial_number) const { | |
346 const auto& ephemeral_device_entry = ephemeral_devices_.find(device); | 342 const auto& ephemeral_device_entry = ephemeral_devices_.find(device); |
347 if (ephemeral_device_entry != ephemeral_devices_.end()) { | 343 if (ephemeral_device_entry != ephemeral_devices_.end()) { |
348 return ephemeral_device_entry->second; | 344 return ephemeral_device_entry->second; |
349 } | 345 } |
350 | 346 |
351 if (serial_number.empty()) { | 347 if (device->serial_number().empty()) { |
352 return nullptr; | 348 return nullptr; |
353 } | 349 } |
354 | 350 |
355 for (const auto& entry : entries_) { | 351 for (const auto& entry : entries_) { |
356 if (!entry->IsPersistent()) { | 352 if (!entry->IsPersistent()) { |
357 continue; | 353 continue; |
358 } | 354 } |
359 if (entry->vendor_id() != device->vendor_id()) { | 355 if (entry->vendor_id() != device->vendor_id()) { |
360 continue; | 356 continue; |
361 } | 357 } |
362 if (entry->product_id() != device->product_id()) { | 358 if (entry->product_id() != device->product_id()) { |
363 continue; | 359 continue; |
364 } | 360 } |
365 if (entry->serial_number() != serial_number) { | 361 if (entry->serial_number() != device->serial_number()) { |
366 continue; | 362 continue; |
367 } | 363 } |
368 return entry; | 364 return entry; |
369 } | 365 } |
370 return nullptr; | 366 return nullptr; |
371 } | 367 } |
372 | 368 |
373 DevicePermissions::DevicePermissions(BrowserContext* context, | 369 DevicePermissions::DevicePermissions(BrowserContext* context, |
374 const std::string& extension_id) { | 370 const std::string& extension_id) { |
375 ExtensionPrefs* prefs = ExtensionPrefs::Get(context); | 371 ExtensionPrefs* prefs = ExtensionPrefs::Get(context); |
376 entries_ = GetDevicePermissionEntries(prefs, extension_id); | 372 entries_ = GetDevicePermissionEntries(prefs, extension_id); |
377 } | 373 } |
378 | 374 |
379 DevicePermissions::DevicePermissions(const DevicePermissions* original) | |
380 : entries_(original->entries_), | |
381 ephemeral_devices_(original->ephemeral_devices_) { | |
382 } | |
383 | |
384 class DevicePermissionsManager::FileThreadHelper : public UsbService::Observer { | |
385 public: | |
386 FileThreadHelper( | |
387 base::WeakPtr<DevicePermissionsManager> device_permissions_manager) | |
388 : device_permissions_manager_(device_permissions_manager), | |
389 observer_(this) {} | |
390 virtual ~FileThreadHelper() {} | |
391 | |
392 void Start() { | |
393 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
394 UsbService* service = device::DeviceClient::Get()->GetUsbService(); | |
395 if (service) { | |
396 observer_.Add(service); | |
397 } | |
398 } | |
399 | |
400 private: | |
401 void OnDeviceRemovedCleanup(scoped_refptr<UsbDevice> device) override { | |
402 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
403 BrowserThread::PostTask( | |
404 BrowserThread::UI, FROM_HERE, | |
405 base::Bind(&DevicePermissionsManager::OnDeviceRemoved, | |
406 device_permissions_manager_, device)); | |
407 } | |
408 | |
409 base::WeakPtr<DevicePermissionsManager> device_permissions_manager_; | |
410 ScopedObserver<UsbService, UsbService::Observer> observer_; | |
411 }; | |
412 | |
413 // static | 375 // static |
414 DevicePermissionsManager* DevicePermissionsManager::Get( | 376 DevicePermissionsManager* DevicePermissionsManager::Get( |
415 BrowserContext* context) { | 377 BrowserContext* context) { |
416 return DevicePermissionsManagerFactory::GetForBrowserContext(context); | 378 return DevicePermissionsManagerFactory::GetForBrowserContext(context); |
417 } | 379 } |
418 | 380 |
419 scoped_ptr<DevicePermissions> DevicePermissionsManager::GetForExtension( | 381 DevicePermissions* DevicePermissionsManager::GetForExtension( |
420 const std::string& extension_id) { | 382 const std::string& extension_id) { |
421 DCHECK(CalledOnValidThread()); | 383 DCHECK(CalledOnValidThread()); |
422 return make_scoped_ptr(new DevicePermissions(GetOrInsert(extension_id))); | 384 DevicePermissions* device_permissions = Get(extension_id); |
| 385 if (!device_permissions) { |
| 386 device_permissions = new DevicePermissions(context_, extension_id); |
| 387 extension_id_to_device_permissions_[extension_id] = device_permissions; |
| 388 } |
| 389 |
| 390 return device_permissions; |
423 } | 391 } |
424 | 392 |
425 std::vector<base::string16> | 393 std::vector<base::string16> |
426 DevicePermissionsManager::GetPermissionMessageStrings( | 394 DevicePermissionsManager::GetPermissionMessageStrings( |
427 const std::string& extension_id) const { | 395 const std::string& extension_id) const { |
428 DCHECK(CalledOnValidThread()); | 396 DCHECK(CalledOnValidThread()); |
429 std::vector<base::string16> messages; | 397 std::vector<base::string16> messages; |
430 const DevicePermissions* device_permissions = Get(extension_id); | 398 const DevicePermissions* device_permissions = Get(extension_id); |
431 if (device_permissions) { | 399 if (device_permissions) { |
432 for (const scoped_refptr<DevicePermissionEntry>& entry : | 400 for (const scoped_refptr<DevicePermissionEntry>& entry : |
433 device_permissions->entries()) { | 401 device_permissions->entries()) { |
434 messages.push_back(entry->GetPermissionMessageString()); | 402 messages.push_back(entry->GetPermissionMessageString()); |
435 } | 403 } |
436 } | 404 } |
437 return messages; | 405 return messages; |
438 } | 406 } |
439 | 407 |
440 void DevicePermissionsManager::AllowUsbDevice( | 408 void DevicePermissionsManager::AllowUsbDevice( |
441 const std::string& extension_id, | 409 const std::string& extension_id, |
442 scoped_refptr<device::UsbDevice> device, | 410 scoped_refptr<device::UsbDevice> device) { |
443 const base::string16& product_string, | |
444 const base::string16& manufacturer_string, | |
445 const base::string16& serial_number) { | |
446 DCHECK(CalledOnValidThread()); | 411 DCHECK(CalledOnValidThread()); |
447 DevicePermissions* device_permissions = GetOrInsert(extension_id); | 412 DevicePermissions* device_permissions = GetForExtension(extension_id); |
448 | 413 |
449 scoped_refptr<DevicePermissionEntry> device_entry(new DevicePermissionEntry( | 414 scoped_refptr<DevicePermissionEntry> device_entry( |
450 device, serial_number, manufacturer_string, product_string)); | 415 new DevicePermissionEntry(device)); |
451 | 416 |
452 if (device_entry->IsPersistent()) { | 417 if (device_entry->IsPersistent()) { |
453 for (const auto& entry : device_permissions->entries()) { | 418 for (const auto& entry : device_permissions->entries()) { |
454 if (entry->vendor_id() != device_entry->vendor_id()) { | 419 if (entry->vendor_id() != device_entry->vendor_id()) { |
455 continue; | 420 continue; |
456 } | 421 } |
457 if (entry->product_id() != device_entry->product_id()) { | 422 if (entry->product_id() != device_entry->product_id()) { |
458 continue; | 423 continue; |
459 } | 424 } |
460 if (entry->serial_number() == device_entry->serial_number()) { | 425 if (entry->serial_number() == device_entry->serial_number()) { |
461 return; | 426 return; |
462 } | 427 } |
463 } | 428 } |
464 | 429 |
465 device_permissions->entries_.insert(device_entry); | 430 device_permissions->entries_.insert(device_entry); |
466 SaveDevicePermissionEntry(context_, extension_id, device_entry); | 431 SaveDevicePermissionEntry(context_, extension_id, device_entry); |
467 } else if (!ContainsKey(device_permissions->ephemeral_devices_, device)) { | 432 } else if (!ContainsKey(device_permissions->ephemeral_devices_, device)) { |
468 // Non-persistent devices cannot be reliably identified when they are | 433 // Non-persistent devices cannot be reliably identified when they are |
469 // reconnected so such devices are only remembered until disconnect. | 434 // reconnected so such devices are only remembered until disconnect. |
470 // Register an observer here so that this set doesn't grow undefinitely. | 435 // Register an observer here so that this set doesn't grow undefinitely. |
471 device_permissions->entries_.insert(device_entry); | 436 device_permissions->entries_.insert(device_entry); |
472 device_permissions->ephemeral_devices_[device] = device_entry; | 437 device_permissions->ephemeral_devices_[device] = device_entry; |
473 | 438 |
474 // Only start observing when an ephemeral device has been added so that | 439 // Only start observing when an ephemeral device has been added so that |
475 // UsbService is not automatically initialized on profile creation (which it | 440 // UsbService is not automatically initialized on profile creation (which it |
476 // would be if this call were in the constructor). | 441 // would be if this call were in the constructor). |
477 if (!helper_) { | 442 UsbService* usb_service = device::DeviceClient::Get()->GetUsbService(); |
478 helper_ = new FileThreadHelper(weak_factory_.GetWeakPtr()); | 443 if (!usb_service_observer_.IsObserving(usb_service)) { |
479 // base::Unretained is safe because any task to delete helper_ will be | 444 usb_service_observer_.Add(usb_service); |
480 // executed after this call. | |
481 BrowserThread::PostTask( | |
482 BrowserThread::FILE, FROM_HERE, | |
483 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_))); | |
484 } | 445 } |
485 } | 446 } |
486 } | 447 } |
487 | 448 |
488 void DevicePermissionsManager::UpdateLastUsed( | 449 void DevicePermissionsManager::UpdateLastUsed( |
489 const std::string& extension_id, | 450 const std::string& extension_id, |
490 scoped_refptr<DevicePermissionEntry> entry) { | 451 scoped_refptr<DevicePermissionEntry> entry) { |
491 DCHECK(CalledOnValidThread()); | 452 DCHECK(CalledOnValidThread()); |
492 entry->set_last_used(base::Time::Now()); | 453 entry->set_last_used(base::Time::Now()); |
493 if (entry->IsPersistent()) { | 454 if (entry->IsPersistent()) { |
(...skipping 24 matching lines...) Expand all Loading... |
518 if (device_permissions) { | 479 if (device_permissions) { |
519 extension_id_to_device_permissions_.erase(extension_id); | 480 extension_id_to_device_permissions_.erase(extension_id); |
520 delete device_permissions; | 481 delete device_permissions; |
521 } | 482 } |
522 } | 483 } |
523 | 484 |
524 DevicePermissionsManager::DevicePermissionsManager( | 485 DevicePermissionsManager::DevicePermissionsManager( |
525 content::BrowserContext* context) | 486 content::BrowserContext* context) |
526 : context_(context), | 487 : context_(context), |
527 process_manager_observer_(this), | 488 process_manager_observer_(this), |
528 helper_(nullptr), | 489 usb_service_observer_(this) { |
529 weak_factory_(this) { | |
530 process_manager_observer_.Add(ProcessManager::Get(context)); | 490 process_manager_observer_.Add(ProcessManager::Get(context)); |
531 } | 491 } |
532 | 492 |
533 DevicePermissionsManager::~DevicePermissionsManager() { | 493 DevicePermissionsManager::~DevicePermissionsManager() { |
534 for (const auto& map_entry : extension_id_to_device_permissions_) { | 494 for (const auto& map_entry : extension_id_to_device_permissions_) { |
535 DevicePermissions* device_permissions = map_entry.second; | 495 DevicePermissions* device_permissions = map_entry.second; |
536 delete device_permissions; | 496 delete device_permissions; |
537 } | 497 } |
538 if (helper_) { | |
539 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, helper_); | |
540 helper_ = nullptr; | |
541 } | |
542 } | 498 } |
543 | 499 |
544 DevicePermissions* DevicePermissionsManager::Get( | 500 DevicePermissions* DevicePermissionsManager::Get( |
545 const std::string& extension_id) const { | 501 const std::string& extension_id) const { |
546 std::map<std::string, DevicePermissions*>::const_iterator it = | 502 std::map<std::string, DevicePermissions*>::const_iterator it = |
547 extension_id_to_device_permissions_.find(extension_id); | 503 extension_id_to_device_permissions_.find(extension_id); |
548 if (it != extension_id_to_device_permissions_.end()) { | 504 if (it != extension_id_to_device_permissions_.end()) { |
549 return it->second; | 505 return it->second; |
550 } | 506 } |
551 | 507 |
552 return NULL; | 508 return NULL; |
553 } | 509 } |
554 | 510 |
555 DevicePermissions* DevicePermissionsManager::GetOrInsert( | |
556 const std::string& extension_id) { | |
557 DevicePermissions* device_permissions = Get(extension_id); | |
558 if (!device_permissions) { | |
559 device_permissions = new DevicePermissions(context_, extension_id); | |
560 extension_id_to_device_permissions_[extension_id] = device_permissions; | |
561 } | |
562 | |
563 return device_permissions; | |
564 } | |
565 | |
566 void DevicePermissionsManager::OnBackgroundHostClose( | 511 void DevicePermissionsManager::OnBackgroundHostClose( |
567 const std::string& extension_id) { | 512 const std::string& extension_id) { |
568 DCHECK(CalledOnValidThread()); | 513 DCHECK(CalledOnValidThread()); |
569 | 514 |
570 DevicePermissions* device_permissions = Get(extension_id); | 515 DevicePermissions* device_permissions = Get(extension_id); |
571 if (device_permissions) { | 516 if (device_permissions) { |
572 // When all of the app's windows are closed and the background page is | 517 // When all of the app's windows are closed and the background page is |
573 // suspended all ephemeral device permissions are cleared. | 518 // suspended all ephemeral device permissions are cleared. |
574 for (const auto& map_entry : device_permissions->ephemeral_devices_) { | 519 for (const auto& map_entry : device_permissions->ephemeral_devices_) { |
575 device_permissions->entries_.erase(map_entry.second); | 520 device_permissions->entries_.erase(map_entry.second); |
576 } | 521 } |
577 device_permissions->ephemeral_devices_.clear(); | 522 device_permissions->ephemeral_devices_.clear(); |
578 } | 523 } |
579 } | 524 } |
580 | 525 |
581 void DevicePermissionsManager::OnDeviceRemoved( | 526 void DevicePermissionsManager::OnDeviceRemovedCleanup( |
582 scoped_refptr<UsbDevice> device) { | 527 scoped_refptr<UsbDevice> device) { |
583 DCHECK(CalledOnValidThread()); | 528 DCHECK(CalledOnValidThread()); |
584 for (const auto& map_entry : extension_id_to_device_permissions_) { | 529 for (const auto& map_entry : extension_id_to_device_permissions_) { |
585 // An ephemeral device cannot be identified if it is reconnected and so | 530 // An ephemeral device cannot be identified if it is reconnected and so |
586 // permission to access it is cleared on disconnect. | 531 // permission to access it is cleared on disconnect. |
587 DevicePermissions* device_permissions = map_entry.second; | 532 DevicePermissions* device_permissions = map_entry.second; |
588 const auto& device_entry = | 533 const auto& device_entry = |
589 device_permissions->ephemeral_devices_.find(device); | 534 device_permissions->ephemeral_devices_.find(device); |
590 if (device_entry != device_permissions->ephemeral_devices_.end()) { | 535 if (device_entry != device_permissions->ephemeral_devices_.end()) { |
591 device_permissions->entries_.erase(device_entry->second); | 536 device_permissions->entries_.erase(device_entry->second); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 | 569 |
625 BrowserContext* DevicePermissionsManagerFactory::GetBrowserContextToUse( | 570 BrowserContext* DevicePermissionsManagerFactory::GetBrowserContextToUse( |
626 BrowserContext* context) const { | 571 BrowserContext* context) const { |
627 // Return the original (possibly off-the-record) browser context so that a | 572 // Return the original (possibly off-the-record) browser context so that a |
628 // separate instance of the DevicePermissionsManager is used in incognito | 573 // separate instance of the DevicePermissionsManager is used in incognito |
629 // mode. The parent class's implemenation returns NULL. | 574 // mode. The parent class's implemenation returns NULL. |
630 return context; | 575 return context; |
631 } | 576 } |
632 | 577 |
633 } // namespace extensions | 578 } // namespace extensions |
OLD | NEW |