Add ICU message format support
[chromium-blink-merge.git] / extensions / browser / api / printer_provider / printer_provider_api.cc
blob1f2ce7dc69dffa70818151d95f2c690700fa6d24
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.
5 #include "extensions/browser/api/printer_provider/printer_provider_api.h"
7 #include <map>
8 #include <set>
9 #include <utility>
10 #include <vector>
12 #include "base/bind.h"
13 #include "base/i18n/rtl.h"
14 #include "base/json/json_string_value_serializer.h"
15 #include "base/macros.h"
16 #include "base/scoped_observer.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "device/usb/usb_device.h"
21 #include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
22 #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h"
23 #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h"
24 #include "extensions/browser/api/usb/usb_guid_map.h"
25 #include "extensions/browser/event_router.h"
26 #include "extensions/browser/extension_registry.h"
27 #include "extensions/browser/extension_registry_observer.h"
28 #include "extensions/common/api/printer_provider.h"
29 #include "extensions/common/api/printer_provider_internal.h"
30 #include "extensions/common/api/usb.h"
31 #include "extensions/common/extension.h"
33 using device::UsbDevice;
35 namespace extensions {
37 namespace {
39 // The separator between extension id and the extension's internal printer id
40 // used when generating a printer id unique across extensions.
41 const char kPrinterIdSeparator = ':';
43 // Given an extension ID and an ID of a printer reported by the extension, it
44 // generates a ID for the printer unique across extensions (assuming that the
45 // printer id is unique in the extension's space).
46 std::string GeneratePrinterId(const std::string& extension_id,
47 const std::string& internal_printer_id) {
48 std::string result = extension_id;
49 result.append(1, kPrinterIdSeparator);
50 result.append(internal_printer_id);
51 return result;
54 // Parses an ID created using |GeneratePrinterId| to it's components:
55 // the extension ID and the printer ID internal to the extension.
56 // Returns whenter the ID was succesfully parsed.
57 bool ParsePrinterId(const std::string& printer_id,
58 std::string* extension_id,
59 std::string* internal_printer_id) {
60 size_t separator = printer_id.find_first_of(kPrinterIdSeparator);
61 if (separator == std::string::npos)
62 return false;
63 *extension_id = printer_id.substr(0, separator);
64 *internal_printer_id = printer_id.substr(separator + 1);
65 return true;
68 void UpdatePrinterWithExtensionInfo(base::DictionaryValue* printer,
69 const Extension* extension) {
70 std::string internal_printer_id;
71 CHECK(printer->GetString("id", &internal_printer_id));
72 printer->SetString("id",
73 GeneratePrinterId(extension->id(), internal_printer_id));
74 printer->SetString("extensionId", extension->id());
75 printer->SetString("extensionName", extension->name());
77 base::string16 printer_name;
78 if (printer->GetString("name", &printer_name) &&
79 base::i18n::AdjustStringForLocaleDirection(&printer_name)) {
80 printer->SetString("name", printer_name);
83 base::string16 printer_description;
84 if (printer->GetString("description", &printer_description) &&
85 base::i18n::AdjustStringForLocaleDirection(&printer_description)) {
86 printer->SetString("description", printer_description);
90 // Holds information about a pending onGetPrintersRequested request;
91 // in particular, the list of extensions to which the event was dispatched but
92 // which haven't yet responded, and the |GetPrinters| callback associated with
93 // the event.
94 class GetPrintersRequest {
95 public:
96 explicit GetPrintersRequest(
97 const PrinterProviderAPI::GetPrintersCallback& callback);
98 ~GetPrintersRequest();
100 // Adds an extension id to the list of the extensions that need to respond
101 // to the event.
102 void AddSource(const std::string& extension_id);
104 // Whether all extensions have responded to the event.
105 bool IsDone() const;
107 // Runs the callback for an extension and removes the extension from the
108 // list of extensions that still have to respond to the event.
109 void ReportForExtension(const std::string& extension_id,
110 const base::ListValue& printers);
112 private:
113 // Callback reporting event result for an extension. Called once for each
114 // extension.
115 PrinterProviderAPI::GetPrintersCallback callback_;
117 // The list of extensions that still have to respond to the event.
118 std::set<std::string> extensions_;
121 // Keeps track of pending chrome.printerProvider.onGetPrintersRequested
122 // requests.
123 class PendingGetPrintersRequests {
124 public:
125 PendingGetPrintersRequests();
126 ~PendingGetPrintersRequests();
128 // Adds a new request to the set of pending requests. Returns the id
129 // assigned to the request.
130 int Add(const PrinterProviderAPI::GetPrintersCallback& callback);
132 // Completes a request for an extension. It runs the request callback with
133 // values reported by the extension.
134 bool CompleteForExtension(const std::string& extension_id,
135 int request_id,
136 const base::ListValue& result);
138 // Runs callbacks for the extension for all requests that are waiting for a
139 // response from the extension with the provided extension id. Callbacks are
140 // called as if the extension reported empty set of printers.
141 void FailAllForExtension(const std::string& extension_id);
143 // Adds an extension id to the list of the extensions that need to respond to
144 // the event.
145 bool AddSource(int request_id, const std::string& extension_id);
147 private:
148 int last_request_id_;
149 std::map<int, GetPrintersRequest> pending_requests_;
151 DISALLOW_COPY_AND_ASSIGN(PendingGetPrintersRequests);
154 // Keeps track of pending chrome.printerProvider.onGetCapabilityRequested
155 // requests for an extension.
156 class PendingGetCapabilityRequests {
157 public:
158 PendingGetCapabilityRequests();
159 ~PendingGetCapabilityRequests();
161 // Adds a new request to the set. Only information needed is the callback
162 // associated with the request. Returns the id assigned to the request.
163 int Add(const PrinterProviderAPI::GetCapabilityCallback& callback);
165 // Completes the request with the provided request id. It runs the request
166 // callback and removes the request from the set.
167 bool Complete(int request_id, const base::DictionaryValue& result);
169 // Runs all pending callbacks with empty capability value and clears the
170 // set of pending requests.
171 void FailAll();
173 private:
174 int last_request_id_;
175 std::map<int, PrinterProviderAPI::GetCapabilityCallback> pending_requests_;
178 // Keeps track of pending chrome.printerProvider.onPrintRequested requests
179 // for an extension.
180 class PendingPrintRequests {
181 public:
182 PendingPrintRequests();
183 ~PendingPrintRequests();
185 // Adds a new request to the set. Only information needed is the callback
186 // associated with the request. Returns the id assigned to the request.
187 int Add(const PrinterProviderPrintJob& job,
188 const PrinterProviderAPI::PrintCallback& callback);
190 // Gets print job associated with a request.
191 const PrinterProviderPrintJob* GetPrintJob(int request_id) const;
193 // Completes the request with the provided request id. It runs the request
194 // callback and removes the request from the set.
195 bool Complete(int request_id, bool success, const std::string& result);
197 // Runs all pending callbacks with ERROR_FAILED and clears the set of
198 // pending requests.
199 void FailAll();
201 private:
202 struct PrintRequest {
203 PrinterProviderAPI::PrintCallback callback;
204 PrinterProviderPrintJob job;
207 int last_request_id_;
208 std::map<int, PrintRequest> pending_requests_;
211 // Keeps track of pending chrome.printerProvider.onGetUsbPrinterInfoRequested
212 // requests for an extension.
213 class PendingUsbPrinterInfoRequests {
214 public:
215 PendingUsbPrinterInfoRequests();
216 ~PendingUsbPrinterInfoRequests();
218 // Adds a new request to the set. Only information needed is the callback
219 // associated with the request. Returns the id assigned to the request.
220 int Add(const PrinterProviderAPI::GetPrinterInfoCallback& callback);
222 // Completes the request with the provided request id. It runs the request
223 // callback and removes the request from the set.
224 void Complete(int request_id, const base::DictionaryValue& printer_info);
226 // Runs all pending callbacks with empty capability value and clears the
227 // set of pending requests.
228 void FailAll();
230 private:
231 int last_request_id_ = 0;
232 std::map<int, PrinterProviderAPI::GetPrinterInfoCallback> pending_requests_;
235 // Implements chrome.printerProvider API events.
236 class PrinterProviderAPIImpl : public PrinterProviderAPI,
237 public PrinterProviderInternalAPIObserver,
238 public ExtensionRegistryObserver {
239 public:
240 explicit PrinterProviderAPIImpl(content::BrowserContext* browser_context);
241 ~PrinterProviderAPIImpl() override;
243 private:
244 // PrinterProviderAPI implementation:
245 void DispatchGetPrintersRequested(
246 const PrinterProviderAPI::GetPrintersCallback& callback) override;
247 void DispatchGetCapabilityRequested(
248 const std::string& printer_id,
249 const PrinterProviderAPI::GetCapabilityCallback& callback) override;
250 void DispatchPrintRequested(
251 const PrinterProviderPrintJob& job,
252 const PrinterProviderAPI::PrintCallback& callback) override;
253 const PrinterProviderPrintJob* GetPrintJob(const Extension* extension,
254 int request_id) const override;
255 void DispatchGetUsbPrinterInfoRequested(
256 const std::string& extension_id,
257 scoped_refptr<UsbDevice> device,
258 const PrinterProviderAPI::GetPrinterInfoCallback& callback) override;
260 // PrinterProviderInternalAPIObserver implementation:
261 void OnGetPrintersResult(
262 const Extension* extension,
263 int request_id,
264 const PrinterProviderInternalAPIObserver::PrinterInfoVector& result)
265 override;
266 void OnGetCapabilityResult(const Extension* extension,
267 int request_id,
268 const base::DictionaryValue& result) override;
269 void OnPrintResult(const Extension* extension,
270 int request_id,
271 api::printer_provider_internal::PrintError error) override;
272 void OnGetUsbPrinterInfoResult(
273 const Extension* extension,
274 int request_id,
275 const api::printer_provider::PrinterInfo* printer_info) override;
277 // ExtensionRegistryObserver implementation:
278 void OnExtensionUnloaded(content::BrowserContext* browser_context,
279 const Extension* extension,
280 UnloadedExtensionInfo::Reason reason) override;
282 // Called before chrome.printerProvider.onGetPrintersRequested event is
283 // dispatched to an extension. It returns whether the extension is interested
284 // in the event. If the extension listens to the event, it's added to the set
285 // of |request| sources. |request| is |GetPrintersRequest| object associated
286 // with the event.
287 bool WillRequestPrinters(int request_id,
288 content::BrowserContext* browser_context,
289 const Extension* extension,
290 base::ListValue* args,
291 const base::DictionaryValue* listener_filter);
293 content::BrowserContext* browser_context_;
295 PendingGetPrintersRequests pending_get_printers_requests_;
297 std::map<std::string, PendingPrintRequests> pending_print_requests_;
299 std::map<std::string, PendingGetCapabilityRequests>
300 pending_capability_requests_;
302 std::map<std::string, PendingUsbPrinterInfoRequests>
303 pending_usb_printer_info_requests_;
305 ScopedObserver<PrinterProviderInternalAPI, PrinterProviderInternalAPIObserver>
306 internal_api_observer_;
308 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
309 extension_registry_observer_;
311 DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPIImpl);
314 GetPrintersRequest::GetPrintersRequest(
315 const PrinterProviderAPI::GetPrintersCallback& callback)
316 : callback_(callback) {
319 GetPrintersRequest::~GetPrintersRequest() {
322 void GetPrintersRequest::AddSource(const std::string& extension_id) {
323 extensions_.insert(extension_id);
326 bool GetPrintersRequest::IsDone() const {
327 return extensions_.empty();
330 void GetPrintersRequest::ReportForExtension(const std::string& extension_id,
331 const base::ListValue& printers) {
332 if (extensions_.erase(extension_id) > 0)
333 callback_.Run(printers, IsDone());
336 PendingGetPrintersRequests::PendingGetPrintersRequests() : last_request_id_(0) {
339 PendingGetPrintersRequests::~PendingGetPrintersRequests() {
342 int PendingGetPrintersRequests::Add(
343 const PrinterProviderAPI::GetPrintersCallback& callback) {
344 pending_requests_.insert(
345 std::make_pair(++last_request_id_, GetPrintersRequest(callback)));
346 return last_request_id_;
349 bool PendingGetPrintersRequests::CompleteForExtension(
350 const std::string& extension_id,
351 int request_id,
352 const base::ListValue& result) {
353 auto it = pending_requests_.find(request_id);
354 if (it == pending_requests_.end())
355 return false;
357 it->second.ReportForExtension(extension_id, result);
358 if (it->second.IsDone()) {
359 pending_requests_.erase(it);
361 return true;
364 void PendingGetPrintersRequests::FailAllForExtension(
365 const std::string& extension_id) {
366 auto it = pending_requests_.begin();
367 while (it != pending_requests_.end()) {
368 int request_id = it->first;
369 // |it| may get deleted during |CompleteForExtension|, so progress it to the
370 // next item before calling the method.
371 ++it;
372 CompleteForExtension(extension_id, request_id, base::ListValue());
376 bool PendingGetPrintersRequests::AddSource(int request_id,
377 const std::string& extension_id) {
378 auto it = pending_requests_.find(request_id);
379 if (it == pending_requests_.end())
380 return false;
382 it->second.AddSource(extension_id);
383 return true;
386 PendingGetCapabilityRequests::PendingGetCapabilityRequests()
387 : last_request_id_(0) {
390 PendingGetCapabilityRequests::~PendingGetCapabilityRequests() {
393 int PendingGetCapabilityRequests::Add(
394 const PrinterProviderAPI::GetCapabilityCallback& callback) {
395 pending_requests_[++last_request_id_] = callback;
396 return last_request_id_;
399 bool PendingGetCapabilityRequests::Complete(
400 int request_id,
401 const base::DictionaryValue& response) {
402 auto it = pending_requests_.find(request_id);
403 if (it == pending_requests_.end())
404 return false;
406 PrinterProviderAPI::GetCapabilityCallback callback = it->second;
407 pending_requests_.erase(it);
409 callback.Run(response);
410 return true;
413 void PendingGetCapabilityRequests::FailAll() {
414 for (auto& request : pending_requests_)
415 request.second.Run(base::DictionaryValue());
416 pending_requests_.clear();
419 PendingPrintRequests::PendingPrintRequests() : last_request_id_(0) {
422 PendingPrintRequests::~PendingPrintRequests() {
425 int PendingPrintRequests::Add(
426 const PrinterProviderPrintJob& job,
427 const PrinterProviderAPI::PrintCallback& callback) {
428 PrintRequest request;
429 request.callback = callback;
430 request.job = job;
431 pending_requests_[++last_request_id_] = request;
432 return last_request_id_;
435 bool PendingPrintRequests::Complete(int request_id,
436 bool success,
437 const std::string& response) {
438 auto it = pending_requests_.find(request_id);
439 if (it == pending_requests_.end())
440 return false;
442 PrinterProviderAPI::PrintCallback callback = it->second.callback;
443 pending_requests_.erase(it);
445 callback.Run(success, response);
446 return true;
449 const PrinterProviderPrintJob* PendingPrintRequests::GetPrintJob(
450 int request_id) const {
451 auto it = pending_requests_.find(request_id);
452 if (it == pending_requests_.end())
453 return nullptr;
455 return &it->second.job;
458 void PendingPrintRequests::FailAll() {
459 for (auto& request : pending_requests_)
460 request.second.callback.Run(false,
461 PrinterProviderAPI::GetDefaultPrintError());
462 pending_requests_.clear();
465 PendingUsbPrinterInfoRequests::PendingUsbPrinterInfoRequests() {
468 PendingUsbPrinterInfoRequests::~PendingUsbPrinterInfoRequests() {
471 int PendingUsbPrinterInfoRequests::Add(
472 const PrinterProviderAPI::GetPrinterInfoCallback& callback) {
473 pending_requests_[++last_request_id_] = callback;
474 return last_request_id_;
477 void PendingUsbPrinterInfoRequests::Complete(
478 int request_id,
479 const base::DictionaryValue& printer_info) {
480 auto it = pending_requests_.find(request_id);
481 if (it == pending_requests_.end())
482 return;
484 PrinterProviderAPI::GetPrinterInfoCallback callback = it->second;
485 pending_requests_.erase(it);
487 callback.Run(printer_info);
490 void PendingUsbPrinterInfoRequests::FailAll() {
491 for (auto& request : pending_requests_) {
492 request.second.Run(base::DictionaryValue());
494 pending_requests_.clear();
497 PrinterProviderAPIImpl::PrinterProviderAPIImpl(
498 content::BrowserContext* browser_context)
499 : browser_context_(browser_context),
500 internal_api_observer_(this),
501 extension_registry_observer_(this) {
502 internal_api_observer_.Add(
503 PrinterProviderInternalAPI::GetFactoryInstance()->Get(browser_context));
504 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context));
507 PrinterProviderAPIImpl::~PrinterProviderAPIImpl() {
510 void PrinterProviderAPIImpl::DispatchGetPrintersRequested(
511 const GetPrintersCallback& callback) {
512 EventRouter* event_router = EventRouter::Get(browser_context_);
513 if (!event_router->HasEventListener(
514 api::printer_provider::OnGetPrintersRequested::kEventName)) {
515 callback.Run(base::ListValue(), true /* done */);
516 return;
519 // |pending_get_printers_requests_| take ownership of |request| which gets
520 // NULLed out. Save the pointer before passing it to the requests, as it will
521 // be needed later on.
522 int request_id = pending_get_printers_requests_.Add(callback);
524 scoped_ptr<base::ListValue> internal_args(new base::ListValue);
525 // Request id is not part of the public API, but it will be massaged out in
526 // custom bindings.
527 internal_args->AppendInteger(request_id);
529 scoped_ptr<Event> event(
530 new Event(events::PRINTER_PROVIDER_ON_GET_PRINTERS_REQUESTED,
531 api::printer_provider::OnGetPrintersRequested::kEventName,
532 internal_args.Pass()));
533 // This callback is called synchronously during |BroadcastEvent|, so
534 // Unretained is safe.
535 event->will_dispatch_callback =
536 base::Bind(&PrinterProviderAPIImpl::WillRequestPrinters,
537 base::Unretained(this), request_id);
539 event_router->BroadcastEvent(event.Pass());
542 void PrinterProviderAPIImpl::DispatchGetCapabilityRequested(
543 const std::string& printer_id,
544 const PrinterProviderAPI::GetCapabilityCallback& callback) {
545 std::string extension_id;
546 std::string internal_printer_id;
547 if (!ParsePrinterId(printer_id, &extension_id, &internal_printer_id)) {
548 callback.Run(base::DictionaryValue());
549 return;
552 EventRouter* event_router = EventRouter::Get(browser_context_);
553 if (!event_router->ExtensionHasEventListener(
554 extension_id,
555 api::printer_provider::OnGetCapabilityRequested::kEventName)) {
556 callback.Run(base::DictionaryValue());
557 return;
560 int request_id = pending_capability_requests_[extension_id].Add(callback);
562 scoped_ptr<base::ListValue> internal_args(new base::ListValue);
563 // Request id is not part of the public API, but it will be massaged out in
564 // custom bindings.
565 internal_args->AppendInteger(request_id);
566 internal_args->AppendString(internal_printer_id);
568 scoped_ptr<Event> event(
569 new Event(events::PRINTER_PROVIDER_ON_GET_CAPABILITY_REQUESTED,
570 api::printer_provider::OnGetCapabilityRequested::kEventName,
571 internal_args.Pass()));
573 event_router->DispatchEventToExtension(extension_id, event.Pass());
576 void PrinterProviderAPIImpl::DispatchPrintRequested(
577 const PrinterProviderPrintJob& job,
578 const PrinterProviderAPI::PrintCallback& callback) {
579 std::string extension_id;
580 std::string internal_printer_id;
581 if (!ParsePrinterId(job.printer_id, &extension_id, &internal_printer_id)) {
582 callback.Run(false, PrinterProviderAPI::GetDefaultPrintError());
583 return;
586 EventRouter* event_router = EventRouter::Get(browser_context_);
587 if (!event_router->ExtensionHasEventListener(
588 extension_id, api::printer_provider::OnPrintRequested::kEventName)) {
589 callback.Run(false, PrinterProviderAPI::GetDefaultPrintError());
590 return;
593 api::printer_provider::PrintJob print_job;
594 print_job.printer_id = internal_printer_id;
596 JSONStringValueDeserializer deserializer(job.ticket_json);
597 scoped_ptr<base::Value> ticket_value(deserializer.Deserialize(NULL, NULL));
598 if (!ticket_value ||
599 !api::printer_provider::PrintJob::Ticket::Populate(*ticket_value,
600 &print_job.ticket)) {
601 callback.Run(false, api::printer_provider::ToString(
602 api::printer_provider::PRINT_ERROR_INVALID_TICKET));
603 return;
606 print_job.content_type = job.content_type;
607 print_job.title = base::UTF16ToUTF8(job.job_title);
608 int request_id = pending_print_requests_[extension_id].Add(job, callback);
610 scoped_ptr<base::ListValue> internal_args(new base::ListValue);
611 // Request id is not part of the public API and it will be massaged out in
612 // custom bindings.
613 internal_args->AppendInteger(request_id);
614 internal_args->Append(print_job.ToValue().release());
615 scoped_ptr<Event> event(
616 new Event(events::PRINTER_PROVIDER_ON_PRINT_REQUESTED,
617 api::printer_provider::OnPrintRequested::kEventName,
618 internal_args.Pass()));
619 event_router->DispatchEventToExtension(extension_id, event.Pass());
622 const PrinterProviderPrintJob* PrinterProviderAPIImpl::GetPrintJob(
623 const Extension* extension,
624 int request_id) const {
625 auto it = pending_print_requests_.find(extension->id());
626 if (it == pending_print_requests_.end())
627 return nullptr;
628 return it->second.GetPrintJob(request_id);
631 void PrinterProviderAPIImpl::DispatchGetUsbPrinterInfoRequested(
632 const std::string& extension_id,
633 scoped_refptr<UsbDevice> device,
634 const PrinterProviderAPI::GetPrinterInfoCallback& callback) {
635 EventRouter* event_router = EventRouter::Get(browser_context_);
636 if (!event_router->ExtensionHasEventListener(
637 extension_id,
638 api::printer_provider::OnGetUsbPrinterInfoRequested::kEventName)) {
639 callback.Run(base::DictionaryValue());
640 return;
643 int request_id =
644 pending_usb_printer_info_requests_[extension_id].Add(callback);
645 api::usb::Device usb_device;
646 usb_device.device =
647 UsbGuidMap::Get(browser_context_)->GetIdFromGuid(device->guid());
648 usb_device.vendor_id = device->vendor_id();
649 usb_device.product_id = device->product_id();
651 scoped_ptr<base::ListValue> internal_args(new base::ListValue);
652 // Request id is not part of the public API and it will be massaged out in
653 // custom bindings.
654 internal_args->AppendInteger(request_id);
655 internal_args->Append(usb_device.ToValue().release());
656 scoped_ptr<Event> event(
657 new Event(events::PRINTER_PROVIDER_ON_GET_USB_PRINTER_INFO_REQUESTED,
658 api::printer_provider::OnGetUsbPrinterInfoRequested::kEventName,
659 internal_args.Pass()));
660 event_router->DispatchEventToExtension(extension_id, event.Pass());
663 void PrinterProviderAPIImpl::OnGetPrintersResult(
664 const Extension* extension,
665 int request_id,
666 const PrinterProviderInternalAPIObserver::PrinterInfoVector& result) {
667 base::ListValue printer_list;
669 // Update some printer description properties to better identify the extension
670 // managing the printer.
671 for (size_t i = 0; i < result.size(); ++i) {
672 scoped_ptr<base::DictionaryValue> printer(result[i]->ToValue());
673 UpdatePrinterWithExtensionInfo(printer.get(), extension);
674 printer_list.Append(printer.Pass());
677 pending_get_printers_requests_.CompleteForExtension(extension->id(),
678 request_id, printer_list);
681 void PrinterProviderAPIImpl::OnGetCapabilityResult(
682 const Extension* extension,
683 int request_id,
684 const base::DictionaryValue& result) {
685 pending_capability_requests_[extension->id()].Complete(request_id, result);
688 void PrinterProviderAPIImpl::OnPrintResult(
689 const Extension* extension,
690 int request_id,
691 api::printer_provider_internal::PrintError error) {
692 const std::string error_str =
693 error == api::printer_provider_internal::PRINT_ERROR_NONE
694 ? PrinterProviderAPI::GetDefaultPrintError()
695 : api::printer_provider_internal::ToString(error);
696 pending_print_requests_[extension->id()].Complete(
697 request_id, error == api::printer_provider_internal::PRINT_ERROR_OK,
698 error_str);
701 void PrinterProviderAPIImpl::OnGetUsbPrinterInfoResult(
702 const Extension* extension,
703 int request_id,
704 const api::printer_provider::PrinterInfo* result) {
705 if (result) {
706 scoped_ptr<base::DictionaryValue> printer(result->ToValue());
707 UpdatePrinterWithExtensionInfo(printer.get(), extension);
708 pending_usb_printer_info_requests_[extension->id()].Complete(request_id,
709 *printer);
710 } else {
711 pending_usb_printer_info_requests_[extension->id()].Complete(
712 request_id, base::DictionaryValue());
716 void PrinterProviderAPIImpl::OnExtensionUnloaded(
717 content::BrowserContext* browser_context,
718 const Extension* extension,
719 UnloadedExtensionInfo::Reason reason) {
720 pending_get_printers_requests_.FailAllForExtension(extension->id());
722 auto print_it = pending_print_requests_.find(extension->id());
723 if (print_it != pending_print_requests_.end()) {
724 print_it->second.FailAll();
725 pending_print_requests_.erase(print_it);
728 auto capability_it = pending_capability_requests_.find(extension->id());
729 if (capability_it != pending_capability_requests_.end()) {
730 capability_it->second.FailAll();
731 pending_capability_requests_.erase(capability_it);
734 auto usb_it = pending_usb_printer_info_requests_.find(extension->id());
735 if (usb_it != pending_usb_printer_info_requests_.end()) {
736 usb_it->second.FailAll();
737 pending_usb_printer_info_requests_.erase(usb_it);
741 bool PrinterProviderAPIImpl::WillRequestPrinters(
742 int request_id,
743 content::BrowserContext* browser_context,
744 const Extension* extension,
745 base::ListValue* args,
746 const base::DictionaryValue* listener_filter) {
747 if (!extension)
748 return false;
749 EventRouter* event_router = EventRouter::Get(browser_context_);
750 if (!event_router->ExtensionHasEventListener(
751 extension->id(),
752 api::printer_provider::OnGetPrintersRequested::kEventName)) {
753 return false;
756 return pending_get_printers_requests_.AddSource(request_id, extension->id());
759 } // namespace
761 // static
762 PrinterProviderAPI* PrinterProviderAPI::Create(
763 content::BrowserContext* context) {
764 return new PrinterProviderAPIImpl(context);
767 // static
768 std::string PrinterProviderAPI::GetDefaultPrintError() {
769 return api::printer_provider_internal::ToString(
770 api::printer_provider_internal::PRINT_ERROR_FAILED);
773 } // namespace extensions