| Index: extensions/browser/api/printer_provider/printer_provider_api.cc
|
| diff --git a/extensions/browser/api/printer_provider/printer_provider_api.cc b/extensions/browser/api/printer_provider/printer_provider_api.cc
|
| index cf1fda6ed4e7fde4a6d74c021b97c39b830ad54b..4d298e5f80b8fea6cde90dded690fc40fa998a13 100644
|
| --- a/extensions/browser/api/printer_provider/printer_provider_api.cc
|
| +++ b/extensions/browser/api/printer_provider/printer_provider_api.cc
|
| @@ -18,6 +18,10 @@
|
| #include "base/strings/string16.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/values.h"
|
| +#include "device/core/device_client.h"
|
| +#include "device/usb/usb_device.h"
|
| +#include "device/usb/usb_service.h"
|
| +#include "extensions/browser/api/device_permissions_manager.h"
|
| #include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
|
| #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h"
|
| #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h"
|
| @@ -25,8 +29,16 @@
|
| #include "extensions/browser/extension_registry.h"
|
| #include "extensions/browser/extension_registry_observer.h"
|
| #include "extensions/common/api/printer_provider.h"
|
| +#include "extensions/common/api/printer_provider/usb_printer_manifest_data.h"
|
| #include "extensions/common/api/printer_provider_internal.h"
|
| +#include "extensions/common/api/usb.h"
|
| #include "extensions/common/extension.h"
|
| +#include "extensions/common/permissions/permissions_data.h"
|
| +#include "extensions/common/value_builder.h"
|
| +
|
| +using device::UsbDevice;
|
| +using device::UsbDeviceFilter;
|
| +using device::UsbService;
|
|
|
| namespace extensions {
|
|
|
| @@ -68,12 +80,13 @@ bool ParsePrinterId(const std::string& printer_id,
|
| class GetPrintersRequest {
|
| public:
|
| explicit GetPrintersRequest(
|
| + bool wait_for_usb_printers,
|
| const PrinterProviderAPI::GetPrintersCallback& callback);
|
| ~GetPrintersRequest();
|
|
|
| // Adds an extension id to the list of the extensions that need to respond
|
| // to the event.
|
| - void AddSource(const std::string& extension_id);
|
| + void AddSource(const std::string& extension);
|
|
|
| // Whether all extensions have responded to the event.
|
| bool IsDone() const;
|
| @@ -83,6 +96,10 @@ class GetPrintersRequest {
|
| void ReportForExtension(const std::string& extension_id,
|
| const base::ListValue& printers);
|
|
|
| + // Runs the callback for USB printers and clears the request for a list of
|
| + // USB printers.
|
| + void ReportUsbPrinters(const base::ListValue& printers);
|
| +
|
| private:
|
| // Callback reporting event result for an extension. Called once for each
|
| // extension.
|
| @@ -90,6 +107,10 @@ class GetPrintersRequest {
|
|
|
| // The list of extensions that still have to respond to the event.
|
| std::set<std::string> extensions_;
|
| +
|
| + // Set when an extension supporting USB printers is detected and the
|
| + // GetPrintersRequest is not done until those devices are reported.
|
| + bool wait_for_usb_printers_;
|
| };
|
|
|
| // Keeps track of pending chrome.printerProvider.onGetPrintersRequested
|
| @@ -101,7 +122,8 @@ class PendingGetPrintersRequests {
|
|
|
| // Adds a new request to the set of pending requests. Returns the id
|
| // assigned to the request.
|
| - int Add(const PrinterProviderAPI::GetPrintersCallback& callback);
|
| + int Add(bool wait_for_usb_printers,
|
| + const PrinterProviderAPI::GetPrintersCallback& callback);
|
|
|
| // Completes a request for an extension. It runs the request callback with
|
| // values reported by the extension.
|
| @@ -114,8 +136,12 @@ class PendingGetPrintersRequests {
|
| // called as if the extension reported empty set of printers.
|
| void FailAllForExtension(const std::string& extension_id);
|
|
|
| - // Adds an extension id to the list of the extensions that need to respond
|
| - // to the event.
|
| + // Completes a request for all USB printers associated with registered
|
| + // extensions.
|
| + void CompleteUsbPrinters(int request_id, const base::ListValue& result);
|
| +
|
| + // Adds an extension to the list of the extensions that need to respond to the
|
| + // event.
|
| bool AddSource(int request_id, const std::string& extension_id);
|
|
|
| private:
|
| @@ -149,7 +175,7 @@ class PendingGetCapabilityRequests {
|
| std::map<int, PrinterProviderAPI::GetCapabilityCallback> pending_requests_;
|
| };
|
|
|
| -// Keeps track of pending chrome.printerProvider.ontPrintRequested requests
|
| +// Keeps track of pending chrome.printerProvider.onPrintRequested requests
|
| // for an extension.
|
| class PendingPrintRequests {
|
| public:
|
| @@ -182,6 +208,31 @@ class PendingPrintRequests {
|
| std::map<int, PrintRequest> pending_requests_;
|
| };
|
|
|
| +// Keeps track of pending chrome.printerProvider.onUsbAccessGranted requests
|
| +// for an extension.
|
| +class PendingUsbPrinterInfoRequests {
|
| + public:
|
| + PendingUsbPrinterInfoRequests();
|
| + ~PendingUsbPrinterInfoRequests();
|
| +
|
| + // Adds a new request to the set. Only information needed is the callback
|
| + // associated with the request. Returns the id assigned to the request.
|
| + int Add(const PrinterProviderAPI::UsbAccessGrantedCallback& callback);
|
| +
|
| + // Completes the request with the provided request id. It runs the request
|
| + // callback and removes the request from the set.
|
| + void Complete(int request_id,
|
| + const core_api::printer_provider::PrinterInfo* printer_info);
|
| +
|
| + // Runs all pending callbacks with empty capability value and clears the
|
| + // set of pending requests.
|
| + void FailAll();
|
| +
|
| + private:
|
| + int last_request_id_ = 0;
|
| + std::map<int, PrinterProviderAPI::UsbAccessGrantedCallback> pending_requests_;
|
| +};
|
| +
|
| // Implements chrome.printerProvider API events.
|
| class PrinterProviderAPIImpl : public PrinterProviderAPI,
|
| public PrinterProviderInternalAPIObserver,
|
| @@ -202,6 +253,10 @@ class PrinterProviderAPIImpl : public PrinterProviderAPI,
|
| const PrinterProviderAPI::PrintCallback& callback) override;
|
| const PrinterProviderPrintJob* GetPrintJob(const Extension* extension,
|
| int request_id) const override;
|
| + void DispatchGrantUsbPrinterAccess(
|
| + const std::string& extension_id,
|
| + int device_id,
|
| + const PrinterProviderAPI::UsbAccessGrantedCallback& callback) override;
|
|
|
| // PrinterProviderInternalAPIObserver implementation:
|
| void OnGetPrintersResult(
|
| @@ -216,6 +271,10 @@ class PrinterProviderAPIImpl : public PrinterProviderAPI,
|
| const Extension* extension,
|
| int request_id,
|
| core_api::printer_provider_internal::PrintError error) override;
|
| + void OnUsbAccessGrantedResult(
|
| + const Extension* extension,
|
| + int request_id,
|
| + const core_api::printer_provider::PrinterInfo* printer_info) override;
|
|
|
| // ExtensionRegistryObserver implementation:
|
| void OnExtensionUnloaded(content::BrowserContext* browser_context,
|
| @@ -232,6 +291,10 @@ class PrinterProviderAPIImpl : public PrinterProviderAPI,
|
| const Extension* extension,
|
| base::ListValue* args);
|
|
|
| + void OnUsbDevicesEnumerated(
|
| + int request_id,
|
| + const std::vector<scoped_refptr<UsbDevice>>& devices);
|
| +
|
| content::BrowserContext* browser_context_;
|
|
|
| PendingGetPrintersRequests pending_get_printers_requests_;
|
| @@ -241,18 +304,24 @@ class PrinterProviderAPIImpl : public PrinterProviderAPI,
|
| std::map<std::string, PendingGetCapabilityRequests>
|
| pending_capability_requests_;
|
|
|
| + std::map<std::string, PendingUsbPrinterInfoRequests>
|
| + pending_usb_printer_info_requests_;
|
| +
|
| ScopedObserver<PrinterProviderInternalAPI, PrinterProviderInternalAPIObserver>
|
| internal_api_observer_;
|
|
|
| ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
|
| extension_registry_observer_;
|
|
|
| + base::WeakPtrFactory<PrinterProviderAPIImpl> weak_factory_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPIImpl);
|
| };
|
|
|
| GetPrintersRequest::GetPrintersRequest(
|
| + bool wait_for_usb_printers,
|
| const PrinterProviderAPI::GetPrintersCallback& callback)
|
| - : callback_(callback) {
|
| + : callback_(callback), wait_for_usb_printers_(wait_for_usb_printers) {
|
| }
|
|
|
| GetPrintersRequest::~GetPrintersRequest() {
|
| @@ -263,7 +332,7 @@ void GetPrintersRequest::AddSource(const std::string& extension_id) {
|
| }
|
|
|
| bool GetPrintersRequest::IsDone() const {
|
| - return extensions_.empty();
|
| + return extensions_.empty() && !wait_for_usb_printers_;
|
| }
|
|
|
| void GetPrintersRequest::ReportForExtension(const std::string& extension_id,
|
| @@ -272,6 +341,12 @@ void GetPrintersRequest::ReportForExtension(const std::string& extension_id,
|
| callback_.Run(printers, IsDone());
|
| }
|
|
|
| +void GetPrintersRequest::ReportUsbPrinters(const base::ListValue& printers) {
|
| + DCHECK(wait_for_usb_printers_);
|
| + wait_for_usb_printers_ = false;
|
| + callback_.Run(printers, IsDone());
|
| +}
|
| +
|
| PendingGetPrintersRequests::PendingGetPrintersRequests() : last_request_id_(0) {
|
| }
|
|
|
| @@ -279,9 +354,10 @@ PendingGetPrintersRequests::~PendingGetPrintersRequests() {
|
| }
|
|
|
| int PendingGetPrintersRequests::Add(
|
| + bool wait_for_usb_printers,
|
| const PrinterProviderAPI::GetPrintersCallback& callback) {
|
| - pending_requests_.insert(
|
| - std::make_pair(++last_request_id_, GetPrintersRequest(callback)));
|
| + pending_requests_.insert(std::make_pair(
|
| + ++last_request_id_, GetPrintersRequest(wait_for_usb_printers, callback)));
|
| return last_request_id_;
|
| }
|
|
|
| @@ -312,6 +388,20 @@ void PendingGetPrintersRequests::FailAllForExtension(
|
| }
|
| }
|
|
|
| +void PendingGetPrintersRequests::CompleteUsbPrinters(
|
| + int request_id,
|
| + const base::ListValue& result) {
|
| + auto it = pending_requests_.find(request_id);
|
| + if (it == pending_requests_.end()) {
|
| + return;
|
| + }
|
| +
|
| + it->second.ReportUsbPrinters(result);
|
| + if (it->second.IsDone()) {
|
| + pending_requests_.erase(it);
|
| + }
|
| +}
|
| +
|
| bool PendingGetPrintersRequests::AddSource(int request_id,
|
| const std::string& extension_id) {
|
| auto it = pending_requests_.find(request_id);
|
| @@ -401,11 +491,49 @@ void PendingPrintRequests::FailAll() {
|
| pending_requests_.clear();
|
| }
|
|
|
| +PendingUsbPrinterInfoRequests::PendingUsbPrinterInfoRequests() {
|
| +}
|
| +
|
| +PendingUsbPrinterInfoRequests::~PendingUsbPrinterInfoRequests() {
|
| +}
|
| +
|
| +int PendingUsbPrinterInfoRequests::Add(
|
| + const PrinterProviderAPI::UsbAccessGrantedCallback& callback) {
|
| + pending_requests_[++last_request_id_] = callback;
|
| + return last_request_id_;
|
| +}
|
| +
|
| +void PendingUsbPrinterInfoRequests::Complete(
|
| + int request_id,
|
| + const core_api::printer_provider::PrinterInfo* printer_info) {
|
| + auto it = pending_requests_.find(request_id);
|
| + if (it == pending_requests_.end()) {
|
| + return;
|
| + }
|
| +
|
| + PrinterProviderAPI::UsbAccessGrantedCallback callback = it->second;
|
| + pending_requests_.erase(it);
|
| +
|
| + if (printer_info) {
|
| + callback.Run(*printer_info->ToValue().get());
|
| + } else {
|
| + callback.Run(base::DictionaryValue());
|
| + }
|
| +}
|
| +
|
| +void PendingUsbPrinterInfoRequests::FailAll() {
|
| + for (auto& request : pending_requests_) {
|
| + request.second.Run(base::DictionaryValue());
|
| + }
|
| + pending_requests_.clear();
|
| +}
|
| +
|
| PrinterProviderAPIImpl::PrinterProviderAPIImpl(
|
| content::BrowserContext* browser_context)
|
| : browser_context_(browser_context),
|
| internal_api_observer_(this),
|
| - extension_registry_observer_(this) {
|
| + extension_registry_observer_(this),
|
| + weak_factory_(this) {
|
| internal_api_observer_.Add(
|
| PrinterProviderInternalAPI::GetFactoryInstance()->Get(browser_context));
|
| extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context));
|
| @@ -423,10 +551,21 @@ void PrinterProviderAPIImpl::DispatchGetPrintersRequested(
|
| return;
|
| }
|
|
|
| - // |pending_get_printers_requests_| take ownership of |request| which gets
|
| - // NULLed out. Save the pointer before passing it to the requests, as it will
|
| - // be needed later on.
|
| - int request_id = pending_get_printers_requests_.Add(callback);
|
| + bool extensions_support_usb_devices = false;
|
| + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
|
| + for (const auto& extension : registry->enabled_extensions()) {
|
| + if (UsbPrinterManifestData::Get(extension.get()) &&
|
| + extension->permissions_data() &&
|
| + extension->permissions_data()->HasAPIPermission(
|
| + extensions::APIPermission::kPrinterProvider) &&
|
| + extension->permissions_data()->HasAPIPermission(
|
| + extensions::APIPermission::kUsb)) {
|
| + extensions_support_usb_devices = true;
|
| + }
|
| + }
|
| +
|
| + int request_id = pending_get_printers_requests_.Add(
|
| + extensions_support_usb_devices, callback);
|
|
|
| scoped_ptr<base::ListValue> internal_args(new base::ListValue);
|
| // Request id is not part of the public API, but it will be massaged out in
|
| @@ -443,6 +582,17 @@ void PrinterProviderAPIImpl::DispatchGetPrintersRequested(
|
| base::Unretained(this), request_id);
|
|
|
| event_router->BroadcastEvent(event.Pass());
|
| +
|
| + // Start the USB device enumeration after the event has been broadcast to
|
| + // extensions as OnUsbDevicesEnumerated may be called synchronously and that
|
| + // would complete the request before extensions can be Added to it.
|
| + if (extensions_support_usb_devices) {
|
| + UsbService* service = device::DeviceClient::Get()->GetUsbService();
|
| + DCHECK(service);
|
| + service->GetDevices(
|
| + base::Bind(&PrinterProviderAPIImpl::OnUsbDevicesEnumerated,
|
| + weak_factory_.GetWeakPtr(), request_id));
|
| + }
|
| }
|
|
|
| void PrinterProviderAPIImpl::DispatchGetCapabilityRequested(
|
| @@ -534,6 +684,49 @@ const PrinterProviderPrintJob* PrinterProviderAPIImpl::GetPrintJob(
|
| return it->second.GetPrintJob(request_id);
|
| }
|
|
|
| +void PrinterProviderAPIImpl::DispatchGrantUsbPrinterAccess(
|
| + const std::string& extension_id,
|
| + int device_id,
|
| + const PrinterProviderAPI::UsbAccessGrantedCallback& callback) {
|
| + UsbService* service = device::DeviceClient::Get()->GetUsbService();
|
| + DCHECK(service);
|
| + scoped_refptr<UsbDevice> device = service->GetDeviceById(device_id);
|
| + if (!device) {
|
| + callback.Run(base::DictionaryValue());
|
| + return;
|
| + }
|
| +
|
| + DevicePermissionsManager* permissions_manager =
|
| + DevicePermissionsManager::Get(browser_context_);
|
| + DCHECK(permissions_manager);
|
| + permissions_manager->AllowUsbDevice(extension_id, device);
|
| +
|
| + EventRouter* event_router = EventRouter::Get(browser_context_);
|
| + if (!event_router->ExtensionHasEventListener(
|
| + extension_id,
|
| + core_api::printer_provider::OnUsbAccessGranted::kEventName)) {
|
| + callback.Run(base::DictionaryValue());
|
| + return;
|
| + }
|
| +
|
| + int request_id =
|
| + pending_usb_printer_info_requests_[extension_id].Add(callback);
|
| + core_api::usb::Device usb_device;
|
| + usb_device.device = device->unique_id();
|
| + usb_device.vendor_id = device->vendor_id();
|
| + usb_device.product_id = device->product_id();
|
| +
|
| + scoped_ptr<base::ListValue> internal_args(new base::ListValue);
|
| + // Request id is not part of the public API and it will be massaged out in
|
| + // custom bindings.
|
| + internal_args->AppendInteger(request_id);
|
| + internal_args->Append(usb_device.ToValue().release());
|
| + scoped_ptr<Event> event(
|
| + new Event(core_api::printer_provider::OnUsbAccessGranted::kEventName,
|
| + internal_args.Pass()));
|
| + event_router->DispatchEventToExtension(extension_id, event.Pass());
|
| +}
|
| +
|
| void PrinterProviderAPIImpl::OnGetPrintersResult(
|
| const Extension* extension,
|
| int request_id,
|
| @@ -590,6 +783,14 @@ void PrinterProviderAPIImpl::OnPrintResult(
|
| error_str);
|
| }
|
|
|
| +void PrinterProviderAPIImpl::OnUsbAccessGrantedResult(
|
| + const Extension* extension,
|
| + int request_id,
|
| + const core_api::printer_provider::PrinterInfo* printer_info) {
|
| + pending_usb_printer_info_requests_[extension->id()].Complete(request_id,
|
| + printer_info);
|
| +}
|
| +
|
| void PrinterProviderAPIImpl::OnExtensionUnloaded(
|
| content::BrowserContext* browser_context,
|
| const Extension* extension,
|
| @@ -607,6 +808,12 @@ void PrinterProviderAPIImpl::OnExtensionUnloaded(
|
| capability_it->second.FailAll();
|
| pending_capability_requests_.erase(capability_it);
|
| }
|
| +
|
| + auto usb_it = pending_usb_printer_info_requests_.find(extension->id());
|
| + if (usb_it != pending_usb_printer_info_requests_.end()) {
|
| + usb_it->second.FailAll();
|
| + pending_usb_printer_info_requests_.erase(usb_it);
|
| + }
|
| }
|
|
|
| bool PrinterProviderAPIImpl::WillRequestPrinters(
|
| @@ -626,6 +833,56 @@ bool PrinterProviderAPIImpl::WillRequestPrinters(
|
| return pending_get_printers_requests_.AddSource(request_id, extension->id());
|
| }
|
|
|
| +void PrinterProviderAPIImpl::OnUsbDevicesEnumerated(
|
| + int request_id,
|
| + const std::vector<scoped_refptr<UsbDevice>>& devices) {
|
| + std::map<scoped_refptr<UsbDevice>,
|
| + std::vector<scoped_refptr<const Extension>>> result_map;
|
| +
|
| + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
|
| + for (const auto& extension : registry->enabled_extensions()) {
|
| + const UsbPrinterManifestData* manifest_data =
|
| + UsbPrinterManifestData::Get(extension.get());
|
| +
|
| + if (!manifest_data || !extension->permissions_data() ||
|
| + !extension->permissions_data()->HasAPIPermission(
|
| + extensions::APIPermission::kPrinterProvider) ||
|
| + !extension->permissions_data()->HasAPIPermission(
|
| + extensions::APIPermission::kUsb)) {
|
| + continue;
|
| + }
|
| +
|
| + for (const auto& device : devices) {
|
| + if (manifest_data->SupportsDevice(device)) {
|
| + result_map[device].push_back(extension);
|
| + }
|
| + }
|
| + }
|
| +
|
| + ListBuilder printer_list;
|
| + for (const auto& map_entry : result_map) {
|
| + ListBuilder extension_list;
|
| + for (const scoped_refptr<const Extension>& extension : map_entry.second) {
|
| + extension_list.Append(DictionaryBuilder()
|
| + .Set("extensionId", extension->id())
|
| + .Set("extensionName", extension->name()));
|
| + }
|
| +
|
| + const scoped_refptr<UsbDevice>& device = map_entry.first;
|
| + printer_list.Append(
|
| + DictionaryBuilder()
|
| + .Set("name", DevicePermissionsManager::GetPermissionMessage(
|
| + device->vendor_id(), device->product_id(),
|
| + device->manufacturer_string(),
|
| + device->product_string(), base::string16(), false))
|
| + .Set("usbDevice", static_cast<int>(device->unique_id()))
|
| + .Set("extensions", extension_list.Pass()));
|
| + }
|
| +
|
| + pending_get_printers_requests_.CompleteUsbPrinters(
|
| + request_id, *printer_list.Build().get());
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
|
|