Index: extensions/browser/api/device_permissions_manager.cc |
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc |
index 3b467ebe2ecd1bf3564da1f66366057f9e30e633..baa3c04b6d07862959b56d1323501f82486bb97d 100644 |
--- a/extensions/browser/api/device_permissions_manager.cc |
+++ b/extensions/browser/api/device_permissions_manager.cc |
@@ -4,12 +4,14 @@ |
#include "extensions/browser/api/device_permissions_manager.h" |
+#include "base/bind.h" |
#include "base/memory/singleton.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/stringprintf.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/values.h" |
#include "components/keyed_service/content/browser_context_dependency_manager.h" |
+#include "content/public/browser/browser_thread.h" |
#include "device/core/device_client.h" |
#include "device/usb/usb_device.h" |
#include "device/usb/usb_ids.h" |
@@ -24,7 +26,9 @@ |
namespace extensions { |
using content::BrowserContext; |
+using content::BrowserThread; |
using device::UsbDevice; |
+using device::UsbService; |
using extensions::APIPermission; |
using extensions::Extension; |
using extensions::ExtensionHost; |
@@ -377,6 +381,35 @@ DevicePermissions::DevicePermissions(const DevicePermissions* original) |
ephemeral_devices_(original->ephemeral_devices_) { |
} |
+class DevicePermissionsManager::FileThreadHelper : public UsbService::Observer { |
+ public: |
+ FileThreadHelper( |
+ base::WeakPtr<DevicePermissionsManager> device_permissions_manager) |
+ : device_permissions_manager_(device_permissions_manager), |
+ observer_(this) {} |
+ virtual ~FileThreadHelper() {} |
+ |
+ void Start() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
+ UsbService* service = device::DeviceClient::Get()->GetUsbService(); |
+ if (service) { |
+ observer_.Add(service); |
+ } |
+ } |
+ |
+ private: |
+ void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override { |
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&DevicePermissionsManager::OnDeviceRemoved, |
+ device_permissions_manager_, device)); |
+ } |
+ |
+ base::WeakPtr<DevicePermissionsManager> device_permissions_manager_; |
+ ScopedObserver<UsbService, UsbService::Observer> observer_; |
+}; |
+ |
// static |
DevicePermissionsManager* DevicePermissionsManager::Get( |
BrowserContext* context) { |
@@ -441,11 +474,13 @@ void DevicePermissionsManager::AllowUsbDevice( |
// Only start observing when an ephemeral device has been added so that |
// UsbService is not automatically initialized on profile creation (which it |
// would be if this call were in the constructor). |
- device::UsbService* usb_service = |
- device::DeviceClient::Get()->GetUsbService(); |
- DCHECK(usb_service); |
- if (!usb_service_observer_.IsObserving(usb_service)) { |
- usb_service_observer_.Add(usb_service); |
+ if (!helper_) { |
+ helper_ = new FileThreadHelper(weak_factory_.GetWeakPtr()); |
+ // base::Unretained is safe because any task to delete helper_ will be |
+ // executed after this call. |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&FileThreadHelper::Start, base::Unretained(helper_))); |
} |
} |
} |
@@ -490,7 +525,8 @@ DevicePermissionsManager::DevicePermissionsManager( |
content::BrowserContext* context) |
: context_(context), |
process_manager_observer_(this), |
- usb_service_observer_(this) { |
+ helper_(nullptr), |
+ weak_factory_(this) { |
process_manager_observer_.Add(ProcessManager::Get(context)); |
} |
@@ -499,6 +535,10 @@ DevicePermissionsManager::~DevicePermissionsManager() { |
DevicePermissions* device_permissions = map_entry.second; |
delete device_permissions; |
} |
+ if (helper_) { |
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, helper_); |
+ helper_ = nullptr; |
+ } |
} |
DevicePermissions* DevicePermissionsManager::Get( |
@@ -540,6 +580,7 @@ void DevicePermissionsManager::OnBackgroundHostClose( |
void DevicePermissionsManager::OnDeviceRemoved( |
scoped_refptr<UsbDevice> device) { |
+ DCHECK(CalledOnValidThread()); |
for (const auto& map_entry : extension_id_to_device_permissions_) { |
// An ephemeral device cannot be identified if it is reconnected and so |
// permission to access it is cleared on disconnect. |