diff options
31 files changed, 410 insertions, 140 deletions
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e1222c3..5ee0844 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -156,7 +156,6 @@ static_library("browser") { "//components/storage_monitor", "//components/translate/content/browser", "//components/url_matcher", - "//components/usb_service", "//components/visitedlink/browser", "//components/visitedlink/common", "//components/web_modal", @@ -450,6 +449,10 @@ static_library("browser") { # Non-mobile. sources += rebase_path(gypi_values.chrome_browser_non_mobile_sources, ".", "//chrome") + deps += [ + "//components/usb_service", + "//device/core", + ] } if (is_android) { @@ -464,7 +467,6 @@ static_library("browser") { "//third_party/libaddressinput", "//components/feedback", "//components/storage_monitor", - "//components/usb_service", "//components/web_modal", ] } else { diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index d8d9246..0b17801 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -70,6 +70,7 @@ include_rules = [ "+components/translate/core/browser", "+components/translate/core/common", "+components/url_matcher", + "+components/usb_service", "+components/user_manager", "+components/user_prefs", "+components/web_modal", @@ -78,6 +79,7 @@ include_rules = [ "+content/test/net", "+courgette", "+device/bluetooth", + "+device/core", "+device/media_transfer_protocol", "+extensions/browser", "+extensions/common", diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 06301fd..ffa2082 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -106,6 +106,7 @@ #if defined(OS_ANDROID) #include "components/gcm_driver/gcm_driver_android.h" #else +#include "chrome/browser/chrome_device_client.h" #include "chrome/browser/services/gcm/gcm_desktop_utils.h" #include "components/gcm_driver/gcm_client_factory.h" #endif @@ -194,6 +195,10 @@ BrowserProcessImpl::BrowserProcessImpl( InitIdleMonitor(); #endif +#if !defined(OS_ANDROID) + device_client_.reset(new ChromeDeviceClient); +#endif + #if defined(ENABLE_EXTENSIONS) apps::AppsClient::Set(ChromeAppsClient::GetInstance()); diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 8fd4ce5..937f813 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -21,6 +21,7 @@ #include "base/timer/timer.h" #include "chrome/browser/browser_process.h" +class ChromeDeviceClient; class ChromeNetLog; class ChromeResourceDispatcherHostDelegate; class RemoteDebuggingServer; @@ -300,6 +301,10 @@ class BrowserProcessImpl : public BrowserProcess, scoped_ptr<gcm::GCMDriver> gcm_driver_; +#if !defined(OS_ANDROID) + scoped_ptr<ChromeDeviceClient> device_client_; +#endif + DISALLOW_COPY_AND_ASSIGN(BrowserProcessImpl); }; diff --git a/chrome/browser/chrome_device_client.cc b/chrome/browser/chrome_device_client.cc new file mode 100644 index 0000000..941e777 --- /dev/null +++ b/chrome/browser/chrome_device_client.cc @@ -0,0 +1,19 @@ +// Copyright 2014 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/chrome_device_client.h" + +#include "base/logging.h" +#include "components/usb_service/usb_service.h" +#include "content/public/browser/browser_thread.h" + +ChromeDeviceClient::ChromeDeviceClient() {} + +ChromeDeviceClient::~ChromeDeviceClient() {} + +usb_service::UsbService* ChromeDeviceClient::GetUsbService() { + return usb_service::UsbService::GetInstance( + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI)); +} diff --git a/chrome/browser/chrome_device_client.h b/chrome/browser/chrome_device_client.h new file mode 100644 index 0000000..d8814dc --- /dev/null +++ b/chrome/browser/chrome_device_client.h @@ -0,0 +1,27 @@ +// Copyright 2014 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_CHROME_DEVICE_CLIENT_H_ +#define CHROME_BROWSER_CHROME_DEVICE_CLIENT_H_ + +#include "device/core/device_client.h" + +#include "base/compiler_specific.h" +#include "base/macros.h" + +// Implementation of device::DeviceClient that returns //device service +// singletons appropriate for use within the Chrome application. +class ChromeDeviceClient : device::DeviceClient { + public: + ChromeDeviceClient(); + virtual ~ChromeDeviceClient(); + + // device::DeviceClient implementation + virtual usb_service::UsbService* GetUsbService() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeDeviceClient); +}; + +#endif // CHROME_BROWSER_CHROME_DEVICE_CLIENT_H_ diff --git a/chrome/browser/devtools/device/usb/DEPS b/chrome/browser/devtools/device/usb/DEPS deleted file mode 100644 index fc9564a..0000000 --- a/chrome/browser/devtools/device/usb/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+components/usb_service" -] diff --git a/chrome/browser/devtools/device/usb/android_usb_device.cc b/chrome/browser/devtools/device/usb/android_usb_device.cc index 3a2bee1..51aed47 100644 --- a/chrome/browser/devtools/device/usb/android_usb_device.cc +++ b/chrome/browser/devtools/device/usb/android_usb_device.cc @@ -21,6 +21,7 @@ #include "components/usb_service/usb_service.h" #include "content/public/browser/browser_thread.h" #include "crypto/rsa_private_key.h" +#include "device/core/device_client.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/socket/stream_socket.h" @@ -224,7 +225,7 @@ static void OpenAndroidDeviceOnFileThread( static int CountOnFileThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); UsbDevices usb_devices; if (service != NULL) service->GetDevices(&usb_devices); @@ -249,7 +250,7 @@ static void EnumerateOnFileThread( scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); UsbDevices usb_devices; if (service != NULL) service->GetDevices(&usb_devices); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 4fc4663..6de6837 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2279,6 +2279,8 @@ 'chrome_browser_non_mobile_sources': [ 'browser/chrome_browser_field_trials_desktop.cc', 'browser/chrome_browser_field_trials_desktop.h', + 'browser/chrome_device_client.cc', + 'browser/chrome_device_client.h', ], 'chrome_browser_supervised_user_sources': [ 'browser/supervised_user/custodian_profile_downloader_service.cc', @@ -2911,7 +2913,6 @@ '../components/components.gyp:storage_monitor', '../components/components.gyp:translate_content_browser', '../components/components.gyp:url_matcher', - '../components/components.gyp:usb_service', '../components/components.gyp:visitedlink_browser', '../components/components.gyp:visitedlink_common', '../components/components.gyp:web_modal', @@ -3236,6 +3237,10 @@ 'sources': [ '<@(chrome_browser_mobile_sources)' ], }, { # OS!="android" and OS!="ios" 'sources': [ '<@(chrome_browser_non_mobile_sources)' ], + 'dependencies': [ + '../components/components.gyp:usb_service', + '../device/core/core.gyp:device_core', + ] }], ['OS=="android"', { 'dependencies': [ @@ -3248,7 +3253,6 @@ 'dependencies!': [ '../components/components.gyp:feedback_component', '../components/components.gyp:storage_monitor', - '../components/components.gyp:usb_service', '../components/components.gyp:web_modal', '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput', ], diff --git a/components/usb_service/DEPS b/components/usb_service/DEPS index f416680..c114bca 100644 --- a/components/usb_service/DEPS +++ b/components/usb_service/DEPS @@ -1,8 +1,6 @@ include_rules = [ "+chromeos", - "+content/public/browser", - "-net", "+net/base", diff --git a/components/usb_service/usb_device_handle_impl.cc b/components/usb_service/usb_device_handle_impl.cc index 73b04b9..5823085 100644 --- a/components/usb_service/usb_device_handle_impl.cc +++ b/components/usb_service/usb_device_handle_impl.cc @@ -7,20 +7,20 @@ #include <algorithm> #include <vector> -#include "base/message_loop/message_loop.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string16.h" #include "base/synchronization/lock.h" +#include "base/thread_task_runner_handle.h" #include "components/usb_service/usb_context.h" #include "components/usb_service/usb_device_impl.h" #include "components/usb_service/usb_error.h" #include "components/usb_service/usb_interface.h" #include "components/usb_service/usb_service.h" -#include "content/public/browser/browser_thread.h" #include "third_party/libusb/src/libusb/libusb.h" -using content::BrowserThread; - namespace usb_service { typedef libusb_device* PlatformUsbDevice; @@ -103,24 +103,8 @@ static UsbTransferStatus ConvertTransferStatus( } } -static void LIBUSB_CALL -PlatformTransferCompletionCallback(PlatformUsbTransferHandle transfer) { - BrowserThread::PostTask(BrowserThread::FILE, - FROM_HERE, - base::Bind(HandleTransferCompletion, transfer)); -} - } // namespace -void HandleTransferCompletion(PlatformUsbTransferHandle transfer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - UsbDeviceHandleImpl* const device_handle = - reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); - CHECK(device_handle) << "Device handle is closed before transfer finishes."; - device_handle->TransferComplete(transfer); - libusb_free_transfer(transfer); -} - class UsbDeviceHandleImpl::InterfaceClaimer : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> { public: @@ -170,10 +154,12 @@ struct UsbDeviceHandleImpl::Transfer { Transfer(); ~Transfer(); + void Complete(UsbTransferStatus status, size_t bytes_transferred); + UsbTransferType transfer_type; scoped_refptr<net::IOBuffer> buffer; scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface; - scoped_refptr<base::MessageLoopProxy> message_loop_proxy; + scoped_refptr<base::SingleThreadTaskRunner> task_runner; size_t length; UsbTransferCallback callback; }; @@ -185,6 +171,16 @@ UsbDeviceHandleImpl::Transfer::Transfer() UsbDeviceHandleImpl::Transfer::~Transfer() { } +void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status, + size_t bytes_transferred) { + if (task_runner->RunsTasksOnCurrentThread()) { + callback.Run(status, buffer, bytes_transferred); + } else { + task_runner->PostTask( + FROM_HERE, base::Bind(callback, status, buffer, bytes_transferred)); + } +} + UsbDeviceHandleImpl::UsbDeviceHandleImpl( scoped_refptr<UsbContext> context, UsbDeviceImpl* device, @@ -193,8 +189,8 @@ UsbDeviceHandleImpl::UsbDeviceHandleImpl( : device_(device), handle_(handle), interfaces_(interfaces), - context_(context) { - DCHECK(thread_checker_.CalledOnValidThread()); + context_(context), + task_runner_(base::ThreadTaskRunnerHandle::Get()) { DCHECK(handle) << "Cannot create device with NULL handle."; DCHECK(interfaces_.get()) << "Unable to list interfaces"; } @@ -216,7 +212,18 @@ void UsbDeviceHandleImpl::Close() { device_->Close(this); } -void UsbDeviceHandleImpl::TransferComplete(PlatformUsbTransferHandle handle) { +/* static */ +void LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback( + PlatformUsbTransferHandle transfer) { + UsbDeviceHandleImpl* device_handle = + reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); + device_handle->task_runner_->PostTask( + FROM_HERE, + base::Bind( + &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer)); +} + +void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) { DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; Transfer transfer = transfers_[handle]; @@ -229,7 +236,6 @@ void UsbDeviceHandleImpl::TransferComplete(PlatformUsbTransferHandle handle) { DCHECK(transfer.length >= actual_length) << "data too big for our buffer (libusb failure?)"; - scoped_refptr<net::IOBuffer> buffer = transfer.buffer; switch (transfer.transfer_type) { case USB_TRANSFER_CONTROL: // If the transfer is a control transfer we do not expose the control @@ -246,9 +252,9 @@ void UsbDeviceHandleImpl::TransferComplete(PlatformUsbTransferHandle handle) { new net::IOBuffer(static_cast<int>( std::max(actual_length, static_cast<size_t>(1)))); memcpy(resized_buffer->data(), - buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, + transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, actual_length); - buffer = resized_buffer; + transfer.buffer = resized_buffer; } } break; @@ -268,8 +274,8 @@ void UsbDeviceHandleImpl::TransferComplete(PlatformUsbTransferHandle handle) { if (actual_length < packet_buffer_start) { CHECK(packet_buffer_start + packet->actual_length <= transfer.length); - memmove(buffer->data() + actual_length, - buffer->data() + packet_buffer_start, + memmove(transfer.buffer->data() + actual_length, + transfer.buffer->data() + packet_buffer_start, packet->actual_length); } actual_length += packet->actual_length; @@ -289,12 +295,8 @@ void UsbDeviceHandleImpl::TransferComplete(PlatformUsbTransferHandle handle) { break; } - transfer.message_loop_proxy->PostTask( - FROM_HERE, - base::Bind(transfer.callback, - ConvertTransferStatus(handle->status), - buffer, - actual_length)); + transfer.Complete(ConvertTransferStatus(handle->status), actual_length); + libusb_free_transfer(handle); // Must release interface first before actually delete this. transfer.claimed_interface = NULL; @@ -552,20 +554,12 @@ void UsbDeviceHandleImpl::ControlTransfer( libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(resized_buffer->data()), - PlatformTransferCompletionCallback, + &UsbDeviceHandleImpl::PlatformTransferCallback, this, timeout); - BrowserThread::PostTask(BrowserThread::FILE, - FROM_HERE, - base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, - this, - transfer, - USB_TRANSFER_CONTROL, - resized_buffer, - resized_length, - base::MessageLoopProxy::current(), - callback)); + PostOrSubmitTransfer( + transfer, USB_TRANSFER_CONTROL, resized_buffer, resized_length, callback); } void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, @@ -586,20 +580,11 @@ void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, new_endpoint, reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), - PlatformTransferCompletionCallback, + &UsbDeviceHandleImpl::PlatformTransferCallback, this, timeout); - BrowserThread::PostTask(BrowserThread::FILE, - FROM_HERE, - base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, - this, - transfer, - USB_TRANSFER_BULK, - make_scoped_refptr(buffer), - length, - base::MessageLoopProxy::current(), - callback)); + PostOrSubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback); } void UsbDeviceHandleImpl::InterruptTransfer( @@ -621,19 +606,12 @@ void UsbDeviceHandleImpl::InterruptTransfer( new_endpoint, reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), - PlatformTransferCompletionCallback, + &UsbDeviceHandleImpl::PlatformTransferCallback, this, timeout); - BrowserThread::PostTask(BrowserThread::FILE, - FROM_HERE, - base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, - this, - transfer, - USB_TRANSFER_INTERRUPT, - make_scoped_refptr(buffer), - length, - base::MessageLoopProxy::current(), - callback)); + + PostOrSubmitTransfer( + transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback); } void UsbDeviceHandleImpl::IsochronousTransfer( @@ -662,21 +640,13 @@ void UsbDeviceHandleImpl::IsochronousTransfer( reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), packets, - PlatformTransferCompletionCallback, + &UsbDeviceHandleImpl::PlatformTransferCallback, this, timeout); libusb_set_iso_packet_lengths(transfer, packet_length); - BrowserThread::PostTask(BrowserThread::FILE, - FROM_HERE, - base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, - this, - transfer, - USB_TRANSFER_ISOCHRONOUS, - make_scoped_refptr(buffer), - length, - base::MessageLoopProxy::current(), - callback)); + PostOrSubmitTransfer( + transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback); } void UsbDeviceHandleImpl::RefreshEndpointMap() { @@ -704,27 +674,52 @@ UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { return NULL; } +void UsbDeviceHandleImpl::PostOrSubmitTransfer( + PlatformUsbTransferHandle transfer, + UsbTransferType transfer_type, + net::IOBuffer* buffer, + size_t length, + const UsbTransferCallback& callback) { + if (task_runner_->RunsTasksOnCurrentThread()) { + SubmitTransfer(transfer, + transfer_type, + buffer, + length, + base::ThreadTaskRunnerHandle::Get(), + callback); + } else { + task_runner_->PostTask(FROM_HERE, + base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, + this, + transfer, + transfer_type, + make_scoped_refptr(buffer), + length, + base::ThreadTaskRunnerHandle::Get(), + callback)); + } +} + void UsbDeviceHandleImpl::SubmitTransfer( PlatformUsbTransferHandle handle, UsbTransferType transfer_type, net::IOBuffer* buffer, const size_t length, - scoped_refptr<base::MessageLoopProxy> message_loop_proxy, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, const UsbTransferCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); - if (!device_) { - message_loop_proxy->PostTask( - FROM_HERE, - base::Bind( - callback, USB_TRANSFER_DISCONNECT, make_scoped_refptr(buffer), 0)); - } Transfer transfer; transfer.transfer_type = transfer_type; transfer.buffer = buffer; transfer.length = length; transfer.callback = callback; - transfer.message_loop_proxy = message_loop_proxy; + transfer.task_runner = task_runner; + + if (!device_) { + transfer.Complete(USB_TRANSFER_DISCONNECT, 0); + return; + } // It's OK for this method to return NULL. libusb_submit_transfer will fail if // it requires an interface we didn't claim. @@ -735,10 +730,7 @@ void UsbDeviceHandleImpl::SubmitTransfer( transfers_[handle] = transfer; } else { VLOG(1) << "Failed to submit transfer: " << ConvertErrorToString(rv); - message_loop_proxy->PostTask( - FROM_HERE, - base::Bind( - callback, USB_TRANSFER_ERROR, make_scoped_refptr(buffer), 0)); + transfer.Complete(USB_TRANSFER_ERROR, 0); } } diff --git a/components/usb_service/usb_device_handle_impl.h b/components/usb_service/usb_device_handle_impl.h index 7d11337..66d6960 100644 --- a/components/usb_service/usb_device_handle_impl.h +++ b/components/usb_service/usb_device_handle_impl.h @@ -15,13 +15,10 @@ #include "components/usb_service/usb_device_handle.h" #include "components/usb_service/usb_interface.h" #include "net/base/io_buffer.h" - -struct libusb_device_handle; -struct libusb_iso_packet_descriptor; -struct libusb_transfer; +#include "third_party/libusb/src/libusb/libusb.h" namespace base { -class MessageLoopProxy; +class SingleThreadTaskRunner; } namespace usb_service { @@ -97,8 +94,6 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { virtual ~UsbDeviceHandleImpl(); private: - friend void HandleTransferCompletion(PlatformUsbTransferHandle handle); - class InterfaceClaimer; struct Transfer; @@ -111,6 +106,16 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { scoped_refptr<InterfaceClaimer> GetClaimedInterfaceForEndpoint( unsigned char endpoint); + // If the device's task runner is on the current thread then the transfer will + // be submitted directly, otherwise a task to do so it posted. The callback + // will be called on the current message loop of the thread where this + // function was called. + void PostOrSubmitTransfer(PlatformUsbTransferHandle handle, + UsbTransferType transfer_type, + net::IOBuffer* buffer, + size_t length, + const UsbTransferCallback& callback); + // Submits a transfer and starts tracking it. Retains the buffer and copies // the completion callback until the transfer finishes, whereupon it invokes // the callback then releases the buffer. @@ -118,12 +123,15 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { UsbTransferType transfer_type, net::IOBuffer* buffer, const size_t length, - scoped_refptr<base::MessageLoopProxy> message_loop_proxy, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, const UsbTransferCallback& callback); + static void LIBUSB_CALL + PlatformTransferCallback(PlatformUsbTransferHandle handle); + // Invokes the callbacks associated with a given transfer, and removes it from // the in-flight transfer set. - void TransferComplete(PlatformUsbTransferHandle transfer); + void CompleteTransfer(PlatformUsbTransferHandle transfer); bool GetSupportedLanguages(); bool GetStringDescriptor(uint8 string_id, base::string16* string); @@ -154,6 +162,8 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle { // before this handle. scoped_refptr<UsbContext> context_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandleImpl); diff --git a/components/usb_service/usb_device_impl.cc b/components/usb_service/usb_device_impl.cc index 243d25d..b6d2a12 100644 --- a/components/usb_service/usb_device_impl.cc +++ b/components/usb_service/usb_device_impl.cc @@ -6,12 +6,15 @@ #include <algorithm> +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "base/thread_task_runner_handle.h" #include "components/usb_service/usb_context.h" #include "components/usb_service/usb_device_handle_impl.h" #include "components/usb_service/usb_error.h" #include "components/usb_service/usb_interface_impl.h" -#include "content/public/browser/browser_thread.h" #include "third_party/libusb/src/libusb/libusb.h" #if defined(OS_CHROMEOS) @@ -20,16 +23,14 @@ #include "chromeos/dbus/permission_broker_client.h" #endif // defined(OS_CHROMEOS) -using content::BrowserThread; - namespace { #if defined(OS_CHROMEOS) void OnRequestUsbAccessReplied( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, const base::Callback<void(bool success)>& callback, bool success) { - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, base::Bind(callback, success)); + task_runner->PostTask(FROM_HERE, base::Bind(callback, success)); } #endif // defined(OS_CHROMEOS) @@ -37,14 +38,17 @@ void OnRequestUsbAccessReplied( namespace usb_service { -UsbDeviceImpl::UsbDeviceImpl(scoped_refptr<UsbContext> context, - PlatformUsbDevice platform_device, - uint16 vendor_id, - uint16 product_id, - uint32 unique_id) +UsbDeviceImpl::UsbDeviceImpl( + scoped_refptr<UsbContext> context, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + PlatformUsbDevice platform_device, + uint16 vendor_id, + uint16 product_id, + uint32 unique_id) : UsbDevice(vendor_id, product_id, unique_id), platform_device_(platform_device), - context_(context) { + context_(context), + ui_task_runner_(ui_task_runner) { CHECK(platform_device) << "platform_device cannot be NULL"; libusb_ref_device(platform_device); } @@ -77,15 +81,16 @@ void UsbDeviceImpl::RequestUsbAccess( return; } - BrowserThread::PostTask( - BrowserThread::UI, + ui_task_runner_->PostTask( FROM_HERE, base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess, base::Unretained(client), vendor_id(), product_id(), interface_id, - base::Bind(&OnRequestUsbAccessReplied, callback))); + base::Bind(&OnRequestUsbAccessReplied, + base::ThreadTaskRunnerHandle::Get(), + callback))); } } diff --git a/components/usb_service/usb_device_impl.h b/components/usb_service/usb_device_impl.h index e27a692..07711bc 100644 --- a/components/usb_service/usb_device_impl.h +++ b/components/usb_service/usb_device_impl.h @@ -15,6 +15,10 @@ struct libusb_device; struct libusb_config_descriptor; +namespace base { +class SingleThreadTaskRunner; +} + namespace usb_service { class UsbDeviceHandleImpl; @@ -40,6 +44,7 @@ class UsbDeviceImpl : public UsbDevice { // Called by UsbServiceImpl only; UsbDeviceImpl(scoped_refptr<UsbContext> context, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, PlatformUsbDevice platform_device, uint16 vendor_id, uint16 product_id, @@ -61,6 +66,9 @@ class UsbDeviceImpl : public UsbDevice { typedef std::vector<scoped_refptr<UsbDeviceHandleImpl> > HandlesVector; HandlesVector handles_; + // Reference to the UI thread for permission-broker calls. + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; + DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl); }; diff --git a/components/usb_service/usb_service.h b/components/usb_service/usb_service.h index 133cacd..11eac1a 100644 --- a/components/usb_service/usb_service.h +++ b/components/usb_service/usb_service.h @@ -12,6 +12,10 @@ #include "base/threading/non_thread_safe.h" #include "components/usb_service/usb_service_export.h" +namespace base { +class SingleThreadTaskRunner; +} + namespace usb_service { class UsbDevice; @@ -22,9 +26,12 @@ class UsbDevice; // competition for the same USB device. class USB_SERVICE_EXPORT UsbService : public base::NonThreadSafe { public: - // Must be called on FILE thread. - // Returns NULL when failed to initialized. - static UsbService* GetInstance(); + // Must be called on a thread with a MessageLoopForIO (for example + // BrowserThread::FILE). The UI task runner reference is used to talk to the + // PermissionBrokerClient on ChromeOS (UI thread). Returns NULL when + // initialization fails. + static UsbService* GetInstance( + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); static void SetInstanceForTest(UsbService* instance); diff --git a/components/usb_service/usb_service_impl.cc b/components/usb_service/usb_service_impl.cc index a77749e..051bead 100644 --- a/components/usb_service/usb_service_impl.cc +++ b/components/usb_service/usb_service_impl.cc @@ -9,11 +9,11 @@ #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" +#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "components/usb_service/usb_context.h" #include "components/usb_service/usb_device_impl.h" #include "components/usb_service/usb_error.h" -#include "content/public/browser/browser_thread.h" #include "third_party/libusb/src/libusb/libusb.h" namespace usb_service { @@ -32,7 +32,9 @@ class UsbServiceImpl : public UsbService, private base::MessageLoop::DestructionObserver { public: - explicit UsbServiceImpl(PlatformUsbContext context); + explicit UsbServiceImpl( + PlatformUsbContext context, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); virtual ~UsbServiceImpl(); private: @@ -48,6 +50,8 @@ class UsbServiceImpl void RefreshDevices(); scoped_refptr<UsbContext> context_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; // TODO(ikarienator): Figure out a better solution. uint32 next_unique_id_; @@ -85,8 +89,12 @@ void UsbServiceImpl::WillDestroyCurrentMessageLoop() { g_usb_service_instance.Get().reset(NULL); } -UsbServiceImpl::UsbServiceImpl(PlatformUsbContext context) - : context_(new UsbContext(context)), next_unique_id_(0) { +UsbServiceImpl::UsbServiceImpl( + PlatformUsbContext context, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) + : context_(new UsbContext(context)), + ui_task_runner_(ui_task_runner), + next_unique_id_(0) { base::MessageLoop::current()->AddDestructionObserver(this); } @@ -124,6 +132,7 @@ void UsbServiceImpl::RefreshDevices() { continue; } UsbDeviceImpl* new_device = new UsbDeviceImpl(context_, + ui_task_runner_, platform_devices[i], descriptor.idVendor, descriptor.idProduct, @@ -153,7 +162,8 @@ void UsbServiceImpl::RefreshDevices() { } // static -UsbService* UsbService::GetInstance() { +UsbService* UsbService::GetInstance( + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { UsbService* instance = g_usb_service_instance.Get().get(); if (!instance) { PlatformUsbContext context = NULL; @@ -166,7 +176,7 @@ UsbService* UsbService::GetInstance() { if (!context) return NULL; - instance = new UsbServiceImpl(context); + instance = new UsbServiceImpl(context, ui_task_runner); g_usb_service_instance.Get().reset(instance); } return instance; diff --git a/device/core/BUILD.gn b/device/core/BUILD.gn new file mode 100644 index 0000000..7d1671f --- /dev/null +++ b/device/core/BUILD.gn @@ -0,0 +1,10 @@ +# Copyright 2014 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. + +source_set("core") { + sources = [ + "device_client.cc", + "device_client.h", + ] +} diff --git a/device/core/core.gyp b/device/core/core.gyp new file mode 100644 index 0000000..09bd315 --- /dev/null +++ b/device/core/core.gyp @@ -0,0 +1,22 @@ +# Copyright 2014 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'device_core', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'sources': [ + 'device_client.cc', + 'device_client.h', + ], + }, + ], +} diff --git a/device/core/device_client.cc b/device/core/device_client.cc new file mode 100644 index 0000000..ad96b1e --- /dev/null +++ b/device/core/device_client.cc @@ -0,0 +1,38 @@ +// Copyright 2014 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 "device/core/device_client.h" + +#include "base/logging.h" + +namespace device { + +namespace { + +DeviceClient* g_instance = NULL; + +} // namespace + +DeviceClient::DeviceClient() { + DCHECK(!g_instance); + g_instance = this; +} + +DeviceClient::~DeviceClient() { + g_instance = NULL; +} + +/* static */ +DeviceClient* DeviceClient::Get() { + DCHECK(g_instance); + return g_instance; +} + +usb_service::UsbService* DeviceClient::GetUsbService() { + // This should never be called by clients which do not support the USB API. + NOTREACHED(); + return NULL; +} + +} // namespace device diff --git a/device/core/device_client.h b/device/core/device_client.h new file mode 100644 index 0000000..d8d938b --- /dev/null +++ b/device/core/device_client.h @@ -0,0 +1,39 @@ +// Copyright 2014 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 DEVICE_CORE_DEVICE_CLIENT_H_ +#define DEVICE_CORE_DEVICE_CLIENT_H_ + +#include "base/macros.h" + +namespace usb_service { +class UsbService; +} + +namespace device { + +// Interface used by consumers of //device APIs to get pointers to the service +// singletons appropriate for a given embedding application. For an example see +// //chrome/browser/chrome_device_client.h. +class DeviceClient { + public: + // Construction sets the single instance. + DeviceClient(); + + // Destruction clears the single instance. + ~DeviceClient(); + + // Returns the single instance of |this|. + static DeviceClient* Get(); + + // Returns the UsbService instance for this embedder. + virtual usb_service::UsbService* GetUsbService(); + + private: + DISALLOW_COPY_AND_ASSIGN(DeviceClient); +}; + +} // namespace device + +#endif // DEVICE_CORE_DEVICE_CLIENT_H_ diff --git a/device/test/usb_test_gadget_impl.cc b/device/test/usb_test_gadget_impl.cc index 59a5faa..e95188b 100644 --- a/device/test/usb_test_gadget_impl.cc +++ b/device/test/usb_test_gadget_impl.cc @@ -155,7 +155,7 @@ UsbTestGadgetImpl::UsbTestGadgetImpl() { session_id_ = base::StringPrintf( "%s:%p", base::HexEncode(&process_id, sizeof(process_id)).c_str(), this); - usb_service_ = UsbService::GetInstance(); + usb_service_ = UsbService::GetInstance(NULL); } UsbTestGadgetImpl::~UsbTestGadgetImpl() { diff --git a/extensions/browser/api/usb/DEPS b/extensions/browser/api/usb/DEPS index 70ac41d..549aed6 100644 --- a/extensions/browser/api/usb/DEPS +++ b/extensions/browser/api/usb/DEPS @@ -1,3 +1,4 @@ include_rules = [ "+components/usb_service", + "+device/core" ] diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc index 05cc15e..20ed117 100644 --- a/extensions/browser/api/usb/usb_api.cc +++ b/extensions/browser/api/usb/usb_api.cc @@ -11,6 +11,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "components/usb_service/usb_device_handle.h" #include "components/usb_service/usb_service.h" +#include "device/core/device_client.h" #include "extensions/browser/api/usb/usb_device_resource.h" #include "extensions/browser/extension_system.h" #include "extensions/common/api/usb.h" @@ -429,7 +430,7 @@ scoped_refptr<UsbDevice> UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError( return NULL; } - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); if (!service) { CompleteWithError(kErrorInitService); return NULL; @@ -560,7 +561,7 @@ void UsbFindDevicesFunction::AsyncWorkStart() { return; } - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); if (!service) { CompleteWithError(kErrorInitService); return; @@ -636,7 +637,7 @@ void UsbGetDevicesFunction::AsyncWorkStart() { return; } - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); if (!service) { CompleteWithError(kErrorInitService); return; diff --git a/extensions/browser/api/usb_private/DEPS b/extensions/browser/api/usb_private/DEPS index d8eab5d..1afc5ec 100644 --- a/extensions/browser/api/usb_private/DEPS +++ b/extensions/browser/api/usb_private/DEPS @@ -1,4 +1,5 @@ include_rules = [ "+components/usb_service", + "+device/core", "+device/usb", ] diff --git a/extensions/browser/api/usb_private/usb_private_api.cc b/extensions/browser/api/usb_private/usb_private_api.cc index 860a13a..22c11ba 100644 --- a/extensions/browser/api/usb_private/usb_private_api.cc +++ b/extensions/browser/api/usb_private/usb_private_api.cc @@ -12,6 +12,7 @@ #include "components/usb_service/usb_device_filter.h" #include "components/usb_service/usb_device_handle.h" #include "components/usb_service/usb_service.h" +#include "device/core/device_client.h" #include "device/usb/usb_ids.h" #include "extensions/common/api/usb_private.h" @@ -19,6 +20,7 @@ namespace usb_private = extensions::core_api::usb_private; namespace GetDevices = usb_private::GetDevices; namespace GetDeviceInfo = usb_private::GetDeviceInfo; +using content::BrowserThread; using usb_service::UsbDevice; using usb_service::UsbDeviceFilter; using usb_service::UsbDeviceHandle; @@ -47,7 +49,7 @@ bool UsbPrivateGetDevicesFunction::Prepare() { } void UsbPrivateGetDevicesFunction::AsyncWorkStart() { - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); if (!service) { CompleteWithError(kErrorInitService); return; @@ -117,7 +119,7 @@ bool UsbPrivateGetDeviceInfoFunction::Prepare() { } void UsbPrivateGetDeviceInfoFunction::AsyncWorkStart() { - UsbService* service = UsbService::GetInstance(); + UsbService* service = device::DeviceClient::Get()->GetUsbService(); if (!service) { CompleteWithError(kErrorInitService); return; diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp index ca52ece..1df7adf5 100644 --- a/extensions/shell/app_shell.gyp +++ b/extensions/shell/app_shell.gyp @@ -22,6 +22,7 @@ '<(DEPTH)/content/content.gyp:content_gpu', '<(DEPTH)/content/content.gyp:content_ppapi_plugin', '<(DEPTH)/content/content_shell_and_tests.gyp:content_shell_lib', + '<(DEPTH)/device/core/core.gyp:device_core', '<(DEPTH)/device/hid/hid.gyp:device_hid', '<(DEPTH)/extensions/browser/api/api_registration.gyp:extensions_api_registration', '<(DEPTH)/extensions/common/api/api.gyp:extensions_api', @@ -71,6 +72,8 @@ 'browser/shell_content_browser_client.h', 'browser/shell_desktop_controller.cc', 'browser/shell_desktop_controller.h', + 'browser/shell_device_client.cc', + 'browser/shell_device_client.h', 'browser/shell_extension_host_delegate.cc', 'browser/shell_extension_host_delegate.h', 'browser/shell_extension_system.cc', diff --git a/extensions/shell/browser/DEPS b/extensions/shell/browser/DEPS index 597cad0..a98697b 100644 --- a/extensions/shell/browser/DEPS +++ b/extensions/shell/browser/DEPS @@ -14,6 +14,8 @@ include_rules = [ "+content/shell/browser/shell_net_log.h", # For device backend support. + "+components/usb_service", + "+device/core", "+device/hid", # Only used in API tests that should be moved to extensions/browser/api/... diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc index 24f7e028..c11fd8e 100644 --- a/extensions/shell/browser/shell_browser_main_parts.cc +++ b/extensions/shell/browser/shell_browser_main_parts.cc @@ -17,6 +17,7 @@ #include "extensions/shell/browser/shell_browser_context.h" #include "extensions/shell/browser/shell_browser_main_delegate.h" #include "extensions/shell/browser/shell_desktop_controller.h" +#include "extensions/shell/browser/shell_device_client.h" #include "extensions/shell/browser/shell_extension_system.h" #include "extensions/shell/browser/shell_extension_system_factory.h" #include "extensions/shell/browser/shell_extensions_browser_client.h" @@ -105,6 +106,8 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() { // TODO(jamescook): Initialize user_manager::UserManager. net_log_.reset(new content::ShellNetLog("app_shell")); + device_client_.reset(new ShellDeviceClient); + extensions_client_.reset(new ShellExtensionsClient()); ExtensionsClient::Set(extensions_client_.get()); diff --git a/extensions/shell/browser/shell_browser_main_parts.h b/extensions/shell/browser/shell_browser_main_parts.h index e8e1b20..264a5f3 100644 --- a/extensions/shell/browser/shell_browser_main_parts.h +++ b/extensions/shell/browser/shell_browser_main_parts.h @@ -30,6 +30,7 @@ namespace extensions { class DesktopController; class ShellBrowserContext; class ShellBrowserMainDelegate; +class ShellDeviceClient; class ShellExtensionsBrowserClient; class ShellExtensionsClient; class ShellExtensionSystem; @@ -69,6 +70,7 @@ class ShellBrowserMainParts : public content::BrowserMainParts { #endif scoped_ptr<DesktopController> desktop_controller_; scoped_ptr<ShellBrowserContext> browser_context_; + scoped_ptr<ShellDeviceClient> device_client_; scoped_ptr<ShellExtensionsClient> extensions_client_; scoped_ptr<ShellExtensionsBrowserClient> extensions_browser_client_; scoped_ptr<net::NetLog> net_log_; diff --git a/extensions/shell/browser/shell_device_client.cc b/extensions/shell/browser/shell_device_client.cc new file mode 100644 index 0000000..3120c01 --- /dev/null +++ b/extensions/shell/browser/shell_device_client.cc @@ -0,0 +1,23 @@ +// Copyright 2014 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 "extensions/shell/browser/shell_device_client.h" + +#include "base/logging.h" +#include "components/usb_service/usb_service.h" +#include "content/public/browser/browser_thread.h" + +namespace extensions { + +ShellDeviceClient::ShellDeviceClient() {} + +ShellDeviceClient::~ShellDeviceClient() {} + +usb_service::UsbService* ShellDeviceClient::GetUsbService() { + return usb_service::UsbService::GetInstance( + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI)); +} + +} diff --git a/extensions/shell/browser/shell_device_client.h b/extensions/shell/browser/shell_device_client.h new file mode 100644 index 0000000..d34e3ca --- /dev/null +++ b/extensions/shell/browser/shell_device_client.h @@ -0,0 +1,31 @@ +// Copyright 2014 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 EXTENSIONS_SHELL_BROWSER_SHELL_DEVICE_CLIENT_H_ +#define EXTENSIONS_SHELL_BROWSER_SHELL_DEVICE_CLIENT_H_ + +#include "device/core/device_client.h" + +#include "base/compiler_specific.h" +#include "base/macros.h" + +namespace extensions { + +// Implementation of device::DeviceClient that returns //device API service +// singletons appropriate for use within app shell. +class ShellDeviceClient : device::DeviceClient { + public: + ShellDeviceClient(); + virtual ~ShellDeviceClient(); + + // device::DeviceClient implementation + virtual usb_service::UsbService* GetUsbService() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(ShellDeviceClient); +}; + +} + +#endif // EXTENSIONS_SHELL_BROWSER_SHELL_DEVICE_CLIENT_H_ |