Fail gracefully when libusb_init fails

BUG=280668

Review URL: https://chromiumcodereview.appspot.com/23571007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221508 0039d316-1c4b-4281-b951-d872f2087c98
parent d34e4070
......@@ -59,6 +59,8 @@ namespace {
const char kDataKey[] = "data";
const char kResultCodeKey[] = "resultCode";
const char kErrorInitService[] = "Failed to initialize USB service.";
const char kErrorOpen[] = "Failed to open device.";
const char kErrorCancelled[] = "Transfer was cancelled.";
const char kErrorDisconnect[] = "Device disconnected.";
......@@ -412,6 +414,10 @@ UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError(
}
UsbService* service = UsbService::GetInstance();
if (!service) {
CompleteWithError(kErrorInitService);
return NULL;
}
scoped_refptr<UsbDevice> device;
device = service->GetDeviceById(input_device.device);
......@@ -537,6 +543,11 @@ void UsbFindDevicesFunction::AsyncWorkStart() {
}
UsbService *service = UsbService::GetInstance();
if (!service) {
CompleteWithError(kErrorInitService);
return;
}
ScopedDeviceVector devices(new DeviceVector());
service->GetDevices(devices.get());
......@@ -624,6 +635,11 @@ void UsbGetDevicesFunction::AsyncWorkStart() {
}
UsbService* service = UsbService::GetInstance();
if (!service) {
CompleteWithError(kErrorInitService);
return;
}
DeviceVector devices;
service->GetDevices(&devices);
......
......@@ -60,9 +60,8 @@ void UsbContext::UsbEventHandler::ThreadMain() {
VLOG(1) << "UsbEventHandler shutting down.";
}
UsbContext::UsbContext() : context_(NULL) {
UsbContext::UsbContext(PlatformUsbContext context) : context_(context) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK_EQ(0, libusb_init(&context_)) << "Cannot initialize libusb";
event_handler_ = new UsbEventHandler(context_);
}
......
......@@ -27,7 +27,7 @@ class UsbContext : public base::RefCountedThreadSafe<UsbContext> {
friend class UsbService;
friend class base::RefCountedThreadSafe<UsbContext>;
UsbContext();
explicit UsbContext(PlatformUsbContext context);
virtual ~UsbContext();
private:
......
......@@ -7,6 +7,7 @@
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libusb/src/libusb/libusb.h"
namespace {
......@@ -14,7 +15,8 @@ class UsbContextTest : public testing::Test {
protected:
class UsbContextForTest : public UsbContext {
public:
UsbContextForTest() : UsbContext() {}
explicit UsbContextForTest(PlatformUsbContext context)
: UsbContext(context) {}
private:
virtual ~UsbContextForTest() {}
DISALLOW_COPY_AND_ASSIGN(UsbContextForTest);
......@@ -36,7 +38,10 @@ class UsbContextTest : public testing::Test {
TEST_F(UsbContextTest, MAYBE_GracefulShutdown) {
base::TimeTicks start = base::TimeTicks::Now();
{
scoped_refptr<UsbContextForTest> context(new UsbContextForTest());
PlatformUsbContext platform_context;
ASSERT_EQ(LIBUSB_SUCCESS, libusb_init(&platform_context));
scoped_refptr<UsbContextForTest> context(
new UsbContextForTest(platform_context));
}
base::TimeDelta elapse = base::TimeTicks::Now() - start;
if (elapse > base::TimeDelta::FromSeconds(2)) {
......
......@@ -64,8 +64,8 @@ class ExitObserver : public content::NotificationObserver {
using content::BrowserThread;
UsbService::UsbService()
: context_(new UsbContext()),
UsbService::UsbService(PlatformUsbContext context)
: context_(new UsbContext(context)),
next_unique_id_(0) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Will be deleted upon NOTIFICATION_APP_TERMINATING.
......@@ -79,10 +79,22 @@ UsbService::~UsbService() {
}
}
struct InitUsbContextTraits : public LeakySingletonTraits<UsbService> {
// LeakySingletonTraits<UsbService>
static UsbService* New() {
PlatformUsbContext context = NULL;
if (libusb_init(&context) != LIBUSB_SUCCESS)
return NULL;
if (!context)
return NULL;
return new UsbService(context);
}
};
UsbService* UsbService::GetInstance() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// UsbService deletes itself upon APP_TERMINATING.
return Singleton<UsbService, LeakySingletonTraits<UsbService> >::get();
return Singleton<UsbService, InitUsbContextTraits>::get();
}
void UsbService::GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices) {
......
......@@ -20,9 +20,11 @@ template <class T> class DeleteHelper;
} // namespace base
struct InitUsbContextTraits;
template <typename T> struct DefaultSingletonTraits;
typedef struct libusb_device* PlatformUsbDevice;
typedef struct libusb_context* PlatformUsbContext;
class UsbContext;
class UsbDevice;
......@@ -37,6 +39,7 @@ class UsbService {
ScopedDeviceVector;
// Must be called on FILE thread.
// Returns NULL when failed to initialized.
static UsbService* GetInstance();
scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id);
......@@ -47,10 +50,11 @@ class UsbService {
void GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices);
private:
friend struct InitUsbContextTraits;
friend struct DefaultSingletonTraits<UsbService>;
friend class base::DeleteHelper<UsbService>;
UsbService();
explicit UsbService(PlatformUsbContext context);
virtual ~UsbService();
// Return true if |device|'s vendor and product identifiers match |vendor_id|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment