Chromium Code Reviews| Index: device/devices_app/usb/device_manager_impl.cc |
| diff --git a/device/devices_app/usb/device_manager_impl.cc b/device/devices_app/usb/device_manager_impl.cc |
| index f438460ddd828dae87a4c28ca2320c41c9e8660a..af45a36bc3c3423df9e9a42cc681607f5c156f80 100644 |
| --- a/device/devices_app/usb/device_manager_impl.cc |
| +++ b/device/devices_app/usb/device_manager_impl.cc |
| @@ -14,7 +14,6 @@ |
| #include "base/thread_task_runner_handle.h" |
| #include "device/core/device_client.h" |
| #include "device/devices_app/usb/device_impl.h" |
| -#include "device/devices_app/usb/public/cpp/device_manager_delegate.h" |
| #include "device/devices_app/usb/public/interfaces/device.mojom.h" |
| #include "device/devices_app/usb/type_converters.h" |
| #include "device/usb/usb_device.h" |
| @@ -108,6 +107,23 @@ void OpenDeviceOnServiceThread( |
| callback_task_runner)); |
| } |
| +void FilterDeviceListAndThen( |
| + const DeviceManagerImpl::GetDevicesCallback& callback, |
| + mojo::Array<DeviceInfoPtr> devices, |
| + mojo::Array<mojo::String> allowed_guids) { |
| + std::set<std::string> allowed_guid_set; |
| + for (size_t i = 0; i < allowed_guids.size(); ++i) |
| + allowed_guid_set.insert(allowed_guids[i]); |
| + |
| + mojo::Array<DeviceInfoPtr> allowed_devices(0); |
| + for (size_t i = 0; i < devices.size(); ++i) { |
| + if (ContainsKey(allowed_guid_set, devices[i]->guid)) |
| + allowed_devices.push_back(devices[i].Pass()); |
| + } |
| + |
| + callback.Run(allowed_devices.Pass()); |
| +} |
| + |
| } // namespace |
| class DeviceManagerImpl::ServiceThreadHelper |
| @@ -122,17 +138,10 @@ class DeviceManagerImpl::ServiceThreadHelper |
| base::MessageLoop::current()->RemoveDestructionObserver(this); |
| } |
| - static void Start( |
| - scoped_ptr<ServiceThreadHelper> self, |
| - const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback) { |
| + static void Start(scoped_ptr<ServiceThreadHelper> self) { |
| UsbService* usb_service = DeviceClient::Get()->GetUsbService(); |
| - if (usb_service) { |
| + if (usb_service) |
| self->observer_.Add(usb_service); |
| - std::vector<UsbDeviceFilter> no_filters; |
| - usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, |
| - no_filters, callback, |
| - self->task_runner_)); |
| - } |
| // |self| now owned by the current message loop. |
| base::MessageLoop::current()->AddDestructionObserver(self.release()); |
| @@ -163,30 +172,38 @@ class DeviceManagerImpl::ServiceThreadHelper |
| DeviceManagerImpl::DeviceManagerImpl( |
| mojo::InterfaceRequest<DeviceManager> request, |
| - scoped_ptr<DeviceManagerDelegate> delegate, |
| + PermissionProviderPtr permission_provider, |
| scoped_refptr<base::SequencedTaskRunner> service_task_runner) |
| - : binding_(this, request.Pass()), |
| - delegate_(delegate.Pass()), |
| + : permission_provider_(permission_provider.Pass()), |
| service_task_runner_(service_task_runner), |
| + binding_(this, request.Pass()), |
| weak_factory_(this) { |
| + // This object owns itself and will be destroyed if either the message pipe |
| + // it is bound to is closed or the PermissionProvider it depends on is |
| + // unavailable. |
| + binding_.set_connection_error_handler([this]() { delete this; }); |
| + permission_provider_.set_connection_error_handler([this]() { delete this; }); |
| + |
| + scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( |
| + weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); |
| + helper_ = helper.get(); |
| + service_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ServiceThreadHelper::Start, base::Passed(&helper))); |
| } |
| DeviceManagerImpl::~DeviceManagerImpl() { |
| - if (helper_) { |
| - // It is safe to call this if |helper_| was already destroyed when |
| - // |service_task_runner_| exited as the task will never execute. |
| - service_task_runner_->DeleteSoon(FROM_HERE, helper_); |
| - } |
| -} |
| - |
| -void DeviceManagerImpl::set_connection_error_handler( |
| - const mojo::Closure& error_handler) { |
| - binding_.set_connection_error_handler(error_handler); |
| + // It is safe to call this if |helper_| was already destroyed when |
| + // |service_task_runner_| exited as the task will never execute. |
| + service_task_runner_->DeleteSoon(FROM_HERE, helper_); |
| + connection_error_handler_.Run(); |
| } |
| void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, |
| const GetDevicesCallback& callback) { |
| - auto filters = options->filters.To<std::vector<UsbDeviceFilter>>(); |
| + std::vector<UsbDeviceFilter> filters; |
| + if (options) |
| + filters = options->filters.To<std::vector<UsbDeviceFilter>>(); |
| auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices, |
| weak_factory_.GetWeakPtr(), callback); |
| service_task_runner_->PostTask( |
| @@ -197,20 +214,8 @@ void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, |
| void DeviceManagerImpl::GetDeviceChanges( |
| const GetDeviceChangesCallback& callback) { |
| - if (helper_) { |
| - device_change_callbacks_.push(callback); |
| - MaybeRunDeviceChangesCallback(); |
| - } else { |
| - scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( |
| - weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); |
| - helper_ = helper.get(); |
| - auto get_devices_callback = |
| - base::Bind(&DeviceManagerImpl::OnGetInitialDevices, |
| - weak_factory_.GetWeakPtr(), callback); |
| - service_task_runner_->PostTask( |
| - FROM_HERE, base::Bind(&ServiceThreadHelper::Start, |
| - base::Passed(&helper), get_devices_callback)); |
| - } |
| + device_change_callbacks_.push(callback); |
| + MaybeRunDeviceChangesCallback(); |
| } |
| void DeviceManagerImpl::OpenDevice( |
| @@ -225,25 +230,13 @@ void DeviceManagerImpl::OpenDevice( |
| void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, |
| mojo::Array<DeviceInfoPtr> devices) { |
| - mojo::Array<DeviceInfoPtr> allowed_devices(0); |
| + mojo::Array<mojo::String> requested_guids(devices.size()); |
| for (size_t i = 0; i < devices.size(); ++i) { |
|
Ken Rockot(use gerrit already)
2015/09/03 00:06:11
extra nitty nit: no {}
Reilly Grant (use Gerrit)
2015/09/03 00:09:28
Done.
|
| - if (delegate_->IsDeviceAllowed(*devices[i])) |
| - allowed_devices.push_back(devices[i].Pass()); |
| - } |
| - callback.Run(allowed_devices.Pass()); |
| -} |
| - |
| -void DeviceManagerImpl::OnGetInitialDevices( |
| - const GetDeviceChangesCallback& callback, |
| - mojo::Array<DeviceInfoPtr> devices) { |
| - DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); |
| - notification->devices_added = mojo::Array<DeviceInfoPtr>::New(0); |
| - notification->devices_removed = mojo::Array<mojo::String>::New(0); |
| - for (size_t i = 0; i < devices.size(); ++i) { |
| - if (delegate_->IsDeviceAllowed(*devices[i])) |
| - notification->devices_added.push_back(devices[i].Pass()); |
| + requested_guids[i] = devices[i]->guid; |
| } |
| - callback.Run(notification.Pass()); |
| + permission_provider_->HasDevicePermission( |
| + requested_guids.Pass(), |
| + base::Bind(&FilterDeviceListAndThen, callback, base::Passed(&devices))); |
| } |
| void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { |
| @@ -268,18 +261,64 @@ void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { |
| } |
| void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { |
| - if (!device_change_callbacks_.empty()) { |
| + if (!permission_request_pending_ && !device_change_callbacks_.empty()) { |
| + mojo::Array<DeviceInfoPtr> devices_added; |
| + devices_added.Swap(&devices_added_); |
| + std::set<std::string> devices_removed; |
| + devices_removed.swap(devices_removed_); |
| + |
| + mojo::Array<mojo::String> requested_guids(devices_added.size() + |
| + devices_removed.size()); |
| + { |
| + size_t i; |
| + for (i = 0; i < devices_added.size(); ++i) |
| + requested_guids[i] = devices_added[i]->guid; |
| + for (const std::string& guid : devices_removed) |
| + requested_guids[i++] = guid; |
| + } |
| + |
| + permission_request_pending_ = true; |
| + permission_provider_->HasDevicePermission( |
| + requested_guids.Pass(), |
| + base::Bind(&DeviceManagerImpl::OnPermissionCheckComplete, |
| + base::Unretained(this), base::Passed(&devices_added), |
| + devices_removed)); |
| + } |
| +} |
| + |
| +void DeviceManagerImpl::OnPermissionCheckComplete( |
| + mojo::Array<DeviceInfoPtr> devices_added, |
| + const std::set<std::string>& devices_removed, |
| + mojo::Array<mojo::String> allowed_guids) { |
| + permission_request_pending_ = false; |
| + |
| + if (allowed_guids.size() > 0) { |
| + std::set<std::string> allowed_guid_set; |
| + for (size_t i = 0; i < allowed_guids.size(); ++i) |
| + allowed_guid_set.insert(allowed_guids[i]); |
| + |
| DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); |
| - notification->devices_added.Swap(&devices_added_); |
| + notification->devices_added.resize(0); |
| + for (size_t i = 0; i < devices_added.size(); ++i) { |
| + if (ContainsKey(allowed_guid_set, devices_added[i]->guid)) |
| + notification->devices_added.push_back(devices_added[i].Pass()); |
| + } |
| + |
| notification->devices_removed.resize(0); |
| - for (const std::string& device : devices_removed_) |
| - notification->devices_removed.push_back(device); |
| - devices_removed_.clear(); |
| + for (const std::string& guid : devices_removed) { |
| + if (ContainsKey(allowed_guid_set, guid)) |
| + notification->devices_removed.push_back(guid); |
| + } |
| + DCHECK(!device_change_callbacks_.empty()); |
| const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); |
| callback.Run(notification.Pass()); |
| device_change_callbacks_.pop(); |
| } |
| + |
| + if (devices_added_.size() > 0 || !devices_removed_.empty()) { |
| + MaybeRunDeviceChangesCallback(); |
| + } |
| } |
| } // namespace usb |