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

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: 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/barrier_closure.h"
8 #include "base/scoped_observer.h"
8 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "device/core/device_client.h" 11 #include "device/core/device_client.h"
12 #include "device/usb/usb_device.h" 12 #include "device/usb/usb_device.h"
13 #include "device/usb/usb_device_filter.h" 13 #include "device/usb/usb_device_filter.h"
14 #include "device/usb/usb_ids.h" 14 #include "device/usb/usb_ids.h"
15 #include "device/usb/usb_service.h" 15 #include "device/usb/usb_service.h"
16 #include "extensions/browser/api/device_permissions_manager.h" 16 #include "extensions/browser/api/device_permissions_manager.h"
17 #include "extensions/common/extension.h" 17 #include "extensions/common/extension.h"
18 #include "extensions/strings/grit/extensions_strings.h" 18 #include "extensions/strings/grit/extensions_strings.h"
19 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
20 20
21 using content::BrowserThread;
22 using device::UsbDevice; 21 using device::UsbDevice;
23 using device::UsbDeviceFilter; 22 using device::UsbDeviceFilter;
24 using device::UsbService; 23 using device::UsbService;
25 24
26 namespace extensions { 25 namespace extensions {
27 26
28 DevicePermissionsPrompt::Delegate::~Delegate() { 27 namespace {
29 }
30 28
31 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo( 29 struct UsbDeviceInfo : public DevicePermissionsPrompt::Prompt::DeviceInfo {
32 scoped_refptr<UsbDevice> device) 30 UsbDeviceInfo(scoped_refptr<UsbDevice> device) : device(device) {
33 : device(device) { 31 base::string16 manufacturer_string = device->manufacturer_string();
34 base::string16 manufacturer_string = device->manufacturer_string(); 32 if (manufacturer_string.empty()) {
35 if (manufacturer_string.empty()) { 33 const char* vendor_name =
36 const char* vendor_name = 34 device::UsbIds::GetVendorName(device->vendor_id());
37 device::UsbIds::GetVendorName(device->vendor_id()); 35 if (vendor_name) {
38 if (vendor_name) { 36 manufacturer_string = base::UTF8ToUTF16(vendor_name);
39 manufacturer_string = base::UTF8ToUTF16(vendor_name); 37 } else {
40 } else { 38 base::string16 vendor_id = base::ASCIIToUTF16(
41 base::string16 vendor_id = 39 base::StringPrintf("0x%04x", device->vendor_id()));
42 base::ASCIIToUTF16(base::StringPrintf("0x%04x", device->vendor_id())); 40 manufacturer_string =
43 manufacturer_string = 41 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id);
44 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 scoped_refptr<UsbDevice> device;
Jeffrey Yasskin 2015/04/23 20:40:07 Does this need to own a reference? It looks like t
Reilly Grant (use Gerrit) 2015/04/23 23:02:47 Added comments about why this needs to be a strong
67 };
68
69 class UsbDevicePermissionsPrompt : public DevicePermissionsPrompt::Prompt,
70 public device::UsbService::Observer {
71 public:
72 UsbDevicePermissionsPrompt(
73 const Extension* extension,
74 content::BrowserContext* context,
75 bool multiple,
76 const std::vector<device::UsbDeviceFilter>& filters,
77 const DevicePermissionsPrompt::UsbDevicesCallback& callback)
78 : Prompt(extension, context, multiple),
79 filters_(filters),
80 callback_(callback),
81 service_observer_(this) {}
82
83 private:
84 ~UsbDevicePermissionsPrompt() override {}
85
86 // DevicePermissionsPrompt::Prompt implementation:
87 void SetObserver(
88 DevicePermissionsPrompt::Prompt::Observer* observer) override {
89 DevicePermissionsPrompt::Prompt::SetObserver(observer);
90
91 if (observer) {
92 UsbService* service = device::DeviceClient::Get()->GetUsbService();
93 if (service && !service_observer_.IsObserving(service)) {
94 service->GetDevices(
95 base::Bind(&UsbDevicePermissionsPrompt::OnDevicesEnumerated, this));
96 service_observer_.Add(service);
97 }
45 } 98 }
46 } 99 }
47 100
48 base::string16 product_string = device->product_string(); 101 base::string16 GetHeading() const override {
49 if (product_string.empty()) { 102 return l10n_util::GetStringUTF16(
50 const char* product_name = device::UsbIds::GetProductName( 103 multiple() ? IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE
51 device->vendor_id(), device->product_id()); 104 : IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE);
52 if (product_name) { 105 }
53 product_string = base::UTF8ToUTF16(product_name); 106
54 } else { 107 void Dismissed() override {
55 base::string16 product_id = base::ASCIIToUTF16( 108 DevicePermissionsManager* permissions_manager =
56 base::StringPrintf("0x%04x", device->product_id())); 109 DevicePermissionsManager::Get(browser_context());
57 product_string = 110 std::vector<scoped_refptr<UsbDevice>> devices;
58 l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); 111 for (const DeviceInfo* device : devices_) {
112 if (device->granted) {
113 const UsbDeviceInfo* usb_device =
114 static_cast<const UsbDeviceInfo*>(device);
115 devices.push_back(usb_device->device);
116 if (permissions_manager) {
117 permissions_manager->AllowUsbDevice(extension()->id(),
118 usb_device->device);
119 }
120 }
121 }
122 DCHECK(multiple() || devices.size() <= 1);
123 callback_.Run(devices);
124 callback_.Reset();
125 }
126
127 // device::UsbService::Observer implementation:
128 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override {
129 if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) {
130 return;
131 }
132
133 device->CheckUsbAccess(base::Bind(
134 &UsbDevicePermissionsPrompt::AddCheckedUsbDevice, this, device));
135 }
136
137 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override {
138 for (auto it = devices_.begin(); it != devices_.end(); ++it) {
139 const UsbDeviceInfo* entry = static_cast<const UsbDeviceInfo*>(*it);
140 if (entry->device == device) {
141 devices_.erase(it);
142 if (observer()) {
143 observer()->OnDevicesChanged();
144 }
145 return;
146 }
59 } 147 }
60 } 148 }
61 149
62 name = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, 150 void OnDevicesEnumerated(
63 product_string, manufacturer_string); 151 const std::vector<scoped_refptr<UsbDevice>>& devices) {
152 for (const auto& device : devices) {
153 if (filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) {
154 device->CheckUsbAccess(base::Bind(
155 &UsbDevicePermissionsPrompt::AddCheckedUsbDevice, this, device));
156 }
157 }
158 }
159
160 void AddCheckedUsbDevice(scoped_refptr<UsbDevice> device, bool allowed) {
161 if (allowed) {
162 devices_.push_back(new UsbDeviceInfo(device));
163 if (observer()) {
164 observer()->OnDevicesChanged();
165 }
166 }
167 }
168
169 std::vector<UsbDeviceFilter> filters_;
170 DevicePermissionsPrompt::UsbDevicesCallback callback_;
171 ScopedObserver<UsbService, UsbService::Observer> service_observer_;
172 };
173
174 } // namespace
175
176 DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo() {
64 } 177 }
65 178
66 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() { 179 DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() {
67 } 180 }
68 181
69 DevicePermissionsPrompt::Prompt::Observer::~Observer() { 182 DevicePermissionsPrompt::Prompt::Observer::~Observer() {
70 } 183 }
71 184
72 DevicePermissionsPrompt::Prompt::Prompt(Delegate* delegate, 185 DevicePermissionsPrompt::Prompt::Prompt(const Extension* extension,
73 const Extension* extension, 186 content::BrowserContext* context,
74 content::BrowserContext* context) 187 bool multiple)
75 : extension_(extension), 188 : extension_(extension), browser_context_(context), multiple_(multiple) {
76 browser_context_(context),
77 delegate_(delegate),
78 usb_service_observer_(this) {
79 } 189 }
80 190
81 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) { 191 void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) {
82 observer_ = observer; 192 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 } 193 }
99 194
100 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const { 195 base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const {
101 return l10n_util::GetStringFUTF16(multiple_ 196 return l10n_util::GetStringFUTF16(multiple_
102 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE 197 ? IDS_DEVICE_PERMISSIONS_PROMPT_MULTIPLE
103 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE, 198 : IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE,
104 base::UTF8ToUTF16(extension_->name())); 199 base::UTF8ToUTF16(extension_->name()));
105 } 200 }
106 201
107 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName( 202 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName(
108 size_t index) const { 203 size_t index) const {
109 DCHECK_LT(index, devices_.size()); 204 DCHECK_LT(index, devices_.size());
110 return devices_[index].name; 205 return devices_[index]->name;
111 } 206 }
112 207
113 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber( 208 base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber(
114 size_t index) const { 209 size_t index) const {
115 DCHECK_LT(index, devices_.size()); 210 DCHECK_LT(index, devices_.size());
116 return devices_[index].device->serial_number(); 211 return devices_[index]->serial_number;
117 } 212 }
118 213
119 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) { 214 void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) {
120 DCHECK_LT(index, devices_.size()); 215 DCHECK_LT(index, devices_.size());
121 devices_[index].granted = true; 216 devices_[index]->granted = true;
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 } 217 }
143 218
144 DevicePermissionsPrompt::Prompt::~Prompt() { 219 DevicePermissionsPrompt::Prompt::~Prompt() {
145 } 220 }
146 221
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( 222 DevicePermissionsPrompt::DevicePermissionsPrompt(
195 content::WebContents* web_contents) 223 content::WebContents* web_contents)
196 : web_contents_(web_contents) { 224 : web_contents_(web_contents) {
197 } 225 }
198 226
199 DevicePermissionsPrompt::~DevicePermissionsPrompt() { 227 DevicePermissionsPrompt::~DevicePermissionsPrompt() {
200 } 228 }
201 229
202 void DevicePermissionsPrompt::AskForUsbDevices( 230 void DevicePermissionsPrompt::AskForUsbDevices(
203 Delegate* delegate,
204 const Extension* extension, 231 const Extension* extension,
205 content::BrowserContext* context, 232 content::BrowserContext* context,
206 bool multiple, 233 bool multiple,
207 const std::vector<UsbDeviceFilter>& filters) { 234 const std::vector<UsbDeviceFilter>& filters,
208 prompt_ = new Prompt(delegate, extension, context); 235 const UsbDevicesCallback& callback) {
209 prompt_->set_multiple(multiple); 236 prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple,
210 prompt_->set_filters(filters); 237 filters, callback);
211
212 ShowDialog(); 238 ShowDialog();
213 } 239 }
214 240
215 } // namespace extensions 241 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698