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
)
29 base::string16 manufacturer_string
;
30 if (device
->GetManufacturer(&manufacturer_string
)) {
31 original_manufacturer_string
= manufacturer_string
;
33 const char* vendor_name
=
34 device::UsbIds::GetVendorName(device
->vendor_id());
36 manufacturer_string
= base::UTF8ToUTF16(vendor_name
);
38 base::string16 vendor_id
=
39 base::ASCIIToUTF16(base::StringPrintf("0x%04x", device
->vendor_id()));
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
;
49 const char* product_name
= device::UsbIds::GetProductName(
50 device
->vendor_id(), device
->product_id());
52 product_string
= base::UTF8ToUTF16(product_name
);
54 base::string16 product_id
= base::ASCIIToUTF16(
55 base::StringPrintf("0x%04x", device
->product_id()));
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),
77 usb_service_observer_(this) {
80 void DevicePermissionsPrompt::Prompt::SetObserver(Observer
* 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
) {
127 DevicePermissionsPrompt::Prompt::~Prompt() {
130 void DevicePermissionsPrompt::Prompt::DoDeviceQuery() {
131 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
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_
))) {
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
,
156 &DevicePermissionsPrompt::Prompt::SetDevices
, this, device_info
));
159 void DevicePermissionsPrompt::Prompt::SetDevices(
160 const std::vector
<DeviceInfo
>& devices
) {
163 observer_
->OnDevicesChanged();
167 void DevicePermissionsPrompt::Prompt::AddDevice(const DeviceInfo
& device
) {
168 devices_
.push_back(device
);
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
) {
181 removed_entry
= true;
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_
))) {
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(
219 const Extension
* extension
,
220 content::BrowserContext
* context
,
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
;
233 } // namespace extensions