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

Unified Diff: extensions/browser/api/printer_provider/printer_provider_api.cc

Issue 1148383002: Add onGetUsbPrinterInfoRequested event to printerProvider API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698