diff options
author | rockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-13 17:43:29 +0000 |
---|---|---|
committer | rockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-13 17:43:29 +0000 |
commit | e195487cff78f14d51ad4ecb0eb73ab304cdd267 (patch) | |
tree | c704be72fd5a2556027ea078d84717692659b4d5 /chrome/browser/usb | |
parent | 026191dd8e11f7ec1a02aad6e82f0069c4f3c1f3 (diff) | |
download | chromium_src-e195487cff78f14d51ad4ecb0eb73ab304cdd267.zip chromium_src-e195487cff78f14d51ad4ecb0eb73ab304cdd267.tar.gz chromium_src-e195487cff78f14d51ad4ecb0eb73ab304cdd267.tar.bz2 |
Remove NotificationService usage from UsbService.
This changes UsbService to be a LazyInstance that destroys
itself along with the FILE thread message loop, rather than
observing NOTIFICATION_APP_TERMINATING.
This has two benefits: It kills one more consumer of
NotificationService, and it removes the only external
Chrome dependency from //chrome/browser/usb.
BUG=361000
R=pfeldman@chromium.org
Review URL: https://codereview.chromium.org/234813007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263556 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/usb')
-rw-r--r-- | chrome/browser/usb/usb_service.cc | 122 | ||||
-rw-r--r-- | chrome/browser/usb/usb_service.h | 27 |
2 files changed, 43 insertions, 106 deletions
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc index 221ccbb..5916457 100644 --- a/chrome/browser/usb/usb_service.cc +++ b/chrome/browser/usb/usb_service.cc @@ -7,110 +7,49 @@ #include <set> #include <vector> -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" +#include "base/lazy_instance.h" #include "base/stl_util.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/usb/usb_context.h" #include "chrome/browser/usb/usb_device.h" -#include "chrome/browser/usb/usb_device_handle.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" #include "third_party/libusb/src/libusb/libusb.h" -namespace content { - -class NotificationDetails; -class NotificationSource; - -} // namespace content - -using content::BrowserThread; -using std::vector; - namespace { -// This is the one and only instance of UsbService. The reason not to use -// Singleton is: 1. Singleton focuses on solving race conditions and at-exit -// deletion, none of them are needed here, and 2. Singleton does not provide -// a way to clear the pointer after the instance being destroyed. -UsbService* g_usb_service_instance = NULL; -bool g_usb_service_instance_destroyed = false; - -class ExitObserver : public content::NotificationObserver { - public: - ExitObserver() { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&content::NotificationRegistrar::Add, - base::Unretained(®istrar_), this, - chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources())); - } - - private: - // content::NotificationObserver - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE { - if (type == chrome::NOTIFICATION_APP_TERMINATING) { - BrowserThread::DeleteSoon(BrowserThread::FILE, - FROM_HERE, - g_usb_service_instance); - delete this; - } - } - content::NotificationRegistrar registrar_; -}; +base::LazyInstance<scoped_ptr<UsbService> >::Leaky g_usb_service_instance = + LAZY_INSTANCE_INITIALIZER; } // namespace -UsbService::UsbService(PlatformUsbContext context) - : context_(new UsbContext(context)), - next_unique_id_(0) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); -} - -UsbService::~UsbService() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - - // Prevents creating a new UsbService. - g_usb_service_instance_destroyed = true; - g_usb_service_instance = NULL; - - for (DeviceMap::iterator it = devices_.begin(); it != devices_.end(); ++it) { - it->second->OnDisconnect(); - } -} - +// static UsbService* UsbService::GetInstance() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - if (g_usb_service_instance_destroyed) - return NULL; - - if (!g_usb_service_instance) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + UsbService* instance = g_usb_service_instance.Get().get(); + if (!instance) { PlatformUsbContext context = NULL; if (libusb_init(&context) != LIBUSB_SUCCESS) return NULL; if (!context) return NULL; - g_usb_service_instance = new UsbService(context); - - // Will be deleted upon NOTIFICATION_APP_TERMINATING. - new ExitObserver(); + instance = new UsbService(context); + g_usb_service_instance.Get().reset(instance); } + return instance; +} - return g_usb_service_instance; +scoped_refptr<UsbDevice> UsbService::GetDeviceById(uint32 unique_id) { + DCHECK(CalledOnValidThread()); + RefreshDevices(); + for (DeviceMap::iterator it = devices_.begin(); it != devices_.end(); ++it) { + if (it->second->unique_id() == unique_id) + return it->second; + } + return NULL; } void UsbService::GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK(CalledOnValidThread()); STLClearObject(devices); RefreshDevices(); @@ -119,25 +58,32 @@ void UsbService::GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices) { } } -scoped_refptr<UsbDevice> UsbService::GetDeviceById(uint32 unique_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - RefreshDevices(); +void UsbService::WillDestroyCurrentMessageLoop() { + DCHECK(CalledOnValidThread()); + g_usb_service_instance.Get().reset(NULL); +} +UsbService::UsbService(PlatformUsbContext context) + : context_(new UsbContext(context)), next_unique_id_(0) { + base::MessageLoop::current()->AddDestructionObserver(this); +} + +UsbService::~UsbService() { + base::MessageLoop::current()->RemoveDestructionObserver(this); for (DeviceMap::iterator it = devices_.begin(); it != devices_.end(); ++it) { - if (it->second->unique_id() == unique_id) return it->second; + it->second->OnDisconnect(); } - return NULL; } void UsbService::RefreshDevices() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK(CalledOnValidThread()); libusb_device** platform_devices = NULL; const ssize_t device_count = libusb_get_device_list(context_->context(), &platform_devices); std::set<UsbDevice*> connected_devices; - vector<PlatformUsbDevice> disconnected_devices; + std::vector<PlatformUsbDevice> disconnected_devices; // Populates new devices. for (ssize_t i = 0; i < device_count; ++i) { diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h index 55e7972..c83ed5b 100644 --- a/chrome/browser/usb/usb_service.h +++ b/chrome/browser/usb/usb_service.h @@ -10,17 +10,10 @@ #include <vector> #include "base/basictypes.h" -#include "base/callback.h" #include "base/memory/ref_counted.h" - -namespace base { - -template <class T> class DeleteHelper; - -} // namespace base - -struct InitUsbContextTraits; -template <typename T> struct DefaultSingletonTraits; +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/threading/non_thread_safe.h" typedef struct libusb_device* PlatformUsbDevice; typedef struct libusb_context* PlatformUsbContext; @@ -32,7 +25,8 @@ class UsbDevice; // used to manage and dispatch USB events. It is also responsible for device // discovery on the system, which allows it to re-use device handles to prevent // competition for the same USB device. -class UsbService { +class UsbService : public base::MessageLoop::DestructionObserver, + public base::NonThreadSafe { public: typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > > ScopedDeviceVector; @@ -48,18 +42,15 @@ class UsbService { // in increasing order. Must be called on FILE thread. void GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices); + // base::MessageLoop::DestructionObserver implementation. + virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + private: - friend class base::DeleteHelper<UsbService>; + friend struct base::DefaultDeleter<UsbService>; explicit UsbService(PlatformUsbContext context); virtual ~UsbService(); - // Return true if |device|'s vendor and product identifiers match |vendor_id| - // and |product_id|. - static bool DeviceMatches(scoped_refptr<UsbDevice> device, - const uint16 vendor_id, - const uint16 product_id); - // Enumerate USB devices from OS and Update devices_ map. void RefreshDevices(); |