Commit 6871112d authored by reillyg's avatar reillyg Committed by Commit bot

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}
parent 4949a513
......@@ -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<UsbDevice> 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<UsbDevice> 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<UsbDevice> device) {
bool removed_entry = false;
for (std::vector<DeviceInfo>::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<UsbDevice> 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<UsbDevice> 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) {
......
......@@ -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<Prompt> {
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::UsbDevice> device,
const base::string16& name,
const base::string16& product_string,
const base::string16& manufacturer_string,
const base::string16& serial_number);
DeviceInfo(scoped_refptr<device::UsbDevice> device);
~DeviceInfo();
scoped_refptr<device::UsbDevice> 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<device::UsbDeviceFilter>& filters);
private:
friend class base::RefCountedThreadSafe<Prompt>;
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::FILE>;
friend class base::DeleteHelper<Prompt>;
virtual ~Prompt();
// Querying for devices must be done asynchronously on the FILE thread.
void DoDeviceQuery();
void SetDevices(const std::vector<DeviceInfo>& devices);
void AddDevice(const DeviceInfo& device);
void RemoveDevice(scoped_refptr<device::UsbDevice> device);
// device::UsbService::Observer implementation:
void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override;
void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override;
const extensions::Extension* extension_;
content::BrowserContext* browser_context_;
......@@ -110,6 +120,8 @@ class DevicePermissionsPrompt {
std::vector<device::UsbDeviceFilter> filters_;
std::vector<DeviceInfo> devices_;
Observer* observer_;
ScopedObserver<device::UsbService, device::UsbService::Observer>
usb_service_observer_;
};
class Delegate {
......
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