Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: extensions/browser/api/device_permissions_prompt.cc

Issue 1098823003: Separate USB device permissions prompt logic into subclasses. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address jyasskin@'s comments. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/api/device_permissions_prompt.h" 5 #include "extensions/browser/api/device_permissions_prompt.h"
6 6
7 #include "base/barrier_closure.h" 7 #include "base/scoped_observer.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "device/core/device_client.h" 10 #include "device/core/device_client.h"
12 #include "device/usb/usb_device.h" 11 #include "device/usb/usb_device.h"
13 #include "device/usb/usb_device_filter.h" 12 #include "device/usb/usb_device_filter.h"
14 #include "device/usb/usb_ids.h" 13 #include "device/usb/usb_ids.h"
15 #include "device/usb/usb_service.h" 14 #include "device/usb/usb_service.h"
16 #include "extensions/browser/api/device_permissions_manager.h" 15 #include "extensions/browser/api/device_permissions_manager.h"
17 #include "extensions/common/extension.h" 16 #include "extensions/common/extension.h"
18 #include "extensions/strings/grit/extensions_strings.h" 17 #include "extensions/strings/grit/extensions_strings.h"
19 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
20 19
21 using content::BrowserThread;
22 using device::UsbDevice; 20 using device::UsbDevice;
23 using device::UsbDeviceFilter; 21 using device::UsbDeviceFilter;
24 using device::UsbService; 22 using device::UsbService;
25 23
26 namespace extensions { 24 namespace extensions {
27 25
28 DevicePermissionsPrompt::Delegate::~Delegate() { 26 namespace {
29 }
30 27
31 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo( 28 class UsbDeviceInfo : public DevicePermissionsPrompt::Prompt::DeviceInfo {
32 scoped_refptr<UsbDevice> device) 29 public:
33 : device(device) { 30 UsbDeviceInfo(scoped_refptr<UsbDevice> device) : device_(device) {
34 base::string16 manufacturer_string = device->manufacturer_string(); 31 base::string16 manufacturer_string = device->manufacturer_string();
35 if (manufacturer_string.empty()) { 32 if (manufacturer_string.empty()) {
36 const char* vendor_name = 33 const char* vendor_name =
37 device::UsbIds::GetVendorName(device->vendor_id()); 34 device::UsbIds::GetVendorName(device->vendor_id());
38 if (vendor_name) { 35 if (vendor_name) {
39 manufacturer_string = base::UTF8ToUTF16(vendor_name); 36 manufacturer_string = base::UTF8ToUTF16(vendor_name);
40 } else { 37 } else {
41 base::string16 vendor_id = 38 base::string16 vendor_id = base::ASCIIToUTF16(
42 base::ASCIIToUTF16(base::StringPrintf("0x%04x", device->vendor_id())); 39 base::StringPrintf("0x%04x", device->vendor_id()));
43 manufacturer_string = 40 manufacturer_string =
44 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id); 41 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id);
42 }
43 }
44
45 base::string16 product_string = device->product_string();
46 if (product_string.empty()) {
47 const char* product_name = device::UsbIds::GetProductName(
48 device->vendor_id(), device->product_id());
49 if (product_name) {
50 product_string = base::UTF8ToUTF16(product_name);
51 } else {
52 base::string16 product_id = base::ASCIIToUTF16(
53 base::StringPrintf("0x%04x", device->product_id()));
54 product_string =
55 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id);
56 }
57 }
58
59 name_ = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME,
60 product_string, manufacturer_string);
61 serial_number_ = device->serial_number();
62 }
63
64 ~UsbDeviceInfo() override {}
65
66 const scoped_refptr<UsbDevice>& device() const { return device_; }
67
68 private:
69 // TODO(reillyg): Convert this to a weak reference when UsbDevice has a
70 // connected flag.
71 scoped_refptr<UsbDevice> device_;
72 };
73
74 class UsbDevicePermissionsPrompt : public DevicePermissionsPrompt::Prompt,
75 public device::UsbService::Observer {
76 public:
77 UsbDevicePermissionsPrompt(
78 const Extension* extension,
79 content::BrowserContext* context,
80 bool multiple,
81 const std::vector<device::UsbDeviceFilter>& filters,
82 const DevicePermissionsPrompt::UsbDevicesCallback& callback)
83 : Prompt(extension, context, multiple),
84 filters_(filters),
85 callback_(callback),
86 service_observer_(this) {}
87
88 private:
89 ~UsbDevicePermissionsPrompt() override {}
90
91 // DevicePermissionsPrompt::Prompt implementation:
92 void SetObserver(
93 DevicePermissionsPrompt::Prompt::Observer* observer) override {
94 DevicePermissionsPrompt::Prompt::SetObserver(observer);
95
96 if (observer) {
97 UsbService* service = device::DeviceClient::Get()->GetUsbService();
98 if (service && !service_observer_.IsObserving(service)) {
99 service->GetDevices(
100 base::Bind(&UsbDevicePermissionsPrompt::OnDevicesEnumerated, this));
101 service_observer_.Add(service);
102 }
45 } 103 }
46 } 104 }
47 105
48 base::string16 product_string = device->product_string(); 106 base::string16 GetHeading() const override {
49 if (product_string.empty()) { 107 return l10n_util::GetStringUTF16(
50 const char* product_name = device::UsbIds::GetProductName( 108 multiple() ? IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE
51 device->vendor_id(), device->product_id()); 109 : IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE);
52 if (product_name) { 110 }
53 product_string = base::UTF8ToUTF16(product_name); 111
54 } else { 112 void Dismissed() override {
55 base::string16 product_id = base::ASCIIToUTF16( 113 DevicePermissionsManager* permissions_manager =
56 base::StringPrintf("0x%04x", device->product_id())); 114 DevicePermissionsManager::Get(browser_context());
57 product_string = 115 std::vector<scoped_refptr<UsbDevice>> devices;
58 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); 116 for (const DeviceInfo* device : devices_) {
117 if (device->granted()) {
118 const UsbDeviceInfo* usb_device =
119 static_cast<const UsbDeviceInfo*>(device);
120 devices.push_back(usb_device->device());
121 if (permissions_manager) {
122 permissions_manager->AllowUsbDevice(extension()->id(),
123 usb_device->device());
124 }
125 }
126 }
127 DCHECK(multiple() || devices.size() <= 1);
128 callback_.Run(devices);
129 callback_.Reset();
130 }
131
132 // device::UsbService::Observer implementation:
133 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override {
134 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
135 return;
136 }
137
138 device->CheckUsbAccess(base::Bind(
139 &UsbDevicePermissionsPrompt::AddCheckedDevice, this, device));
140 }
141
142 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override {
143 for (auto it = devices_.begin(); it != devices_.end(); ++it) {
144 const UsbDeviceInfo* entry = static_cast<const UsbDeviceInfo*>(*it);
145 if (entry->device() == device) {
146 devices_.erase(it);
147 if (observer()) {
148 observer()->OnDevicesChanged();
149 }
150 return;
151 }
59 } 152 }
60 } 153 }
61 154
62 name = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, 155 void OnDevicesEnumerated(
63 product_string, manufacturer_string); 156 const std::vector<scoped_refptr<UsbDevice>>& devices) {
157 for (const auto& device : devices) {
158 OnDeviceAdded(device);
159 }
160 }
161
162 void AddCheckedDevice(scoped_refptr<UsbDevice> device, bool allowed) {
163 if (allowed) {
164 // TODO(reillyg): This method could be called after OnDeviceRemoved. We
165 // should check that the device is still connected.
166 devices_.push_back(new UsbDeviceInfo(device));
167 if (observer()) {
168 observer()->OnDevicesChanged();
169 }
170 }
171 }
172
173 std::vector<UsbDeviceFilter> filters_;
174 DevicePermissionsPrompt::UsbDevicesCallback callback_;
175 ScopedObserver<UsbService, UsbService::Observer> service_observer_;
176 };
177
178 } // namespace
179
180 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo() {
64 } 181 }
65 182
66 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() { 183 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() {
67 } 184 }
68 185
69 DevicePermissionsPrompt::Prompt::Observer::~Observer() { 186 DevicePermissionsPrompt::Prompt::Observer::~Observer() {
70 } 187 }
71 188
72 DevicePermissionsPrompt::Prompt::Prompt(Delegate* delegate, 189 DevicePermissionsPrompt::Prompt::Prompt(const Extension* extension,
73 const Extension* extension, 190 content::BrowserContext* context,
74 content::BrowserContext* context) 191 bool multiple)
75 : extension_(extension), 192 : extension_(extension), browser_context_(context), multiple_(multiple) {
76 browser_context_(context),
77 delegate_(delegate),
78 usb_service_observer_(this) {
79 } 193 }
80 194
81 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) { 195 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) {
82 observer_ = observer; 196 observer_ = observer;
83
84 if (observer_) {
85 UsbService* service = device::DeviceClient::Get()->GetUsbService();
86 if (service && !usb_service_observer_.IsObserving(service)) {
87 service->GetDevices(base::Bind(
88 &DevicePermissionsPrompt::Prompt::OnDevicesEnumerated, this));
89 usb_service_observer_.Add(service);
90 }
91 }
92 }
93
94 base::string16 DevicePermissionsPrompt::Prompt::GetHeading() const {
95 return l10n_util::GetStringUTF16(
96 multiple_ ? IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE
97 : IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE);
98 } 197 }
99 198
100 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const { 199 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const {
101 return l10n_util::GetStringFUTF16(multiple_ 200 return l10n_util::GetStringFUTF16(multiple_
102 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE 201 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE
103 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE, 202 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE,
104 base::UTF8ToUTF16(extension_->name())); 203 base::UTF8ToUTF16(extension_->name()));
105 } 204 }
106 205
107 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName( 206 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName(
108 size_t index) const { 207 size_t index) const {
109 DCHECK_LT(index, devices_.size()); 208 DCHECK_LT(index, devices_.size());
110 return devices_[index].name; 209 return devices_[index]->name();
111 } 210 }
112 211
113 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber( 212 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber(
114 size_t index) const { 213 size_t index) const {
115 DCHECK_LT(index, devices_.size()); 214 DCHECK_LT(index, devices_.size());
116 return devices_[index].device->serial_number(); 215 return devices_[index]->serial_number();
117 } 216 }
118 217
119 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) { 218 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) {
120 DCHECK_LT(index, devices_.size()); 219 DCHECK_LT(index, devices_.size());
121 devices_[index].granted = true; 220 devices_[index]->set_granted();
122 }
123
124 void DevicePermissionsPrompt::Prompt::Dismissed() {
125 DevicePermissionsManager* permissions_manager =
126 DevicePermissionsManager::Get(browser_context_);
127 std::vector<scoped_refptr<UsbDevice>> devices;
128 for (const DeviceInfo& device : devices_) {
129 if (device.granted) {
130 devices.push_back(device.device);
131 if (permissions_manager) {
132 permissions_manager->AllowUsbDevice(extension_->id(), device.device);
133 }
134 }
135 }
136 delegate_->OnUsbDevicesChosen(devices);
137 }
138
139 void DevicePermissionsPrompt::Prompt::set_filters(
140 const std::vector<UsbDeviceFilter>& filters) {
141 filters_ = filters;
142 } 221 }
143 222
144 DevicePermissionsPrompt::Prompt::~Prompt() { 223 DevicePermissionsPrompt::Prompt::~Prompt() {
145 } 224 }
146 225
147 void DevicePermissionsPrompt::Prompt::OnDeviceAdded(
148 scoped_refptr<UsbDevice> device) {
149 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
150 return;
151 }
152
153 device->CheckUsbAccess(base::Bind(
154 &DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice, this, device));
155 }
156
157 void DevicePermissionsPrompt::Prompt::OnDeviceRemoved(
158 scoped_refptr<UsbDevice> device) {
159 bool removed_entry = false;
160 for (std::vector<DeviceInfo>::iterator it = devices_.begin();
161 it != devices_.end(); ++it) {
162 if (it->device == device) {
163 devices_.erase(it);
164 removed_entry = true;
165 break;
166 }
167 }
168 if (observer_ && removed_entry) {
169 observer_->OnDevicesChanged();
170 }
171 }
172
173 void DevicePermissionsPrompt::Prompt::OnDevicesEnumerated(
174 const std::vector<scoped_refptr<UsbDevice>>& devices) {
175 for (const auto& device : devices) {
176 if (filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) {
177 device->CheckUsbAccess(base::Bind(
178 &DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice, this, device));
179 }
180 }
181 }
182
183 void DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice(
184 scoped_refptr<UsbDevice> device,
185 bool allowed) {
186 if (allowed) {
187 devices_.push_back(DeviceInfo(device));
188 if (observer_) {
189 observer_->OnDevicesChanged();
190 }
191 }
192 }
193
194 DevicePermissionsPrompt::DevicePermissionsPrompt( 226 DevicePermissionsPrompt::DevicePermissionsPrompt(
195 content::WebContents* web_contents) 227 content::WebContents* web_contents)
196 : web_contents_(web_contents) { 228 : web_contents_(web_contents) {
197 } 229 }
198 230
199 DevicePermissionsPrompt::~DevicePermissionsPrompt() { 231 DevicePermissionsPrompt::~DevicePermissionsPrompt() {
200 } 232 }
201 233
202 void DevicePermissionsPrompt::AskForUsbDevices( 234 void DevicePermissionsPrompt::AskForUsbDevices(
203 Delegate* delegate,
204 const Extension* extension, 235 const Extension* extension,
205 content::BrowserContext* context, 236 content::BrowserContext* context,
206 bool multiple, 237 bool multiple,
207 const std::vector<UsbDeviceFilter>& filters) { 238 const std::vector<UsbDeviceFilter>& filters,
208 prompt_ = new Prompt(delegate, extension, context); 239 const UsbDevicesCallback& callback) {
209 prompt_->set_multiple(multiple); 240 prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple,
210 prompt_->set_filters(filters); 241 filters, callback);
211
212 ShowDialog(); 242 ShowDialog();
213 } 243 }
214 244
215 } // namespace extensions 245 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/device_permissions_prompt.h ('k') | extensions/browser/api/usb/usb_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698