Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / extensions / browser / api / device_permissions_prompt.cc
blobafb895cd642490596df8e226c8f8c4ef25c512a2
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/device_permissions_prompt.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "device/core/device_client.h"
11 #include "device/usb/usb_device.h"
12 #include "device/usb/usb_device_filter.h"
13 #include "device/usb/usb_ids.h"
14 #include "device/usb/usb_service.h"
15 #include "extensions/browser/api/device_permissions_manager.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/strings/grit/extensions_strings.h"
18 #include "ui/base/l10n/l10n_util.h"
20 using device::UsbDevice;
21 using device::UsbDeviceFilter;
22 using device::UsbService;
24 namespace extensions {
26 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo(
27 scoped_refptr<UsbDevice> device)
28 : device(device) {
29 base::string16 manufacturer_string;
30 if (device->GetManufacturer(&manufacturer_string)) {
31 original_manufacturer_string = manufacturer_string;
32 } else {
33 const char* vendor_name =
34 device::UsbIds::GetVendorName(device->vendor_id());
35 if (vendor_name) {
36 manufacturer_string = base::UTF8ToUTF16(vendor_name);
37 } else {
38 base::string16 vendor_id =
39 base::ASCIIToUTF16(base::StringPrintf("0x%04x", device->vendor_id()));
40 manufacturer_string =
41 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id);
45 base::string16 product_string;
46 if (device->GetProduct(&product_string)) {
47 original_product_string = product_string;
48 } else {
49 const char* product_name = device::UsbIds::GetProductName(
50 device->vendor_id(), device->product_id());
51 if (product_name) {
52 product_string = base::UTF8ToUTF16(product_name);
53 } else {
54 base::string16 product_id = base::ASCIIToUTF16(
55 base::StringPrintf("0x%04x", device->product_id()));
56 product_string =
57 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id);
61 if (!device->GetSerialNumber(&serial_number)) {
62 serial_number.clear();
65 name = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME,
66 product_string, manufacturer_string);
69 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() {
72 DevicePermissionsPrompt::Prompt::Prompt()
73 : extension_(nullptr),
74 browser_context_(nullptr),
75 multiple_(false),
76 observer_(nullptr),
77 usb_service_observer_(this) {
80 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) {
81 observer_ = observer;
83 if (observer_) {
84 content::BrowserThread::PostTask(
85 content::BrowserThread::FILE, FROM_HERE,
86 base::Bind(&DevicePermissionsPrompt::Prompt::DoDeviceQuery, this));
90 base::string16 DevicePermissionsPrompt::Prompt::GetHeading() const {
91 return l10n_util::GetStringUTF16(
92 multiple_ ? IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE
93 : IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE);
96 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const {
97 return l10n_util::GetStringFUTF16(multiple_
98 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE
99 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE,
100 base::UTF8ToUTF16(extension_->name()));
103 scoped_refptr<UsbDevice> DevicePermissionsPrompt::Prompt::GetDevice(
104 size_t index) const {
105 DCHECK_LT(index, devices_.size());
106 return devices_[index].device;
109 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(
110 size_t index) const {
111 DCHECK_LT(index, devices_.size());
112 DevicePermissionsManager* permissions_manager =
113 DevicePermissionsManager::Get(browser_context_);
114 if (permissions_manager) {
115 const DeviceInfo& device = devices_[index];
116 permissions_manager->AllowUsbDevice(
117 extension_->id(), device.device, device.original_product_string,
118 device.original_manufacturer_string, device.serial_number);
122 void DevicePermissionsPrompt::Prompt::set_filters(
123 const std::vector<UsbDeviceFilter>& filters) {
124 filters_ = filters;
127 DevicePermissionsPrompt::Prompt::~Prompt() {
130 void DevicePermissionsPrompt::Prompt::DoDeviceQuery() {
131 UsbService* service = device::DeviceClient::Get()->GetUsbService();
132 if (!service) {
133 return;
136 std::vector<scoped_refptr<UsbDevice>> devices;
137 service->GetDevices(&devices);
139 std::vector<DeviceInfo> device_info;
140 for (const auto& device : devices) {
141 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
142 continue;
145 device_info.push_back(DeviceInfo(device));
148 if (!usb_service_observer_.IsObserving(service)) {
149 usb_service_observer_.Add(service);
152 content::BrowserThread::PostTask(
153 content::BrowserThread::UI,
154 FROM_HERE,
155 base::Bind(
156 &DevicePermissionsPrompt::Prompt::SetDevices, this, device_info));
159 void DevicePermissionsPrompt::Prompt::SetDevices(
160 const std::vector<DeviceInfo>& devices) {
161 devices_ = devices;
162 if (observer_) {
163 observer_->OnDevicesChanged();
167 void DevicePermissionsPrompt::Prompt::AddDevice(const DeviceInfo& device) {
168 devices_.push_back(device);
169 if (observer_) {
170 observer_->OnDevicesChanged();
174 void DevicePermissionsPrompt::Prompt::RemoveDevice(
175 scoped_refptr<UsbDevice> device) {
176 bool removed_entry = false;
177 for (std::vector<DeviceInfo>::iterator it = devices_.begin();
178 it != devices_.end(); ++it) {
179 if (it->device == device) {
180 devices_.erase(it);
181 removed_entry = true;
182 break;
185 if (observer_ && removed_entry) {
186 observer_->OnDevicesChanged();
190 void DevicePermissionsPrompt::Prompt::OnDeviceAdded(
191 scoped_refptr<UsbDevice> device) {
192 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
193 return;
196 content::BrowserThread::PostTask(
197 content::BrowserThread::UI, FROM_HERE,
198 base::Bind(&DevicePermissionsPrompt::Prompt::AddDevice, this,
199 DeviceInfo(device)));
202 void DevicePermissionsPrompt::Prompt::OnDeviceRemoved(
203 scoped_refptr<UsbDevice> device) {
204 content::BrowserThread::PostTask(
205 content::BrowserThread::UI, FROM_HERE,
206 base::Bind(&DevicePermissionsPrompt::Prompt::RemoveDevice, this, device));
209 DevicePermissionsPrompt::DevicePermissionsPrompt(
210 content::WebContents* web_contents)
211 : web_contents_(web_contents), delegate_(nullptr) {
214 DevicePermissionsPrompt::~DevicePermissionsPrompt() {
217 void DevicePermissionsPrompt::AskForUsbDevices(
218 Delegate* delegate,
219 const Extension* extension,
220 content::BrowserContext* context,
221 bool multiple,
222 const std::vector<UsbDeviceFilter>& filters) {
223 prompt_ = new Prompt();
224 prompt_->set_extension(extension);
225 prompt_->set_browser_context(context);
226 prompt_->set_multiple(multiple);
227 prompt_->set_filters(filters);
228 delegate_ = delegate;
230 ShowDialog();
233 } // namespace extensions