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

Side by Side Diff: chrome/browser/chromeos/printer_detector/legacy_printer_detector.cc

Issue 2945653002: Remove the legacy (extension-notifier) usb printer detector. Rename the remaining printerdetector … (Closed)
Patch Set: Remove the legacy (extension-notifier) usb printer detector. Rename the remaining printerdetector … Created 3 years, 6 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
(Empty)
1 // Copyright 2015 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.
4
5 #include <stdint.h>
6
7 #include <memory>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/macros.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/scoped_observer.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chromeos/printer_detector/printer_detector.h"
20 #include "chrome/browser/chromeos/printing/usb_printer_util.h"
21 #include "chrome/browser/chromeos/profiles/profile_helper.h"
22 #include "chrome/browser/notifications/notification.h"
23 #include "chrome/browser/notifications/notification_delegate.h"
24 #include "chrome/browser/notifications/notification_ui_manager.h"
25 #include "chrome/browser/ui/browser_navigator.h"
26 #include "chrome/common/extensions/api/webstore_widget_private.h"
27 #include "chrome/common/extensions/extension_constants.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "chrome/grit/theme_resources.h"
30 #include "components/user_manager/user.h"
31 #include "components/user_manager/user_manager.h"
32 #include "device/base/device_client.h"
33 #include "device/usb/usb_device.h"
34 #include "device/usb/usb_device_filter.h"
35 #include "device/usb/usb_ids.h"
36 #include "device/usb/usb_service.h"
37 #include "extensions/browser/event_router.h"
38 #include "extensions/browser/extension_registry.h"
39 #include "extensions/browser/extension_system.h"
40 #include "extensions/common/api/printer_provider/usb_printer_manifest_data.h"
41 #include "extensions/common/extension.h"
42 #include "extensions/common/extension_set.h"
43 #include "extensions/common/one_shot_event.h"
44 #include "extensions/common/permissions/api_permission.h"
45 #include "extensions/common/permissions/permissions_data.h"
46 #include "extensions/common/permissions/usb_device_permission.h"
47 #include "ui/base/l10n/l10n_util.h"
48 #include "ui/base/resource/resource_bundle.h"
49
50 namespace webstore_widget_private_api =
51 extensions::api::webstore_widget_private;
52
53 namespace chromeos {
54 namespace {
55
56 const char kPrinterProviderFoundNotificationID[] =
57 "chrome://settings/printer/printer_app_found";
58
59 const char kNoPrinterProviderNotificationID[] =
60 "chrome://settings/printer/no_printer_app";
61
62 enum PrinterServiceEvent {
63 PRINTER_ADDED,
64 DEPRECATED_PAGE_DISPLAYED,
65 NOTIFICATION_SHOWN_PRINTER_SUPPORTED,
66 NOTIFICATION_SHOWN_PRINTER_NOT_SUPPORTED,
67 WEBSTORE_WIDGET_APP_LAUNCHED,
68 PRINTER_SERVICE_EVENT_MAX,
69 };
70
71 base::string16 GetNotificationTitle(uint16_t vendor_id, uint16_t product_id) {
72 const char* vendor_name = device::UsbIds::GetVendorName(vendor_id);
73 if (vendor_name) {
74 return l10n_util::GetStringFUTF16(IDS_PRINTER_DETECTED_NOTIFICATION_TITLE,
75 base::UTF8ToUTF16(vendor_name));
76 } else {
77 return l10n_util::GetStringUTF16(
78 IDS_PRINTER_DETECTED_NOTIFICATION_TITLE_UNKNOWN_VENDOR);
79 }
80 }
81
82 std::string GetNotificationTag(const std::string& vendor_id,
83 const std::string& product_id) {
84 return vendor_id + ":" + product_id;
85 }
86
87 // Checks if there is an enabled extension with printerProvider permission and
88 // usbDevices persmission for the USB (vendor_id, product_id) pair.
89 bool HasAppThatSupportsPrinter(Profile* profile,
90 const scoped_refptr<device::UsbDevice>& device) {
91 const extensions::ExtensionSet& enabled_extensions =
92 extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
93 for (const auto& extension : enabled_extensions) {
94 if (!extension->permissions_data() ||
95 !extension->permissions_data()->HasAPIPermission(
96 extensions::APIPermission::kPrinterProvider) ||
97 !extension->permissions_data()->HasAPIPermission(
98 extensions::APIPermission::kUsb)) {
99 continue;
100 }
101
102 const extensions::UsbPrinterManifestData* manifest_data =
103 extensions::UsbPrinterManifestData::Get(extension.get());
104 if (manifest_data && manifest_data->SupportsDevice(device)) {
105 return true;
106 }
107
108 std::unique_ptr<extensions::UsbDevicePermission::CheckParam> param =
109 extensions::UsbDevicePermission::CheckParam::ForUsbDevice(
110 extension.get(), device.get());
111 if (extension->permissions_data()->CheckAPIPermissionWithParam(
112 extensions::APIPermission::kUsbDevice, param.get())) {
113 return true;
114 }
115 }
116 return false;
117 }
118
119 // Delegate for notification shown when a printer provider app for the plugged
120 // in printer is found.
121 class PrinterProviderExistsNotificationDelegate : public NotificationDelegate {
122 public:
123 PrinterProviderExistsNotificationDelegate(const std::string& vendor_id,
124 const std::string& product_id)
125 : vendor_id_(vendor_id), product_id_(product_id) {}
126
127 std::string id() const override {
128 return "system.printer.printer_provider_exists/" +
129 GetNotificationTag(vendor_id_, product_id_);
130 }
131
132 private:
133 ~PrinterProviderExistsNotificationDelegate() override = default;
134
135 const std::string vendor_id_;
136 const std::string product_id_;
137
138 DISALLOW_COPY_AND_ASSIGN(PrinterProviderExistsNotificationDelegate);
139 };
140
141 // Delegate for notification shown when there are no printer provider apps that
142 // support the plugged in printer found.
143 // The notification is clickable, and clicking it is supposed to launch
144 // Chrome Web Store widget listing apps that can support the plugged in printer.
145 // (not implemented yet).
146 class SearchPrinterAppNotificationDelegate : public NotificationDelegate {
147 public:
148 SearchPrinterAppNotificationDelegate(content::BrowserContext* browser_context,
149 uint16_t vendor_id,
150 const std::string& vendor_id_str,
151 uint16_t product_id,
152 const std::string& product_id_str)
153 : browser_context_(browser_context),
154 vendor_id_(vendor_id),
155 vendor_id_str_(vendor_id_str),
156 product_id_(product_id),
157 product_id_str_(product_id_str) {}
158
159 std::string id() const override {
160 return "system.printer.no_printer_provider_found/" +
161 GetNotificationTag(vendor_id_str_, product_id_str_);
162 }
163
164 bool HasClickedListener() override { return true; }
165
166 void Click() override {
167 UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent",
168 WEBSTORE_WIDGET_APP_LAUNCHED,
169 PRINTER_SERVICE_EVENT_MAX);
170 webstore_widget_private_api::Options options;
171 options.type = webstore_widget_private_api::TYPE_PRINTER_PROVIDER;
172 options.usb_id.reset(new webstore_widget_private_api::UsbId());
173 options.usb_id->vendor_id = vendor_id_;
174 options.usb_id->product_id = product_id_;
175
176 extensions::EventRouter* event_router =
177 extensions::EventRouter::Get(browser_context_);
178 std::unique_ptr<extensions::Event> event(new extensions::Event(
179 extensions::events::WEBSTORE_WIDGET_PRIVATE_ON_SHOW_WIDGET,
180 webstore_widget_private_api::OnShowWidget::kEventName,
181 webstore_widget_private_api::OnShowWidget::Create(options)));
182 event_router->DispatchEventToExtension(extension_misc::kWebstoreWidgetAppId,
183 std::move(event));
184 }
185
186 private:
187 ~SearchPrinterAppNotificationDelegate() override = default;
188
189 content::BrowserContext* browser_context_;
190 uint16_t vendor_id_;
191 std::string vendor_id_str_;
192 uint16_t product_id_;
193 std::string product_id_str_;
194
195 DISALLOW_COPY_AND_ASSIGN(SearchPrinterAppNotificationDelegate);
196 };
197
198 // The PrinterDetector that initiates extension-based USB printer setup:
199 //
200 // * if there is a printer provider extension for a detected USB printer
201 // installed, it shows a notification informing the user the printer is ready to
202 // be used.
203 //
204 // * otherwise, it shows a notification offering the user an option to install a
205 // printer provider extension for the printer from the Chrome Web Store.
206 //
207 // TODO(justincarlson) - Remove this implementation when CUPS support is enabled
208 // by default.
209 class LegacyPrinterDetectorImpl : public PrinterDetector,
210 public device::UsbService::Observer {
211 public:
212 explicit LegacyPrinterDetectorImpl(Profile* profile)
213 : profile_(profile),
214 notification_ui_manager_(nullptr),
215 observer_(this),
216 weak_ptr_factory_(this) {
217 extensions::ExtensionSystem::Get(profile)->ready().Post(
218 FROM_HERE, base::Bind(&LegacyPrinterDetectorImpl::Initialize,
219 weak_ptr_factory_.GetWeakPtr()));
220 }
221 ~LegacyPrinterDetectorImpl() override = default;
222
223 private:
224 // UsbService::observer override:
225 void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override {
226 const user_manager::User* user =
227 ProfileHelper::Get()->GetUserByProfile(profile_);
228 if (!user || !user->HasGaiaAccount() || !user_manager::UserManager::Get() ||
229 user != user_manager::UserManager::Get()->GetActiveUser()) {
230 return;
231 }
232
233 if (!UsbDeviceIsPrinter(*device)) {
234 return;
235 }
236
237 if (notification_ui_manager_ == nullptr) {
238 notification_ui_manager_ = g_browser_process->notification_ui_manager();
239 }
240
241 UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent",
242 PRINTER_ADDED, PRINTER_SERVICE_EVENT_MAX);
243 ShowPrinterPluggedNotification(device);
244 }
245
246 // Initializes the printer detector.
247 void Initialize() {
248 device::UsbService* usb_service =
249 device::DeviceClient::Get()->GetUsbService();
250 if (!usb_service)
251 return;
252 observer_.Add(usb_service);
253 }
254
255 void SetNotificationUIManagerForTesting(
256 NotificationUIManager* manager) override {
257 notification_ui_manager_ = manager;
258 }
259
260 // Shows a notification for a plugged in printer.
261 // If there is a printerProvider app that handles the printer's USB
262 // (vendor_id, product_id) pair, the notification informs the user that the
263 // printer is ready to be used, otherwise it offers the user to search the
264 // Chrome Web Store for an app that can handle the printer.
265 void ShowPrinterPluggedNotification(
266 const scoped_refptr<device::UsbDevice>& device) {
267 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
268 std::unique_ptr<Notification> notification;
269
270 const std::string kVendorIdStr = base::IntToString(device->vendor_id());
271 const std::string kProductIdStr = base::IntToString(device->product_id());
272
273 if (HasAppThatSupportsPrinter(profile_, device)) {
274 UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent",
275 NOTIFICATION_SHOWN_PRINTER_SUPPORTED,
276 PRINTER_SERVICE_EVENT_MAX);
277 notification.reset(new Notification(
278 message_center::NOTIFICATION_TYPE_SIMPLE,
279 GetNotificationTitle(device->vendor_id(), device->product_id()),
280 l10n_util::GetStringUTF16(
281 IDS_PRINTER_DETECTED_NOTIFICATION_PRINT_APP_FOUND_BODY),
282 bundle.GetImageNamed(IDR_PRINTER_NOTIFICATION),
283 message_center::NotifierId(
284 message_center::NotifierId::SYSTEM_COMPONENT,
285 kPrinterProviderFoundNotificationID),
286 base::string16(), GURL(kPrinterProviderFoundNotificationID),
287 GetNotificationTag(kVendorIdStr, kProductIdStr),
288 message_center::RichNotificationData(),
289 new PrinterProviderExistsNotificationDelegate(kVendorIdStr,
290 kProductIdStr)));
291 } else {
292 UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent",
293 NOTIFICATION_SHOWN_PRINTER_NOT_SUPPORTED,
294 PRINTER_SERVICE_EVENT_MAX);
295 message_center::RichNotificationData options;
296 options.clickable = true;
297 notification.reset(new Notification(
298 message_center::NOTIFICATION_TYPE_SIMPLE,
299 GetNotificationTitle(device->vendor_id(), device->product_id()),
300 l10n_util::GetStringUTF16(
301 IDS_PRINTER_DETECTED_NOTIFICATION_NO_PRINT_APP_BODY),
302 bundle.GetImageNamed(IDR_PRINTER_NOTIFICATION),
303 message_center::NotifierId(
304 message_center::NotifierId::SYSTEM_COMPONENT,
305 kNoPrinterProviderNotificationID),
306 base::string16(), GURL(kNoPrinterProviderNotificationID),
307 GetNotificationTag(kVendorIdStr, kProductIdStr), options,
308 new SearchPrinterAppNotificationDelegate(
309 profile_, device->vendor_id(), kVendorIdStr, device->product_id(),
310 kProductIdStr)));
311 }
312
313 notification->SetSystemPriority();
314 notification_ui_manager_->Add(*notification, profile_);
315 }
316
317 std::unique_ptr<Notification> notification_;
318
319 Profile* profile_;
320 NotificationUIManager* notification_ui_manager_;
321 ScopedObserver<device::UsbService, device::UsbService::Observer> observer_;
322 base::WeakPtrFactory<LegacyPrinterDetectorImpl> weak_ptr_factory_;
323 };
324
325 } // namespace
326
327 // static
328 std::unique_ptr<PrinterDetector> PrinterDetector::CreateLegacy(
329 Profile* profile) {
330 return base::MakeUnique<LegacyPrinterDetectorImpl>(profile);
331 }
332
333 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698