summaryrefslogtreecommitdiffstats
path: root/chrome/browser/usb
diff options
context:
space:
mode:
authorrockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-13 17:43:29 +0000
committerrockot@chromium.org <rockot@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-13 17:43:29 +0000
commite195487cff78f14d51ad4ecb0eb73ab304cdd267 (patch)
treec704be72fd5a2556027ea078d84717692659b4d5 /chrome/browser/usb
parent026191dd8e11f7ec1a02aad6e82f0069c4f3c1f3 (diff)
downloadchromium_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.cc122
-rw-r--r--chrome/browser/usb/usb_service.h27
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(&registrar_), 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();