From 6871112deb52f0469df3b9b2d8f11f2a78ee89de Mon Sep 17 00:00:00 2001 From: reillyg Date: Tue, 6 Jan 2015 14:10:54 -0800 Subject: Update the device permissions prompt when the device list changes. This patch sets up DevicePermissionsPrompt::Prompt as a UsbService::Observer so that the UI is updated whenever a device is connected or disconnected. BUG=411715 Review URL: https://codereview.chromium.org/839453002 Cr-Commit-Position: refs/heads/master@{#310157} --- .../browser/api/device_permissions_prompt.cc | 166 ++++++++++++--------- extensions/browser/api/device_permissions_prompt.h | 30 ++-- 2 files changed, 119 insertions(+), 77 deletions(-) (limited to 'extensions') diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc index 8ae6776..afb895c 100644 --- a/extensions/browser/api/device_permissions_prompt.cc +++ b/extensions/browser/api/device_permissions_prompt.cc @@ -17,23 +17,53 @@ #include "extensions/strings/grit/extensions_strings.h" #include "ui/base/l10n/l10n_util.h" -namespace extensions { - using device::UsbDevice; using device::UsbDeviceFilter; using device::UsbService; +namespace extensions { + DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo( - scoped_refptr device, - const base::string16& name, - const base::string16& product_string, - const base::string16& manufacturer_string, - const base::string16& serial_number) - : device(device), - name(name), - product_string(product_string), - manufacturer_string(manufacturer_string), - serial_number(serial_number) { + scoped_refptr device) + : device(device) { + base::string16 manufacturer_string; + if (device->GetManufacturer(&manufacturer_string)) { + original_manufacturer_string = manufacturer_string; + } else { + const char* vendor_name = + device::UsbIds::GetVendorName(device->vendor_id()); + if (vendor_name) { + manufacturer_string = base::UTF8ToUTF16(vendor_name); + } else { + base::string16 vendor_id = + base::ASCIIToUTF16(base::StringPrintf("0x%04x", device->vendor_id())); + manufacturer_string = + l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id); + } + } + + base::string16 product_string; + if (device->GetProduct(&product_string)) { + original_product_string = product_string; + } else { + const char* product_name = device::UsbIds::GetProductName( + device->vendor_id(), device->product_id()); + if (product_name) { + product_string = base::UTF8ToUTF16(product_name); + } else { + base::string16 product_id = base::ASCIIToUTF16( + base::StringPrintf("0x%04x", device->product_id())); + product_string = + l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); + } + } + + if (!device->GetSerialNumber(&serial_number)) { + serial_number.clear(); + } + + name = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, + product_string, manufacturer_string); } DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() { @@ -43,16 +73,18 @@ DevicePermissionsPrompt::Prompt::Prompt() : extension_(nullptr), browser_context_(nullptr), multiple_(false), - observer_(nullptr) { + observer_(nullptr), + usb_service_observer_(this) { } void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) { observer_ = observer; - content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&DevicePermissionsPrompt::Prompt::DoDeviceQuery, this)); + if (observer_) { + content::BrowserThread::PostTask( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&DevicePermissionsPrompt::Prompt::DoDeviceQuery, this)); + } } base::string16 DevicePermissionsPrompt::Prompt::GetHeading() const { @@ -81,11 +113,9 @@ void DevicePermissionsPrompt::Prompt::GrantDevicePermission( DevicePermissionsManager::Get(browser_context_); if (permissions_manager) { const DeviceInfo& device = devices_[index]; - permissions_manager->AllowUsbDevice(extension_->id(), - device.device, - device.product_string, - device.manufacturer_string, - device.serial_number); + permissions_manager->AllowUsbDevice( + extension_->id(), device.device, device.original_product_string, + device.original_manufacturer_string, device.serial_number); } } @@ -112,53 +142,11 @@ void DevicePermissionsPrompt::Prompt::DoDeviceQuery() { continue; } - base::string16 manufacturer_string; - base::string16 original_manufacturer_string; - if (device->GetManufacturer(&original_manufacturer_string)) { - manufacturer_string = original_manufacturer_string; - } else { - const char* vendor_name = - device::UsbIds::GetVendorName(device->vendor_id()); - if (vendor_name) { - manufacturer_string = base::UTF8ToUTF16(vendor_name); - } else { - base::string16 vendor_id = base::ASCIIToUTF16( - base::StringPrintf("0x%04x", device->vendor_id())); - manufacturer_string = - l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id); - } - } - - base::string16 product_string; - base::string16 original_product_string; - if (device->GetProduct(&original_product_string)) { - product_string = original_product_string; - } else { - const char* product_name = device::UsbIds::GetProductName( - device->vendor_id(), device->product_id()); - if (product_name) { - product_string = base::UTF8ToUTF16(product_name); - } else { - base::string16 product_id = base::ASCIIToUTF16( - base::StringPrintf("0x%04x", device->product_id())); - product_string = - l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); - } - } - - base::string16 serial_number; - if (!device->GetSerialNumber(&serial_number)) { - serial_number.clear(); - } + device_info.push_back(DeviceInfo(device)); + } - device_info.push_back(DeviceInfo( - device, - l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, - product_string, - manufacturer_string), - original_product_string, - original_manufacturer_string, - serial_number)); + if (!usb_service_observer_.IsObserving(service)) { + usb_service_observer_.Add(service); } content::BrowserThread::PostTask( @@ -176,6 +164,48 @@ void DevicePermissionsPrompt::Prompt::SetDevices( } } +void DevicePermissionsPrompt::Prompt::AddDevice(const DeviceInfo& device) { + devices_.push_back(device); + if (observer_) { + observer_->OnDevicesChanged(); + } +} + +void DevicePermissionsPrompt::Prompt::RemoveDevice( + scoped_refptr device) { + bool removed_entry = false; + for (std::vector::iterator it = devices_.begin(); + it != devices_.end(); ++it) { + if (it->device == device) { + devices_.erase(it); + removed_entry = true; + break; + } + } + if (observer_ && removed_entry) { + observer_->OnDevicesChanged(); + } +} + +void DevicePermissionsPrompt::Prompt::OnDeviceAdded( + scoped_refptr device) { + if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) { + return; + } + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&DevicePermissionsPrompt::Prompt::AddDevice, this, + DeviceInfo(device))); +} + +void DevicePermissionsPrompt::Prompt::OnDeviceRemoved( + scoped_refptr device) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&DevicePermissionsPrompt::Prompt::RemoveDevice, this, device)); +} + DevicePermissionsPrompt::DevicePermissionsPrompt( content::WebContents* web_contents) : web_contents_(web_contents), delegate_(nullptr) { diff --git a/extensions/browser/api/device_permissions_prompt.h b/extensions/browser/api/device_permissions_prompt.h index 6679a16..3ef2587 100644 --- a/extensions/browser/api/device_permissions_prompt.h +++ b/extensions/browser/api/device_permissions_prompt.h @@ -10,7 +10,10 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/scoped_observer.h" #include "base/strings/string16.h" +#include "content/public/browser/browser_thread.h" +#include "device/usb/usb_service.h" namespace content { class BrowserContext; @@ -31,21 +34,20 @@ class Extension; class DevicePermissionsPrompt { public: // Context information available to the UI implementation. - class Prompt : public base::RefCountedThreadSafe { + class Prompt : public base::RefCountedThreadSafe< + Prompt, + content::BrowserThread::DeleteOnFileThread>, + public device::UsbService::Observer { public: // Displayed properties of a device. struct DeviceInfo { - DeviceInfo(scoped_refptr device, - const base::string16& name, - const base::string16& product_string, - const base::string16& manufacturer_string, - const base::string16& serial_number); + DeviceInfo(scoped_refptr device); ~DeviceInfo(); scoped_refptr device; base::string16 name; - base::string16 product_string; - base::string16 manufacturer_string; + base::string16 original_manufacturer_string; + base::string16 original_product_string; base::string16 serial_number; }; @@ -96,13 +98,21 @@ class DevicePermissionsPrompt { void set_filters(const std::vector& filters); private: - friend class base::RefCountedThreadSafe; + friend struct content::BrowserThread::DeleteOnThread< + content::BrowserThread::FILE>; + friend class base::DeleteHelper; virtual ~Prompt(); // Querying for devices must be done asynchronously on the FILE thread. void DoDeviceQuery(); void SetDevices(const std::vector& devices); + void AddDevice(const DeviceInfo& device); + void RemoveDevice(scoped_refptr device); + + // device::UsbService::Observer implementation: + void OnDeviceAdded(scoped_refptr device) override; + void OnDeviceRemoved(scoped_refptr device) override; const extensions::Extension* extension_; content::BrowserContext* browser_context_; @@ -110,6 +120,8 @@ class DevicePermissionsPrompt { std::vector filters_; std::vector devices_; Observer* observer_; + ScopedObserver + usb_service_observer_; }; class Delegate { -- cgit v1.1