Revert of Fix missing GN dependencies. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / extensions / browser / api / device_permissions_prompt.cc
blobb2df4726b2591a0771d6c0f4e2c2e4efb1e0dc31
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/bind.h"
8 #include "base/scoped_observer.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "device/core/device_client.h"
12 #include "device/hid/hid_device_filter.h"
13 #include "device/hid/hid_device_info.h"
14 #include "device/hid/hid_service.h"
15 #include "device/usb/usb_device.h"
16 #include "device/usb/usb_device_filter.h"
17 #include "device/usb/usb_ids.h"
18 #include "device/usb/usb_service.h"
19 #include "extensions/browser/api/device_permissions_manager.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/strings/grit/extensions_strings.h"
22 #include "ui/base/l10n/l10n_util.h"
24 #if defined(OS_CHROMEOS)
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/permission_broker_client.h"
27 #endif // defined(OS_CHROMEOS)
29 using device::HidDeviceFilter;
30 using device::HidService;
31 using device::UsbDevice;
32 using device::UsbDeviceFilter;
33 using device::UsbService;
35 namespace extensions {
37 namespace {
39 class UsbDeviceInfo : public DevicePermissionsPrompt::Prompt::DeviceInfo {
40 public:
41 UsbDeviceInfo(scoped_refptr<UsbDevice> device) : device_(device) {
42 name_ = DevicePermissionsManager::GetPermissionMessage(
43 device->vendor_id(), device->product_id(),
44 device->manufacturer_string(), device->product_string(),
45 base::string16(), // Serial number is displayed separately.
46 true);
47 serial_number_ = device->serial_number();
50 ~UsbDeviceInfo() override {}
52 const scoped_refptr<UsbDevice>& device() const { return device_; }
54 private:
55 // TODO(reillyg): Convert this to a weak reference when UsbDevice has a
56 // connected flag.
57 scoped_refptr<UsbDevice> device_;
60 class UsbDevicePermissionsPrompt : public DevicePermissionsPrompt::Prompt,
61 public device::UsbService::Observer {
62 public:
63 UsbDevicePermissionsPrompt(
64 const Extension* extension,
65 content::BrowserContext* context,
66 bool multiple,
67 const std::vector<UsbDeviceFilter>& filters,
68 const DevicePermissionsPrompt::UsbDevicesCallback& callback)
69 : Prompt(extension, context, multiple),
70 filters_(filters),
71 callback_(callback),
72 service_observer_(this) {}
74 private:
75 ~UsbDevicePermissionsPrompt() override {}
77 // DevicePermissionsPrompt::Prompt implementation:
78 void SetObserver(
79 DevicePermissionsPrompt::Prompt::Observer* observer) override {
80 DevicePermissionsPrompt::Prompt::SetObserver(observer);
82 if (observer) {
83 UsbService* service = device::DeviceClient::Get()->GetUsbService();
84 if (service && !service_observer_.IsObserving(service)) {
85 service->GetDevices(
86 base::Bind(&UsbDevicePermissionsPrompt::OnDevicesEnumerated, this));
87 service_observer_.Add(service);
92 base::string16 GetHeading() const override {
93 return l10n_util::GetPluralStringFUTF16(
94 IDS_HID_DEVICE_PERMISSIONS_PROMPT_TITLE, devices_.size());
97 void Dismissed() override {
98 DevicePermissionsManager* permissions_manager =
99 DevicePermissionsManager::Get(browser_context());
100 std::vector<scoped_refptr<UsbDevice>> devices;
101 for (const DeviceInfo* device : devices_) {
102 if (device->granted()) {
103 const UsbDeviceInfo* usb_device =
104 static_cast<const UsbDeviceInfo*>(device);
105 devices.push_back(usb_device->device());
106 if (permissions_manager) {
107 permissions_manager->AllowUsbDevice(extension()->id(),
108 usb_device->device());
112 DCHECK(multiple() || devices.size() <= 1);
113 callback_.Run(devices);
114 callback_.Reset();
117 // device::UsbService::Observer implementation:
118 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override {
119 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
120 return;
123 scoped_ptr<DeviceInfo> device_info(new UsbDeviceInfo(device));
124 device->CheckUsbAccess(
125 base::Bind(&UsbDevicePermissionsPrompt::AddCheckedDevice, this,
126 base::Passed(&device_info)));
129 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override {
130 for (auto it = devices_.begin(); it != devices_.end(); ++it) {
131 const UsbDeviceInfo* entry = static_cast<const UsbDeviceInfo*>(*it);
132 if (entry->device() == device) {
133 devices_.erase(it);
134 if (observer()) {
135 observer()->OnDevicesChanged();
137 return;
142 void OnDevicesEnumerated(
143 const std::vector<scoped_refptr<UsbDevice>>& devices) {
144 for (const auto& device : devices) {
145 OnDeviceAdded(device);
149 std::vector<UsbDeviceFilter> filters_;
150 DevicePermissionsPrompt::UsbDevicesCallback callback_;
151 ScopedObserver<UsbService, UsbService::Observer> service_observer_;
154 class HidDeviceInfo : public DevicePermissionsPrompt::Prompt::DeviceInfo {
155 public:
156 HidDeviceInfo(scoped_refptr<device::HidDeviceInfo> device) : device_(device) {
157 name_ = DevicePermissionsManager::GetPermissionMessage(
158 device->vendor_id(), device->product_id(),
159 base::string16(), // HID devices include manufacturer in product name.
160 base::UTF8ToUTF16(device->product_name()),
161 base::string16(), // Serial number is displayed separately.
162 false);
163 serial_number_ = base::UTF8ToUTF16(device->serial_number());
166 ~HidDeviceInfo() override {}
168 const scoped_refptr<device::HidDeviceInfo>& device() const { return device_; }
170 private:
171 scoped_refptr<device::HidDeviceInfo> device_;
174 class HidDevicePermissionsPrompt : public DevicePermissionsPrompt::Prompt,
175 public device::HidService::Observer {
176 public:
177 HidDevicePermissionsPrompt(
178 const Extension* extension,
179 content::BrowserContext* context,
180 bool multiple,
181 const std::vector<HidDeviceFilter>& filters,
182 const DevicePermissionsPrompt::HidDevicesCallback& callback)
183 : Prompt(extension, context, multiple),
184 filters_(filters),
185 callback_(callback),
186 service_observer_(this) {}
188 private:
189 ~HidDevicePermissionsPrompt() override {}
191 // DevicePermissionsPrompt::Prompt implementation:
192 void SetObserver(
193 DevicePermissionsPrompt::Prompt::Observer* observer) override {
194 DevicePermissionsPrompt::Prompt::SetObserver(observer);
196 if (observer) {
197 HidService* service = device::DeviceClient::Get()->GetHidService();
198 if (service && !service_observer_.IsObserving(service)) {
199 service->GetDevices(
200 base::Bind(&HidDevicePermissionsPrompt::OnDevicesEnumerated, this));
201 service_observer_.Add(service);
206 base::string16 GetHeading() const override {
207 return l10n_util::GetPluralStringFUTF16(
208 IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE, devices_.size());
211 void Dismissed() override {
212 DevicePermissionsManager* permissions_manager =
213 DevicePermissionsManager::Get(browser_context());
214 std::vector<scoped_refptr<device::HidDeviceInfo>> devices;
215 for (const DeviceInfo* device : devices_) {
216 if (device->granted()) {
217 const HidDeviceInfo* hid_device =
218 static_cast<const HidDeviceInfo*>(device);
219 devices.push_back(hid_device->device());
220 if (permissions_manager) {
221 permissions_manager->AllowHidDevice(extension()->id(),
222 hid_device->device());
226 DCHECK(multiple() || devices.size() <= 1);
227 callback_.Run(devices);
228 callback_.Reset();
231 // device::HidService::Observer implementation:
232 void OnDeviceAdded(scoped_refptr<device::HidDeviceInfo> device) override {
233 if (HasUnprotectedCollections(device) &&
234 (filters_.empty() || HidDeviceFilter::MatchesAny(device, filters_))) {
235 scoped_ptr<DeviceInfo> device_info(new HidDeviceInfo(device));
236 #if defined(OS_CHROMEOS)
237 chromeos::PermissionBrokerClient* client =
238 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
239 DCHECK(client) << "Could not get permission broker client.";
240 client->CheckPathAccess(
241 device->device_id(),
242 base::Bind(&HidDevicePermissionsPrompt::AddCheckedDevice, this,
243 base::Passed(&device_info)));
244 #else
245 AddCheckedDevice(device_info.Pass(), true);
246 #endif // defined(OS_CHROMEOS)
250 void OnDeviceRemoved(scoped_refptr<device::HidDeviceInfo> device) override {
251 for (auto it = devices_.begin(); it != devices_.end(); ++it) {
252 const HidDeviceInfo* entry = static_cast<const HidDeviceInfo*>(*it);
253 if (entry->device() == device) {
254 devices_.erase(it);
255 if (observer()) {
256 observer()->OnDevicesChanged();
258 return;
263 void OnDevicesEnumerated(
264 const std::vector<scoped_refptr<device::HidDeviceInfo>>& devices) {
265 for (const auto& device : devices) {
266 OnDeviceAdded(device);
270 bool HasUnprotectedCollections(scoped_refptr<device::HidDeviceInfo> device) {
271 for (const auto& collection : device->collections()) {
272 if (!collection.usage.IsProtected()) {
273 return true;
276 return false;
279 std::vector<HidDeviceFilter> filters_;
280 DevicePermissionsPrompt::HidDevicesCallback callback_;
281 ScopedObserver<HidService, HidService::Observer> service_observer_;
284 } // namespace
286 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo() {
289 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() {
292 DevicePermissionsPrompt::Prompt::Observer::~Observer() {
295 DevicePermissionsPrompt::Prompt::Prompt(const Extension* extension,
296 content::BrowserContext* context,
297 bool multiple)
298 : extension_(extension), browser_context_(context), multiple_(multiple) {
301 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) {
302 observer_ = observer;
305 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const {
306 // TODO(jungshik): Consider using the ICU syntax once bug 481734 is fixed.
307 return l10n_util::GetStringFUTF16(multiple_
308 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE
309 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE,
310 base::UTF8ToUTF16(extension_->name()));
313 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName(
314 size_t index) const {
315 DCHECK_LT(index, devices_.size());
316 return devices_[index]->name();
319 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber(
320 size_t index) const {
321 DCHECK_LT(index, devices_.size());
322 return devices_[index]->serial_number();
325 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) {
326 DCHECK_LT(index, devices_.size());
327 devices_[index]->set_granted();
330 DevicePermissionsPrompt::Prompt::~Prompt() {
333 void DevicePermissionsPrompt::Prompt::AddCheckedDevice(
334 scoped_ptr<DeviceInfo> device,
335 bool allowed) {
336 if (allowed) {
337 devices_.push_back(device.release());
338 if (observer_) {
339 observer_->OnDevicesChanged();
344 DevicePermissionsPrompt::DevicePermissionsPrompt(
345 content::WebContents* web_contents)
346 : web_contents_(web_contents) {
349 DevicePermissionsPrompt::~DevicePermissionsPrompt() {
352 void DevicePermissionsPrompt::AskForUsbDevices(
353 const Extension* extension,
354 content::BrowserContext* context,
355 bool multiple,
356 const std::vector<UsbDeviceFilter>& filters,
357 const UsbDevicesCallback& callback) {
358 prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple,
359 filters, callback);
360 ShowDialog();
363 void DevicePermissionsPrompt::AskForHidDevices(
364 const Extension* extension,
365 content::BrowserContext* context,
366 bool multiple,
367 const std::vector<HidDeviceFilter>& filters,
368 const HidDevicesCallback& callback) {
369 prompt_ = new HidDevicePermissionsPrompt(extension, context, multiple,
370 filters, callback);
371 ShowDialog();
374 } // namespace extensions