summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorikarienator@chromium.org <ikarienator@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-02 00:56:15 +0000
committerikarienator@chromium.org <ikarienator@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-02 00:56:15 +0000
commitb6eb1ac86ad7b25035984d6ab9f78ba6898835be (patch)
tree5bea453844c7d6c386c83746e38a10b97bf89def /chrome/browser
parente6c97f6de21efd3e693a1afda435cc3b9a9eb2c7 (diff)
downloadchromium_src-b6eb1ac86ad7b25035984d6ab9f78ba6898835be.zip
chromium_src-b6eb1ac86ad7b25035984d6ab9f78ba6898835be.tar.gz
chromium_src-b6eb1ac86ad7b25035984d6ab9f78ba6898835be.tar.bz2
Create a refcounted usb context wrapper.
This will be also used when we introduce UsbDevice. BUG=223817 Review URL: https://chromiumcodereview.appspot.com/20012002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215174 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/devtools/adb/android_usb_device.cc7
-rw-r--r--chrome/browser/extensions/api/usb/usb_api.cc55
-rw-r--r--chrome/browser/extensions/api/usb/usb_api.h16
-rw-r--r--chrome/browser/usb/usb_context.cc73
-rw-r--r--chrome/browser/usb/usb_context.h46
-rw-r--r--chrome/browser/usb/usb_context_unittest.cc (renamed from chrome/browser/usb/usb_service_unittest.cc)17
-rw-r--r--chrome/browser/usb/usb_device_handle.cc14
-rw-r--r--chrome/browser/usb/usb_device_handle.h2
-rw-r--r--chrome/browser/usb/usb_service.cc162
-rw-r--r--chrome/browser/usb/usb_service.h55
10 files changed, 326 insertions, 121 deletions
diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc
index 36965ed..c6f537c 100644
--- a/chrome/browser/devtools/adb/android_usb_device.cc
+++ b/chrome/browser/devtools/adb/android_usb_device.cc
@@ -149,11 +149,11 @@ static void RespondOnUIThread(const AndroidUsbDevicesCallback& callback,
callback.Run(devices);
}
-static void EnumerateOnFileThread(UsbService* service,
- crypto::RSAPrivateKey* rsa_key,
+static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key,
const AndroidUsbDevicesCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ UsbService* service = UsbService::GetInstance();
AndroidUsbDevices& devices = g_devices.Get();
UsbDevices usb_devices;
@@ -207,10 +207,9 @@ static void EnumerateOnFileThread(UsbService* service,
void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
const AndroidUsbDevicesCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UsbService* service = UsbService::GetInstance();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&EnumerateOnFileThread, service, rsa_key, callback));
+ base::Bind(&EnumerateOnFileThread, rsa_key, callback));
}
AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index 223f831..a6c8ae8 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -326,6 +326,14 @@ static base::Value* PopulateInterfaceDescriptor(int interface_number,
return descriptor.ToValue().release();
}
+void GetUsbService(base::Callback<void(UsbService* service)> callback) {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(UsbService::GetInstance),
+ callback);
+}
+
} // namespace
namespace extensions {
@@ -440,21 +448,48 @@ void UsbFindDevicesFunction::AsyncWorkStart() {
return;
}
- UsbService::GetInstance()->FindDevices(
- vendor_id,
- product_id,
- interface_id,
- &devices_,
- base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
+ GetUsbService(base::Bind(&UsbFindDevicesFunction::EnumerateDevices,
+ this,
+ vendor_id,
+ product_id,
+ interface_id));
+}
+
+void UsbFindDevicesFunction::EnumerateDevices(
+ uint16_t vendor_id,
+ uint16_t product_id,
+ int interface_id,
+ UsbService* service) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbService::FindDevices,
+ base::Unretained(service),
+ vendor_id,
+ product_id,
+ interface_id,
+ base::Bind(&UsbFindDevicesFunction::OnEnumerationCompleted,
+ this)));
+}
+
+
+void UsbFindDevicesFunction::OnEnumerationCompleted(
+ ScopedDeviceVector devices) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&UsbFindDevicesFunction::OnCompleted,
+ this,
+ base::Passed(devices.Pass())));
}
-void UsbFindDevicesFunction::OnCompleted() {
- for (size_t i = 0; i < devices_.size(); ++i) {
- UsbDeviceHandle* const device = devices_[i].get();
+void UsbFindDevicesFunction::OnCompleted(
+ ScopedDeviceVector devices) {
+ for (size_t i = 0; i < devices->size(); ++i) {
+ UsbDeviceHandle* const device = devices->at(i).get();
UsbDeviceResource* const resource =
new UsbDeviceResource(extension_->id(), device);
- Device js_device;
result_->Append(PopulateDevice(manager_->Add(resource),
parameters_->options.vendor_id,
parameters_->options.product_id));
diff --git a/chrome/browser/extensions/api/usb/usb_api.h b/chrome/browser/extensions/api/usb/usb_api.h
index 80941fc..65c713e 100644
--- a/chrome/browser/extensions/api/usb/usb_api.h
+++ b/chrome/browser/extensions/api/usb/usb_api.h
@@ -16,6 +16,7 @@
#include "net/base/io_buffer.h"
class UsbDeviceHandle;
+class UsbService;
namespace extensions {
@@ -71,10 +72,21 @@ class UsbFindDevicesFunction : public UsbAsyncApiFunction {
virtual void AsyncWorkStart() OVERRIDE;
private:
- void OnCompleted();
+ typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+ ScopedDeviceVector;
+
+ // Wait for GetDeviceService to return and start enumeration on FILE thread.
+ void EnumerateDevices(uint16_t vendor_id,
+ uint16_t product_id,
+ int interface_id,
+ UsbService* service);
+ // Relay the result on IO thread to OnCompleted.
+ void OnEnumerationCompleted(ScopedDeviceVector devices);
+
+ // Create ApiResources and reply.
+ void OnCompleted(ScopedDeviceVector devices);
scoped_ptr<base::ListValue> result_;
- std::vector<scoped_refptr<UsbDeviceHandle> > devices_;
scoped_ptr<extensions::api::usb::FindDevices::Params> parameters_;
};
diff --git a/chrome/browser/usb/usb_context.cc b/chrome/browser/usb/usb_context.cc
new file mode 100644
index 0000000..3b0811a
--- /dev/null
+++ b/chrome/browser/usb/usb_context.cc
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/usb/usb_context.h"
+
+#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/libusb/src/libusb/interrupt.h"
+#include "third_party/libusb/src/libusb/libusb.h"
+
+// The UsbEventHandler works around a design flaw in the libusb interface. There
+// is currently no way to signal to libusb that any caller into one of the event
+// handler calls should return without handling any events.
+class UsbContext::UsbEventHandler : public base::PlatformThread::Delegate {
+ public:
+ explicit UsbEventHandler(libusb_context* context);
+ virtual ~UsbEventHandler();
+
+ // base::PlatformThread::Delegate
+ virtual void ThreadMain() OVERRIDE;
+
+ private:
+ volatile bool running_;
+ libusb_context* context_;
+ base::PlatformThreadHandle thread_handle_;
+ base::WaitableEvent start_polling_;
+ DISALLOW_COPY_AND_ASSIGN(UsbEventHandler);
+};
+
+UsbContext::UsbEventHandler::UsbEventHandler(libusb_context* context)
+ : running_(true),
+ context_(context),
+ thread_handle_(0),
+ start_polling_(false, false) {
+ DCHECK(base::PlatformThread::Create(0, this, &thread_handle_)) <<
+ "Failed to create USB IO handling thread.";
+ start_polling_.Wait();
+}
+
+UsbContext::UsbEventHandler::~UsbEventHandler() {
+ running_ = false;
+ // Spreading running_ to the UsbEventHandler thread.
+ base::subtle::MemoryBarrier();
+ libusb_interrupt_handle_event(context_);
+ base::PlatformThread::Join(thread_handle_);
+}
+
+void UsbContext::UsbEventHandler::ThreadMain() {
+ base::PlatformThread::SetName("UsbEventHandler");
+ VLOG(1) << "UsbEventHandler started.";
+ if (running_) {
+ start_polling_.Signal();
+ libusb_handle_events(context_);
+ }
+ while (running_)
+ libusb_handle_events(context_);
+ VLOG(1) << "UsbEventHandler shutting down.";
+}
+
+UsbContext::UsbContext() : context_(NULL) {
+ CHECK_EQ(0, libusb_init(&context_)) << "Cannot initialize libusb";
+ event_handler_.reset(new UsbEventHandler(context_));
+}
+
+UsbContext::~UsbContext() {
+ // destruction of UsbEventHandler is a blocking operation.
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ event_handler_.reset(NULL);
+ libusb_exit(context_);
+}
diff --git a/chrome/browser/usb/usb_context.h b/chrome/browser/usb/usb_context.h
new file mode 100644
index 0000000..07894c5
--- /dev/null
+++ b/chrome/browser/usb/usb_context.h
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_USB_USB_CONTEXT_H_
+#define CHROME_BROWSER_USB_USB_CONTEXT_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/browser_thread.h"
+
+struct libusb_context;
+
+typedef libusb_context* PlatformUsbContext;
+
+// Ref-counted wrapper for libusb_context*.
+// It also manages the life-cycle of UsbEventHandler.
+// It is a blocking operation to delete UsbContext.
+// Destructor must be called on FILE thread.
+class UsbContext
+ : public base::RefCountedThreadSafe<
+ UsbContext, content::BrowserThread::DeleteOnFileThread> {
+ public:
+ PlatformUsbContext context() const { return context_; }
+
+ protected:
+ friend class UsbService;
+ friend struct content::BrowserThread::DeleteOnThread<
+ content::BrowserThread::FILE>;
+ friend class base::DeleteHelper<UsbContext>;
+
+ // Set wait_for_polling_starts to true if the constructor should wait until
+ // the polling starts. It will block the current thread. Only use it in tests.
+ explicit UsbContext();
+ virtual ~UsbContext();
+
+ private:
+ class UsbEventHandler;
+ PlatformUsbContext context_;
+ scoped_ptr<UsbEventHandler> event_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(UsbContext);
+};
+
+#endif // CHROME_BROWSER_USB_USB_CONTEXT_H_
diff --git a/chrome/browser/usb/usb_service_unittest.cc b/chrome/browser/usb/usb_context_unittest.cc
index 44864d8..4944c1c 100644
--- a/chrome/browser/usb/usb_service_unittest.cc
+++ b/chrome/browser/usb/usb_context_unittest.cc
@@ -2,16 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/usb/usb_service.h"
+#include "chrome/browser/usb/usb_context.h"
+#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-class UsbServiceTest : public testing::Test {
+class UsbContextTest : public testing::Test {
protected:
- class UsbServiceForTest : public UsbService {};
+ class UsbContextForTest : public UsbContext {
+ public:
+ UsbContextForTest() : UsbContext() {}
+ private:
+ virtual ~UsbContextForTest() {}
+ DISALLOW_COPY_AND_ASSIGN(UsbContextForTest);
+ };
};
#if defined(OS_LINUX)
@@ -24,10 +31,10 @@ class UsbServiceTest : public testing::Test {
#define MAYBE_GracefulShutdown GracefulShutdown
#endif
-TEST_F(UsbServiceTest, MAYBE_GracefulShutdown) {
+TEST_F(UsbContextTest, MAYBE_GracefulShutdown) {
base::TimeTicks start = base::TimeTicks::Now();
{
- scoped_ptr<UsbServiceForTest> service(new UsbServiceForTest());
+ scoped_refptr<UsbContextForTest> context(new UsbContextForTest());
}
base::TimeDelta elapse = base::TimeTicks::Now() - start;
if (elapse > base::TimeDelta::FromSeconds(2)) {
diff --git a/chrome/browser/usb/usb_device_handle.cc b/chrome/browser/usb/usb_device_handle.cc
index b6e54f4..56c3dc7 100644
--- a/chrome/browser/usb/usb_device_handle.cc
+++ b/chrome/browser/usb/usb_device_handle.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -127,7 +127,7 @@ void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed";
Transfer* const transfer = &transfers_[handle];
- DCHECK(handle->actual_length >= 0) << "Negative actual length received";
+ DCHECK_GE(handle->actual_length, 0) << "Negative actual length received";
size_t actual_length =
static_cast<size_t>(std::max(handle->actual_length, 0));
@@ -272,9 +272,15 @@ bool UsbDeviceHandle::GetSerial(base::string16* serial) {
size = libusb_get_string_descriptor(
handle_, desc.iSerialNumber, langid[i],
reinterpret_cast<unsigned char*>(&text[0]), sizeof(text));
- if (size < 0)
+ if (size <= 2)
continue;
- *serial = base::string16(text, size / 2);
+ if ((text[0] >> 8) != LIBUSB_DT_STRING)
+ continue;
+ if ((text[0] & 255) > size)
+ continue;
+
+ size = size / 2 - 1;
+ *serial = base::string16(text + 1, size);
return true;
}
return false;
diff --git a/chrome/browser/usb/usb_device_handle.h b/chrome/browser/usb/usb_device_handle.h
index ef059d7..0659955 100644
--- a/chrome/browser/usb/usb_device_handle.h
+++ b/chrome/browser/usb/usb_device_handle.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc
index 9cba20cc..d850488 100644
--- a/chrome/browser/usb/usb_service.cc
+++ b/chrome/browser/usb/usb_service.cc
@@ -10,9 +10,13 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/usb/usb_context.h"
#include "chrome/browser/usb/usb_device_handle.h"
-#include "third_party/libusb/src/libusb/interrupt.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"
#if defined(OS_CHROMEOS)
@@ -21,70 +25,64 @@
#include "chromeos/dbus/permission_broker_client.h"
#endif // defined(OS_CHROMEOS)
-using std::vector;
+namespace content {
-// The UsbEventHandler works around a design flaw in the libusb interface. There
-// is currently no way to signal to libusb that any caller into one of the event
-// handler calls should return without handling any events.
-class UsbEventHandler : public base::PlatformThread::Delegate {
- public:
- explicit UsbEventHandler(PlatformUsbContext context)
- : running_(true),
- context_(context),
- thread_handle_(0),
- started_event_(false, false) {
- base::PlatformThread::Create(0, this, &thread_handle_);
- started_event_.Wait();
- }
+class NotificationDetails;
+class NotificationSource;
- virtual ~UsbEventHandler() {}
+} // namespace content
- virtual void ThreadMain() OVERRIDE {
- base::PlatformThread::SetName("UsbEventHandler");
- VLOG(1) << "UsbEventHandler started.";
- started_event_.Signal();
- while (running_)
- libusb_handle_events(context_);
- VLOG(1) << "UsbEventHandler shutting down.";
- }
+using content::BrowserThread;
+using std::vector;
+
+namespace {
- void Stop() {
- running_ = false;
- base::subtle::MemoryBarrier();
- libusb_interrupt_handle_event(context_);
- base::PlatformThread::Join(thread_handle_);
+class ExitObserver : public content::NotificationObserver {
+ public:
+ explicit ExitObserver(UsbService* service) : service_(service) {
+ registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
+ content::NotificationService::AllSources());
}
private:
- volatile bool running_;
- PlatformUsbContext context_;
- base::PlatformThreadHandle thread_handle_;
- base::WaitableEvent started_event_;
- DISALLOW_COPY_AND_ASSIGN(UsbEventHandler);
+ // content::NotificationObserver
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ if (type == chrome::NOTIFICATION_APP_TERMINATING) {
+ registrar_.RemoveAll();
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, service_);
+ }
+ }
+ UsbService* service_;
+ content::NotificationRegistrar registrar_;
};
-UsbService::UsbService() {
- libusb_init(&context_);
- event_handler_ = new UsbEventHandler(context_);
+} // namespace
+
+UsbService::UsbService() : context_(new UsbContext()) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
}
UsbService::~UsbService() {
- event_handler_->Stop();
- delete event_handler_;
- libusb_exit(context_);
- context_ = NULL;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ // UsbDeviceHandle::Close removes itself from devices_.
+ while (devices_.size())
+ devices_.begin()->second->Close();
}
UsbService* UsbService::GetInstance() {
- return Singleton<UsbService>::get();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ // UsbService deletes itself upon APP_TERMINATING.
+ return Singleton<UsbService, LeakySingletonTraits<UsbService> >::get();
}
-void UsbService::FindDevices(const uint16 vendor_id,
- const uint16 product_id,
- int interface_id,
- vector<scoped_refptr<UsbDeviceHandle> >* devices,
- const base::Callback<void()>& callback) {
- DCHECK(event_handler_) << "FindDevices called after event handler stopped.";
+void UsbService::FindDevices(
+ const uint16 vendor_id,
+ const uint16 product_id,
+ int interface_id,
+ const base::Callback<void(ScopedDeviceVector vector)>& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
#if defined(OS_CHROMEOS)
// ChromeOS builds on non-ChromeOS machines (dev) should not attempt to
// use permission broker.
@@ -93,29 +91,33 @@ void UsbService::FindDevices(const uint16 vendor_id,
chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
DCHECK(client) << "Could not get permission broker client.";
if (!client) {
- callback.Run();
+ callback.Run(ScopedDeviceVector());
return;
}
- client->RequestUsbAccess(vendor_id,
- product_id,
- interface_id,
- base::Bind(&UsbService::FindDevicesImpl,
- base::Unretained(this),
- vendor_id,
- product_id,
- devices,
- callback));
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess,
+ base::Unretained(client),
+ vendor_id,
+ product_id,
+ interface_id,
+ base::Bind(&UsbService::OnRequestUsbAccessReplied,
+ base::Unretained(this),
+ vendor_id,
+ product_id,
+ callback)));
} else {
- FindDevicesImpl(vendor_id, product_id, devices, callback, true);
+ FindDevicesImpl(vendor_id, product_id, callback, true);
}
#else
- FindDevicesImpl(vendor_id, product_id, devices, callback, true);
+ FindDevicesImpl(vendor_id, product_id, callback, true);
#endif // defined(OS_CHROMEOS)
}
void UsbService::EnumerateDevices(
- std::vector<scoped_refptr<UsbDeviceHandle> >* devices) {
+ vector<scoped_refptr<UsbDeviceHandle> >* devices) {
devices->clear();
DeviceVector enumerated_devices;
@@ -130,21 +132,36 @@ void UsbService::EnumerateDevices(
}
}
-void UsbService::FindDevicesImpl(
+void UsbService::OnRequestUsbAccessReplied(
const uint16 vendor_id,
const uint16 product_id,
- vector<scoped_refptr<UsbDeviceHandle> >* devices,
- const base::Callback<void()>& callback,
+ const base::Callback<void(ScopedDeviceVector vectors)>& callback,
bool success) {
- base::ScopedClosureRunner run_callback(callback);
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbService::FindDevicesImpl,
+ base::Unretained(this),
+ vendor_id,
+ product_id,
+ callback,
+ success));
+}
- devices->clear();
+void UsbService::FindDevicesImpl(
+ const uint16 vendor_id,
+ const uint16 product_id,
+ const base::Callback<void(ScopedDeviceVector vectors)>& callback,
+ bool success) {
+ ScopedDeviceVector devices(new vector<scoped_refptr<UsbDeviceHandle> >());
// If the permission broker was unable to obtain permission for the specified
// devices then there is no point in attempting to enumerate the devices. On
// platforms without a permission broker, we assume permission is granted.
- if (!success)
+ if (!success) {
+ callback.Run(devices.Pass());
return;
+ }
DeviceVector enumerated_devices;
EnumerateDevicesImpl(&enumerated_devices);
@@ -155,14 +172,13 @@ void UsbService::FindDevicesImpl(
if (DeviceMatches(device, vendor_id, product_id)) {
UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
if (wrapper)
- devices->push_back(wrapper);
+ devices->push_back(make_scoped_refptr(wrapper));
}
}
+ callback.Run(devices.Pass());
}
void UsbService::CloseDevice(scoped_refptr<UsbDeviceHandle> device) {
- DCHECK(event_handler_) << "CloseDevice called after event handler stopped.";
-
PlatformUsbDevice platform_device = libusb_get_device(device->handle());
if (!ContainsKey(devices_, platform_device)) {
LOG(WARNING) << "CloseDevice called for device we're not tracking!";
@@ -195,7 +211,9 @@ void UsbService::EnumerateDevicesImpl(DeviceVector* output) {
STLClearObject(output);
libusb_device** devices = NULL;
- const ssize_t device_count = libusb_get_device_list(context_, &devices);
+ const ssize_t device_count = libusb_get_device_list(
+ context_->context(),
+ &devices);
if (device_count < 0)
return;
diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h
index 5588364..dcd6e28 100644
--- a/chrome/browser/usb/usb_service.h
+++ b/chrome/browser/usb/usb_service.h
@@ -11,15 +11,16 @@
#include "base/basictypes.h"
#include "base/memory/singleton.h"
-#include "base/threading/platform_thread.h"
#include "chrome/browser/usb/usb_device_handle.h"
-#include "third_party/libusb/src/libusb/libusb.h"
-class UsbEventHandler;
-template <typename T> struct DefaultSingletonTraits;
-struct libusb_context;
+namespace base {
+
+template <class T> class DeleteHelper;
-typedef struct libusb_context* PlatformUsbContext;
+} // namespace base
+
+template <typename T> struct DefaultSingletonTraits;
+class UsbContext;
// The USB service handles creating and managing an event handler thread that is
// used to manage and dispatch USB events. It is also responsbile for device
@@ -27,16 +28,19 @@ typedef struct libusb_context* PlatformUsbContext;
// competition for the same USB device.
class UsbService {
public:
+ typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+ ScopedDeviceVector;
+ // Must be called on FILE thread.
static UsbService* GetInstance();
// Find all of the devices attached to the system that are identified by
// |vendor_id| and |product_id|, inserting them into |devices|. Clears
// |devices| before use. Calls |callback| once |devices| is populated.
- void FindDevices(const uint16 vendor_id,
- const uint16 product_id,
- int interface_id,
- std::vector<scoped_refptr<UsbDeviceHandle> >* devices,
- const base::Callback<void()>& callback);
+ void FindDevices(
+ const uint16 vendor_id,
+ const uint16 product_id,
+ int interface_id,
+ const base::Callback<void(ScopedDeviceVector vector)>& callback);
// Find all of the devices attached to the system, inserting them into
// |devices|. Clears |devices| before use.
@@ -46,13 +50,11 @@ class UsbService {
// UsbDevice's Close function and disposes of the associated platform handle.
void CloseDevice(scoped_refptr<UsbDeviceHandle> device);
- protected:
+ private:
UsbService();
virtual ~UsbService();
-
- private:
friend struct DefaultSingletonTraits<UsbService>;
-
+ friend class base::DeleteHelper<UsbService>;
// RefCountedPlatformUsbDevice takes care of managing the underlying reference
// count of a single PlatformUsbDevice. This allows us to construct things
@@ -77,15 +79,23 @@ class UsbService {
const uint16 vendor_id,
const uint16 product_id);
+ // This method is called when permission broker replied our request.
+ // We will simply relay it to FILE thread.
+ void OnRequestUsbAccessReplied(
+ const uint16 vendor_id,
+ const uint16 product_id,
+ const base::Callback<void(ScopedDeviceVector vector)>& callback,
+ bool success);
+
// FindDevicesImpl is called by FindDevices on ChromeOS after the permission
- // broker has signalled that permission has been granted to access the
+ // broker has signaled that permission has been granted to access the
// underlying device nodes. On other platforms, it is called directly by
// FindDevices.
- void FindDevicesImpl(const uint16 vendor_id,
- const uint16 product_id,
- std::vector<scoped_refptr<UsbDeviceHandle> >* devices,
- const base::Callback<void()>& callback,
- bool success);
+ void FindDevicesImpl(
+ const uint16 vendor_id,
+ const uint16 product_id,
+ const base::Callback<void(ScopedDeviceVector vector)>& callback,
+ bool success);
// Populates |output| with the result of enumerating all attached USB devices.
void EnumerateDevicesImpl(DeviceVector* output);
@@ -95,8 +105,7 @@ class UsbService {
// the wrapper with the device internally.
UsbDeviceHandle* LookupOrCreateDevice(PlatformUsbDevice device);
- PlatformUsbContext context_;
- UsbEventHandler* event_handler_;
+ scoped_refptr<UsbContext> context_;
// The devices_ map contains scoped_refptrs to all open devices, indicated by
// their vendor and product id. This allows for reusing an open device without