Commit 1378bc38 authored by tbarzic's avatar tbarzic Committed by Commit bot

Make PrinterProviderAPI a pure interface

This makes PrinterProviderAPI a pure interface, with the
implementation hidden in printer_provider.cc, and with a custom browser
context keyed service factory. This will make it easier to inject a
fake API implementation in tests (e.g. for ExtensionPrinterHandler).

BUG=461114
TEST=extensions_browsertests --gtest_filter=PrinterProviderAPI

Review URL: https://codereview.chromium.org/922833004

Cr-Commit-Position: refs/heads/master@{#318124}
parent 05b47b88
......@@ -19,6 +19,8 @@
#include "components/cloud_devices/common/cloud_device_description.h"
#include "components/cloud_devices/common/printer_description.h"
#include "extensions/browser/api/printer_provider/printer_provider_api.h"
#include "extensions/browser/api/printer_provider/printer_provider_api_factory.h"
#include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
#include "printing/pdf_render_settings.h"
#include "printing/pwg_raster_settings.h"
......@@ -87,8 +89,8 @@ void ExtensionPrinterHandler::Reset() {
void ExtensionPrinterHandler::StartGetPrinters(
const PrinterHandler::GetPrintersCallback& callback) {
extensions::PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context_)
extensions::PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context_)
->DispatchGetPrintersRequested(
base::Bind(&ExtensionPrinterHandler::WrapGetPrintersCallback,
weak_ptr_factory_.GetWeakPtr(), callback));
......@@ -97,8 +99,8 @@ void ExtensionPrinterHandler::StartGetPrinters(
void ExtensionPrinterHandler::StartGetCapability(
const std::string& destination_id,
const PrinterHandler::GetCapabilityCallback& callback) {
extensions::PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context_)
extensions::PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context_)
->DispatchGetCapabilityRequested(
destination_id,
base::Bind(&ExtensionPrinterHandler::WrapGetCapabilityCallback,
......@@ -112,8 +114,8 @@ void ExtensionPrinterHandler::StartPrint(
const gfx::Size& page_size,
const scoped_refptr<base::RefCountedMemory>& print_data,
const PrinterHandler::PrintCallback& callback) {
scoped_ptr<extensions::PrinterProviderAPI::PrintJob> print_job(
new extensions::PrinterProviderAPI::PrintJob());
scoped_ptr<extensions::PrinterProviderPrintJob> print_job(
new extensions::PrinterProviderPrintJob());
print_job->printer_id = destination_id;
print_job->ticket_json = ticket_json;
......@@ -163,7 +165,7 @@ void ExtensionPrinterHandler::ConvertToPWGRaster(
void ExtensionPrinterHandler::DispatchPrintJob(
const PrinterHandler::PrintCallback& callback,
scoped_ptr<extensions::PrinterProviderAPI::PrintJob> print_job,
scoped_ptr<extensions::PrinterProviderPrintJob> print_job,
const scoped_refptr<base::RefCountedMemory>& print_data) {
if (!print_data) {
WrapPrintCallback(callback, false, kInvalidDataPrintError);
......@@ -172,8 +174,8 @@ void ExtensionPrinterHandler::DispatchPrintJob(
print_job->document_bytes = print_data;
extensions::PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context_)
extensions::PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context_)
->DispatchPrintRequested(
*print_job, base::Bind(&ExtensionPrinterHandler::WrapPrintCallback,
weak_ptr_factory_.GetWeakPtr(), callback));
......
......@@ -73,11 +73,9 @@ class ExtensionPrinterHandler : public PrinterHandler {
const RefCountedMemoryCallback& callback);
// Sets print job document data and dispatches it using printerProvider API.
// TODO(tbarzic): Move PrinterProvider::PrintJob to it's own file so it can
// be forward-declared.
void DispatchPrintJob(
const PrinterHandler::PrintCallback& callback,
scoped_ptr<extensions::PrinterProviderAPI::PrintJob> print_job,
scoped_ptr<extensions::PrinterProviderPrintJob> print_job,
const scoped_refptr<base::RefCountedMemory>& data);
// Methods used as wrappers to callbacks for extensions::PrinterProviderAPI
......
......@@ -4,17 +4,23 @@
#include "extensions/browser/api/printer_provider/printer_provider_api.h"
#include <map>
#include <set>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/scoped_observer.h"
#include "base/values.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"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_factory.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/api/printer_provider.h"
#include "extensions/common/api/printer_provider_internal.h"
#include "extensions/common/extension.h"
......@@ -23,9 +29,6 @@ namespace extensions {
namespace {
static base::LazyInstance<BrowserContextKeyedAPIFactory<PrinterProviderAPI>>
g_api_factory = LAZY_INSTANCE_INITIALIZER;
// The separator between extension id and the extension's internal printer id
// used when generating a printer id unique across extensions.
const char kPrinterIdSeparator = ':';
......@@ -55,27 +58,323 @@ bool ParsePrinterId(const std::string& printer_id,
return true;
}
} // namespace
// Holds information about a pending onGetPrintersRequested request;
// in particular, the list of extensions to which the event was dispatched but
// which haven't yet responded, and the |GetPrinters| callback associated with
// the event.
class GetPrintersRequest {
public:
explicit GetPrintersRequest(
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);
// Whether all extensions have responded to the event.
bool IsDone() const;
// Runs the callback for an extension and removes the extension from the
// list of extensions that still have to respond to the event.
void ReportForExtension(const std::string& extension_id,
const base::ListValue& printers);
private:
// Callback reporting event result for an extension. Called once for each
// extension.
PrinterProviderAPI::GetPrintersCallback callback_;
// The list of extensions that still have to respond to the event.
std::set<std::string> extensions_;
};
// Keeps track of pending chrome.printerProvider.onGetPrintersRequested
// requests.
class PendingGetPrintersRequests {
public:
PendingGetPrintersRequests();
~PendingGetPrintersRequests();
// Adds a new request to the set of pending requests. Returns the id
// assigned to the request.
int Add(const PrinterProviderAPI::GetPrintersCallback& callback);
// Completes a request for an extension. It runs the request callback with
// values reported by the extension.
bool CompleteForExtension(const std::string& extension_id,
int request_id,
const base::ListValue& result);
// Runs callbacks for the extension for all requests that are waiting for a
// response from the extension with the provided extension id. Callbacks are
// 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.
bool AddSource(int request_id, const std::string& extension_id);
private:
int last_request_id_;
std::map<int, GetPrintersRequest> pending_requests_;
DISALLOW_COPY_AND_ASSIGN(PendingGetPrintersRequests);
};
// Keeps track of pending chrome.printerProvider.onGetCapabilityRequested
// requests for an extension.
class PendingGetCapabilityRequests {
public:
PendingGetCapabilityRequests();
~PendingGetCapabilityRequests();
// 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::GetCapabilityCallback& callback);
// Completes the request with the provided request id. It runs the request
// callback and removes the request from the set.
bool Complete(int request_id, const base::DictionaryValue& result);
// Runs all pending callbacks with empty capability value and clears the
// set of pending requests.
void FailAll();
private:
int last_request_id_;
std::map<int, PrinterProviderAPI::GetCapabilityCallback> pending_requests_;
};
// Keeps track of pending chrome.printerProvider.ontPrintRequested requests
// for an extension.
class PendingPrintRequests {
public:
PendingPrintRequests();
~PendingPrintRequests();
// 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::PrintCallback& callback);
// Completes the request with the provided request id. It runs the request
// callback and removes the request from the set.
bool Complete(int request_id, bool success, const std::string& result);
// Runs all pending callbacks with ERROR_FAILED and clears the set of
// pending requests.
void FailAll();
private:
int last_request_id_;
std::map<int, PrinterProviderAPI::PrintCallback> pending_requests_;
};
// Implements chrome.printerProvider API events.
class PrinterProviderAPIImpl : public PrinterProviderAPI,
public PrinterProviderInternalAPIObserver,
public ExtensionRegistryObserver {
public:
explicit PrinterProviderAPIImpl(content::BrowserContext* browser_context);
~PrinterProviderAPIImpl() override;
private:
// PrinterProviderAPI implementation:
void DispatchGetPrintersRequested(
const PrinterProviderAPI::GetPrintersCallback& callback) override;
void DispatchGetCapabilityRequested(
const std::string& printer_id,
const PrinterProviderAPI::GetCapabilityCallback& callback) override;
void DispatchPrintRequested(
const PrinterProviderPrintJob& job,
const PrinterProviderAPI::PrintCallback& callback) override;
// PrinterProviderInternalAPIObserver implementation:
void OnGetPrintersResult(
const Extension* extension,
int request_id,
const PrinterProviderInternalAPIObserver::PrinterInfoVector& result)
override;
void OnGetCapabilityResult(const Extension* extension,
int request_id,
const base::DictionaryValue& result) override;
void OnPrintResult(
const Extension* extension,
int request_id,
core_api::printer_provider_internal::PrintError error) override;
// ExtensionRegistryObserver implementation:
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) override;
// Called before chrome.printerProvider.onGetPrintersRequested event is
// dispatched to an extension. It returns whether the extension is interested
// in the event. If the extension listens to the event, it's added to the set
// of |request| sources. |request| is |GetPrintersRequest| object associated
// with the event.
bool WillRequestPrinters(int request_id,
content::BrowserContext* browser_context,
const Extension* extension,
base::ListValue* args);
content::BrowserContext* browser_context_;
PendingGetPrintersRequests pending_get_printers_requests_;
std::map<std::string, PendingPrintRequests> pending_print_requests_;
std::map<std::string, PendingGetCapabilityRequests>
pending_capability_requests_;
ScopedObserver<PrinterProviderInternalAPI, PrinterProviderInternalAPIObserver>
internal_api_observer_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPIImpl);
};
GetPrintersRequest::GetPrintersRequest(
const PrinterProviderAPI::GetPrintersCallback& callback)
: callback_(callback) {
}
PrinterProviderAPI::PrintJob::PrintJob() {
GetPrintersRequest::~GetPrintersRequest() {
}
PrinterProviderAPI::PrintJob::~PrintJob() {
void GetPrintersRequest::AddSource(const std::string& extension_id) {
extensions_.insert(extension_id);
}
// static
BrowserContextKeyedAPIFactory<PrinterProviderAPI>*
PrinterProviderAPI::GetFactoryInstance() {
return g_api_factory.Pointer();
bool GetPrintersRequest::IsDone() const {
return extensions_.empty();
}
// static
std::string PrinterProviderAPI::GetDefaultPrintError() {
return core_api::printer_provider_internal::ToString(
core_api::printer_provider_internal::PRINT_ERROR_FAILED);
void GetPrintersRequest::ReportForExtension(const std::string& extension_id,
const base::ListValue& printers) {
if (extensions_.erase(extension_id) > 0)
callback_.Run(printers, IsDone());
}
PendingGetPrintersRequests::PendingGetPrintersRequests() : last_request_id_(0) {
}
PendingGetPrintersRequests::~PendingGetPrintersRequests() {
}
int PendingGetPrintersRequests::Add(
const PrinterProviderAPI::GetPrintersCallback& callback) {
pending_requests_.insert(
std::make_pair(++last_request_id_, GetPrintersRequest(callback)));
return last_request_id_;
}
bool PendingGetPrintersRequests::CompleteForExtension(
const std::string& extension_id,
int request_id,
const base::ListValue& result) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
it->second.ReportForExtension(extension_id, result);
if (it->second.IsDone()) {
pending_requests_.erase(it);
}
return true;
}
void PendingGetPrintersRequests::FailAllForExtension(
const std::string& extension_id) {
auto it = pending_requests_.begin();
while (it != pending_requests_.end()) {
int request_id = it->first;
// |it| may get deleted during |CompleteForExtension|, so progress it to the
// next item before calling the method.
++it;
CompleteForExtension(extension_id, request_id, base::ListValue());
}
}
bool PendingGetPrintersRequests::AddSource(int request_id,
const std::string& extension_id) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
it->second.AddSource(extension_id);
return true;
}
PendingGetCapabilityRequests::PendingGetCapabilityRequests()
: last_request_id_(0) {
}
PrinterProviderAPI::PrinterProviderAPI(content::BrowserContext* browser_context)
PendingGetCapabilityRequests::~PendingGetCapabilityRequests() {
}
int PendingGetCapabilityRequests::Add(
const PrinterProviderAPI::GetCapabilityCallback& callback) {
pending_requests_[++last_request_id_] = callback;
return last_request_id_;
}
bool PendingGetCapabilityRequests::Complete(
int request_id,
const base::DictionaryValue& response) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
PrinterProviderAPI::GetCapabilityCallback callback = it->second;
pending_requests_.erase(it);
callback.Run(response);
return true;
}
void PendingGetCapabilityRequests::FailAll() {
for (auto& request : pending_requests_)
request.second.Run(base::DictionaryValue());
pending_requests_.clear();
}
PendingPrintRequests::PendingPrintRequests() : last_request_id_(0) {
}
PendingPrintRequests::~PendingPrintRequests() {
}
int PendingPrintRequests::Add(
const PrinterProviderAPI::PrintCallback& callback) {
pending_requests_[++last_request_id_] = callback;
return last_request_id_;
}
bool PendingPrintRequests::Complete(int request_id,
bool success,
const std::string& response) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
PrinterProviderAPI::PrintCallback callback = it->second;
pending_requests_.erase(it);
callback.Run(success, response);
return true;
}
void PendingPrintRequests::FailAll() {
for (auto& request : pending_requests_)
request.second.Run(false, PrinterProviderAPI::GetDefaultPrintError());
pending_requests_.clear();
}
PrinterProviderAPIImpl::PrinterProviderAPIImpl(
content::BrowserContext* browser_context)
: browser_context_(browser_context),
internal_api_observer_(this),
extension_registry_observer_(this) {
......@@ -84,10 +383,10 @@ PrinterProviderAPI::PrinterProviderAPI(content::BrowserContext* browser_context)
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context));
}
PrinterProviderAPI::~PrinterProviderAPI() {
PrinterProviderAPIImpl::~PrinterProviderAPIImpl() {
}
void PrinterProviderAPI::DispatchGetPrintersRequested(
void PrinterProviderAPIImpl::DispatchGetPrintersRequested(
const GetPrintersCallback& callback) {
EventRouter* event_router = EventRouter::Get(browser_context_);
if (!event_router->HasEventListener(
......@@ -110,16 +409,15 @@ void PrinterProviderAPI::DispatchGetPrintersRequested(
new Event(core_api::printer_provider::OnGetPrintersRequested::kEventName,
internal_args.Pass()));
// This callback is called synchronously during |BroadcastEvent|, so
// Unretained is safe. Also, |raw_request_ptr| will stay valid at least until
// |BroadcastEvent| finishes.
// Unretained is safe.
event->will_dispatch_callback =
base::Bind(&PrinterProviderAPI::WillRequestPrinters,
base::Bind(&PrinterProviderAPIImpl::WillRequestPrinters,
base::Unretained(this), request_id);
event_router->BroadcastEvent(event.Pass());
}
void PrinterProviderAPI::DispatchGetCapabilityRequested(
void PrinterProviderAPIImpl::DispatchGetCapabilityRequested(
const std::string& printer_id,
const PrinterProviderAPI::GetCapabilityCallback& callback) {
std::string extension_id;
......@@ -152,13 +450,13 @@ void PrinterProviderAPI::DispatchGetCapabilityRequested(
event_router->DispatchEventToExtension(extension_id, event.Pass());
}
void PrinterProviderAPI::DispatchPrintRequested(
const PrinterProviderAPI::PrintJob& job,
void PrinterProviderAPIImpl::DispatchPrintRequested(
const PrinterProviderPrintJob& job,
const PrinterProviderAPI::PrintCallback& callback) {
std::string extension_id;
std::string internal_printer_id;
if (!ParsePrinterId(job.printer_id, &extension_id, &internal_printer_id)) {
callback.Run(false, GetDefaultPrintError());
callback.Run(false, PrinterProviderAPI::GetDefaultPrintError());
return;
}
......@@ -166,7 +464,7 @@ void PrinterProviderAPI::DispatchPrintRequested(
if (!event_router->ExtensionHasEventListener(
extension_id,
core_api::printer_provider::OnPrintRequested::kEventName)) {
callback.Run(false, GetDefaultPrintError());
callback.Run(false, PrinterProviderAPI::GetDefaultPrintError());
return;
}
......@@ -211,151 +509,7 @@ void PrinterProviderAPI::DispatchPrintRequested(
event_router->DispatchEventToExtension(extension_id, event.Pass());
}
PrinterProviderAPI::GetPrintersRequest::GetPrintersRequest(
const GetPrintersCallback& callback)
: callback_(callback) {
}
PrinterProviderAPI::GetPrintersRequest::~GetPrintersRequest() {
}
void PrinterProviderAPI::GetPrintersRequest::AddSource(
const std::string& extension_id) {
extensions_.insert(extension_id);
}
bool PrinterProviderAPI::GetPrintersRequest::IsDone() const {
return extensions_.empty();
}
void PrinterProviderAPI::GetPrintersRequest::ReportForExtension(
const std::string& extension_id,
const base::ListValue& printers) {
if (extensions_.erase(extension_id) > 0)
callback_.Run(printers, IsDone());
}
PrinterProviderAPI::PendingGetPrintersRequests::PendingGetPrintersRequests()
: last_request_id_(0) {
}
PrinterProviderAPI::PendingGetPrintersRequests::~PendingGetPrintersRequests() {
}
int PrinterProviderAPI::PendingGetPrintersRequests::Add(
const GetPrintersCallback& callback) {
pending_requests_.insert(
std::make_pair(++last_request_id_, GetPrintersRequest(callback)));
return last_request_id_;
}
bool PrinterProviderAPI::PendingGetPrintersRequests::CompleteForExtension(
const std::string& extension_id,
int request_id,
const base::ListValue& result) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
it->second.ReportForExtension(extension_id, result);
if (it->second.IsDone()) {
pending_requests_.erase(it);
}
return true;
}
void PrinterProviderAPI::PendingGetPrintersRequests::FailAllForExtension(
const std::string& extension_id) {
auto it = pending_requests_.begin();
while (it != pending_requests_.end()) {
int request_id = it->first;
// |it| may get deleted during |CompleteForExtension|, so progress it to the
// next item before calling the method.
++it;
CompleteForExtension(extension_id, request_id, base::ListValue());
}
}
bool PrinterProviderAPI::PendingGetPrintersRequests::AddSource(
int request_id,
const std::string& extension_id) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
it->second.AddSource(extension_id);
return true;
}
PrinterProviderAPI::PendingGetCapabilityRequests::PendingGetCapabilityRequests()
: last_request_id_(0) {
}
PrinterProviderAPI::PendingGetCapabilityRequests::
~PendingGetCapabilityRequests() {
}
int PrinterProviderAPI::PendingGetCapabilityRequests::Add(
const PrinterProviderAPI::GetCapabilityCallback& callback) {
pending_requests_[++last_request_id_] = callback;
return last_request_id_;
}
bool PrinterProviderAPI::PendingGetCapabilityRequests::Complete(
int request_id,
const base::DictionaryValue& response) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
GetCapabilityCallback callback = it->second;
pending_requests_.erase(it);
callback.Run(response);
return true;
}
void PrinterProviderAPI::PendingGetCapabilityRequests::FailAll() {
for (auto& request : pending_requests_)
request.second.Run(base::DictionaryValue());
pending_requests_.clear();
}
PrinterProviderAPI::PendingPrintRequests::PendingPrintRequests()
: last_request_id_(0) {
}
PrinterProviderAPI::PendingPrintRequests::~PendingPrintRequests() {
}
int PrinterProviderAPI::PendingPrintRequests::Add(
const PrinterProviderAPI::PrintCallback& callback) {
pending_requests_[++last_request_id_] = callback;
return last_request_id_;
}
bool PrinterProviderAPI::PendingPrintRequests::Complete(
int request_id,
bool success,
const std::string& response) {
auto it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return false;
PrintCallback callback = it->second;
pending_requests_.erase(it);
callback.Run(success, response);
return true;
}
void PrinterProviderAPI::PendingPrintRequests::FailAll() {
for (auto& request : pending_requests_)
request.second.Run(false, GetDefaultPrintError());
pending_requests_.clear();
}
void PrinterProviderAPI::OnGetPrintersResult(
void PrinterProviderAPIImpl::OnGetPrintersResult(
const Extension* extension,
int request_id,
const PrinterProviderInternalAPIObserver::PrinterInfoVector& result) {
......@@ -377,27 +531,27 @@ void PrinterProviderAPI::OnGetPrintersResult(
request_id, printer_list);
}
void PrinterProviderAPI::OnGetCapabilityResult(
void PrinterProviderAPIImpl::OnGetCapabilityResult(
const Extension* extension,
int request_id,
const base::DictionaryValue& result) {
pending_capability_requests_[extension->id()].Complete(request_id, result);
}
void PrinterProviderAPI::OnPrintResult(
void PrinterProviderAPIImpl::OnPrintResult(
const Extension* extension,
int request_id,
core_api::printer_provider_internal::PrintError error) {
const std::string error_str =
error == core_api::printer_provider_internal::PRINT_ERROR_NONE
? GetDefaultPrintError()
? PrinterProviderAPI::GetDefaultPrintError()
: core_api::printer_provider_internal::ToString(error);
pending_print_requests_[extension->id()].Complete(
request_id, error == core_api::printer_provider_internal::PRINT_ERROR_OK,
error_str);
}
void PrinterProviderAPI::OnExtensionUnloaded(
void PrinterProviderAPIImpl::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
......@@ -416,7 +570,7 @@ void PrinterProviderAPI::OnExtensionUnloaded(
}
}
bool PrinterProviderAPI::WillRequestPrinters(
bool PrinterProviderAPIImpl::WillRequestPrinters(
int request_id,
content::BrowserContext* browser_context,
const Extension* extension,
......@@ -433,12 +587,18 @@ bool PrinterProviderAPI::WillRequestPrinters(
return pending_get_printers_requests_.AddSource(request_id, extension->id());
}
template <>
void BrowserContextKeyedAPIFactory<
PrinterProviderAPI>::DeclareFactoryDependencies() {
DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
DependsOn(PrinterProviderInternalAPI::GetFactoryInstance());
DependsOn(ExtensionRegistryFactory::GetInstance());
} // namespace
// static
PrinterProviderAPI* PrinterProviderAPI::Create(
content::BrowserContext* context) {
return new PrinterProviderAPIImpl(context);
}
// static
std::string PrinterProviderAPI::GetDefaultPrintError() {
return core_api::printer_provider_internal::ToString(
core_api::printer_provider_internal::PRINT_ERROR_FAILED);
}
} // namespace extensions
......@@ -5,17 +5,10 @@
#ifndef EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_H_
#define EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_H_
#include <map>
#include <set>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/scoped_observer.h"
#include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_registry_observer.h"
#include "components/keyed_service/core/keyed_service.h"
namespace base {
class DictionaryValue;
......@@ -27,41 +20,14 @@ class BrowserContext;
}
namespace extensions {
class Extension;
class ExtensionRegistry;
class PrinterProviderInternalAPI;
struct PrinterProviderPrintJob;
}
namespace extensions {
// Implements chrome.printerProvider API events.
class PrinterProviderAPI : public BrowserContextKeyedAPI,
public PrinterProviderInternalAPIObserver,
public ExtensionRegistryObserver {
class PrinterProviderAPI : public KeyedService {
public:
// Struct describing print job that should be forwarded to an extension via
// chrome.printerProvider.onPrintRequested event.
struct PrintJob {
PrintJob();
~PrintJob();
// The id of the printer that should handle the print job. The id is
// formatted as <extension_id>:<printer_id>, where <extension_id> is the
// id of the extension that manages the printer, and <printer_id> is
// the the printer's id within the extension (as reported via
// chrome.printerProvider.onGetPrintersRequested event callback).
std::string printer_id;
// The print job ticket.
std::string ticket_json;
// Content type of the document that should be printed.
std::string content_type;
// The document data that should be printed.
scoped_refptr<base::RefCountedMemory> document_bytes;
};
using GetPrintersCallback =
base::Callback<void(const base::ListValue& printers, bool done)>;
using GetCapabilityCallback =
......@@ -69,25 +35,20 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI,
using PrintCallback =
base::Callback<void(bool success, const std::string& error)>;
static BrowserContextKeyedAPIFactory<PrinterProviderAPI>*
GetFactoryInstance();
static PrinterProviderAPI* Create(content::BrowserContext* context);
// Returns generic error string for print request.
static std::string GetDefaultPrintError();
explicit PrinterProviderAPI(content::BrowserContext* browser_context);
~PrinterProviderAPI() override;
// The API currently cannot handle very large files, so the document size that
// may be sent to an extension is restricted.
// TODO(tbarzic): Fix the API to support huge documents.
static const int kMaxDocumentSize = 50 * 1000 * 1000;
~PrinterProviderAPI() override {}
// Requests list of supported printers from extensions implementing
// chrome.printerProvider API. It dispatches
// chrome.printerProvider.onGetPrintersRequested event. The callback is
// called once for every extension handling the event with a list of its
// supported printers. The printer values reported by an extension are
// added "extensionId" property that is set to the ID of the extension
// returning the list.
// Note that the "id" property of printer values reported by an extension are
// rewriten as "<extension_id>:<id>" to ensure they are unique across
// different extensions.
void DispatchGetPrintersRequested(const GetPrintersCallback& callback);
virtual void DispatchGetPrintersRequested(
const GetPrintersCallback& callback) = 0;
// Requests printer capability for a printer with id |printer_id|.
// |printer_id| should be one of the printer ids reported by |GetPrinters|
......@@ -97,191 +58,19 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI,
// |printer_id| value).
// |callback| is passed a dictionary value containing printer capabilities as
// reported by the extension.
void DispatchGetCapabilityRequested(const std::string& printer_id,
const GetCapabilityCallback& callback);
virtual void DispatchGetCapabilityRequested(
const std::string& printer_id,
const GetCapabilityCallback& callback) = 0;
// It dispatches chrome.printerProvider.onPrintRequested event with the
// provided print job. The event is dispatched only to the extension that
// manages printer with id |job.printer_id|.
// |callback| is passed the print status returned by the extension, and it
// must not be null.
void DispatchPrintRequested(const PrintJob& job,
const PrintCallback& callback);
// The API currently cannot handle very large files, so the document size that
// may be sent to an extension is restricted.
// TODO(tbarzic): Fix the API to support huge documents.
static const int kMaxDocumentSize = 50 * 1000 * 1000;
private:
friend class BrowserContextKeyedAPIFactory<PrinterProviderAPI>;
// Holds information about a pending onGetPrintersRequested request;
// in particular, the list of extensions to which the event was dispatched but
// which haven't yet responded, and the |GetPrinters| callback associated with
// the event.
class GetPrintersRequest {
public:
explicit GetPrintersRequest(const 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);
// Whether all extensions have responded to the event.
bool IsDone() const;
// Runs the callback for an extension and removes the extension from the
// list of extensions that still have to respond to the event.
void ReportForExtension(const std::string& extension_id,
const base::ListValue& printers);
private:
// Callback reporting event result for an extension. Called once for each
// extension.
GetPrintersCallback callback_;
// The list of extensions that still have to respond to the event.
std::set<std::string> extensions_;
};
// Keeps track of pending chrome.printerProvider.onGetPrintersRequested
// requests.
class PendingGetPrintersRequests {
public:
PendingGetPrintersRequests();
~PendingGetPrintersRequests();
// Adds a new request to the set of pending requests. Returns the id
// assigned to the request.
int Add(const GetPrintersCallback& callback);
// Completes a request for an extension. It runs the request callback with
// values reported by the extension.
bool CompleteForExtension(const std::string& extension_id,
int request_id,
const base::ListValue& result);
// Runs callbacks for the extension for all requests that are waiting for a
// response from the extension with the provided extension id. Callbacks are
// 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.
bool AddSource(int request_id, const std::string& extension_id);
private:
int last_request_id_;
std::map<int, GetPrintersRequest> pending_requests_;
DISALLOW_COPY_AND_ASSIGN(PendingGetPrintersRequests);
};
// Keeps track of pending chrome.printerProvider.onGetCapabilityRequested
// requests for an extension.
class PendingGetCapabilityRequests {
public:
PendingGetCapabilityRequests();
~PendingGetCapabilityRequests();
// 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 GetCapabilityCallback& callback);
// Completes the request with the provided request id. It runs the request
// callback and removes the request from the set.
bool Complete(int request_id, const base::DictionaryValue& result);
// Runs all pending callbacks with empty capability value and clears the
// set of pending requests.
void FailAll();
private:
int last_request_id_;
std::map<int, GetCapabilityCallback> pending_requests_;
};
// Keeps track of pending chrome.printerProvider.ontPrintRequested requests
// for an extension.
class PendingPrintRequests {
public:
PendingPrintRequests();
~PendingPrintRequests();
// 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 PrintCallback& callback);
// Completes the request with the provided request id. It runs the request
// callback and removes the request from the set.
bool Complete(int request_id, bool success, const std::string& result);
// Runs all pending callbacks with ERROR_FAILED and clears the set of
// pending requests.
void FailAll();
private:
int last_request_id_;
std::map<int, PrintCallback> pending_requests_;
};
// BrowserContextKeyedAPI implementation.
static const bool kServiceRedirectedInIncognito = true;
static const char* service_name() { return "PrinterProvider"; }
// PrinterProviderInternalAPIObserver implementation:
void OnGetPrintersResult(
const Extension* extension,
int request_id,
const PrinterProviderInternalAPIObserver::PrinterInfoVector& result)
override;
void OnGetCapabilityResult(const Extension* extension,
int request_id,
const base::DictionaryValue& result) override;
void OnPrintResult(
const Extension* extension,
int request_id,
core_api::printer_provider_internal::PrintError error) override;
// ExtensionRegistryObserver implementation:
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) override;
// Called before chrome.printerProvider.onGetPrintersRequested event is
// dispatched to an extension. It returns whether the extension is interested
// in the event. If the extension listens to the event, it's added to the set
// of |request| sources. |request| is |GetPrintersRequest| object associated
// with the event.
bool WillRequestPrinters(int request_id,
content::BrowserContext* browser_context,
const Extension* extension,
base::ListValue* args);
content::BrowserContext* browser_context_;
PendingGetPrintersRequests pending_get_printers_requests_;
std::map<std::string, PendingPrintRequests> pending_print_requests_;
std::map<std::string, PendingGetCapabilityRequests>
pending_capability_requests_;
ScopedObserver<PrinterProviderInternalAPI, PrinterProviderInternalAPIObserver>
internal_api_observer_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPI);
virtual void DispatchPrintRequested(const PrinterProviderPrintJob& job,
const PrintCallback& callback) = 0;
};
template <>
void BrowserContextKeyedAPIFactory<
PrinterProviderAPI>::DeclareFactoryDependencies();
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/api/printer_provider/printer_provider_api_factory.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "extensions/browser/api/printer_provider/printer_provider_api.h"
#include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h"
#include "extensions/browser/extension_registry_factory.h"
#include "extensions/browser/extensions_browser_client.h"
namespace {
static base::LazyInstance<extensions::PrinterProviderAPIFactory> g_api_factory =
LAZY_INSTANCE_INITIALIZER;
} // namespace
namespace extensions {
// static
PrinterProviderAPIFactory* PrinterProviderAPIFactory::GetInstance() {
return g_api_factory.Pointer();
}
PrinterProviderAPI* PrinterProviderAPIFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<PrinterProviderAPI*>(
GetServiceForBrowserContext(context, true));
}
PrinterProviderAPIFactory::PrinterProviderAPIFactory()
: BrowserContextKeyedServiceFactory(
"PrinterProviderAPI",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
DependsOn(PrinterProviderInternalAPI::GetFactoryInstance());
DependsOn(ExtensionRegistryFactory::GetInstance());
}
PrinterProviderAPIFactory::~PrinterProviderAPIFactory() {
}
KeyedService* PrinterProviderAPIFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return PrinterProviderAPI::Create(context);
}
content::BrowserContext* PrinterProviderAPIFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
}
} // namespace extensions
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_FACTORY_H_
#define EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_FACTORY_H_
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class KeyedService;
namespace content {
class BrowserContext;
}
namespace extensions {
class PrinterProviderAPI;
}
namespace extensions {
// Factory for PrinterProviderAPI.
class PrinterProviderAPIFactory : public BrowserContextKeyedServiceFactory {
public:
static PrinterProviderAPIFactory* GetInstance();
PrinterProviderAPI* GetForBrowserContext(content::BrowserContext* context);
private:
friend struct base::DefaultLazyInstanceTraits<PrinterProviderAPIFactory>;
PrinterProviderAPIFactory();
~PrinterProviderAPIFactory() override;
// BrowserContextKeyedServiceFactory implementation:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPIFactory);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_FACTORY_H_
......@@ -8,6 +8,8 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "extensions/browser/api/printer_provider/printer_provider_api.h"
#include "extensions/browser/api/printer_provider/printer_provider_api_factory.h"
#include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/shell/test/shell_apitest.h"
......@@ -18,6 +20,7 @@
namespace {
using extensions::PrinterProviderAPI;
using extensions::PrinterProviderAPIFactory;
// Callback for PrinterProviderAPI::DispatchGetPrintersRequested calls.
// It appends items in |printers| to |*printers_out|. If |done| is set, it runs
......@@ -69,14 +72,14 @@ class PrinterProviderApiTest : public extensions::ShellApiTest {
void StartGetPrintersRequest(
const PrinterProviderAPI::GetPrintersCallback& callback) {
PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context())
PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context())
->DispatchGetPrintersRequested(callback);
}
void StartPrintRequest(const std::string& extension_id,
const PrinterProviderAPI::PrintCallback& callback) {
PrinterProviderAPI::PrintJob job;
extensions::PrinterProviderPrintJob job;
job.printer_id = extension_id + ":printer_id";
job.ticket_json = "{}";
job.content_type = "content_type";
......@@ -84,16 +87,16 @@ class PrinterProviderApiTest : public extensions::ShellApiTest {
job.document_bytes =
new base::RefCountedBytes(kDocumentBytes, arraysize(kDocumentBytes));
PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context())
PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context())
->DispatchPrintRequested(job, callback);
}
void StartCapabilityRequest(
const std::string& extension_id,
const PrinterProviderAPI::GetCapabilityCallback& callback) {
PrinterProviderAPI::GetFactoryInstance()
->Get(browser_context())
PrinterProviderAPIFactory::GetInstance()
->GetForBrowserContext(browser_context())
->DispatchGetCapabilityRequested(extension_id + ":printer_id",
callback);
}
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
namespace extensions {
PrinterProviderPrintJob::PrinterProviderPrintJob() {
}
PrinterProviderPrintJob::~PrinterProviderPrintJob() {
}
} // namespace extensions
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_PRINT_JOB_H_
#define EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_PRINT_JOB_H_
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
namespace extensions {
// Struct describing print job that should be forwarded to an extension via
// chrome.printerProvider.onPrintRequested event.
struct PrinterProviderPrintJob {
PrinterProviderPrintJob();
~PrinterProviderPrintJob();
// The id of the printer that should handle the print job. The id is
// formatted as <extension_id>:<printer_id>, where <extension_id> is the
// id of the extension that manages the printer, and <printer_id> is
// the the printer's id within the extension (as reported via
// chrome.printerProvider.onGetPrintersRequested event callback).
std::string printer_id;
// The print job ticket.
std::string ticket_json;
// Content type of the document that should be printed.
std::string content_type;
// The document data that should be printed.
scoped_refptr<base::RefCountedMemory> document_bytes;
private:
DISALLOW_COPY_AND_ASSIGN(PrinterProviderPrintJob);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_PRINT_JOB_H_
......@@ -387,6 +387,10 @@
'browser/api/power/power_api_manager.h',
'browser/api/printer_provider/printer_provider_api.cc',
'browser/api/printer_provider/printer_provider_api.h',
'browser/api/printer_provider/printer_provider_api_factory.cc',
'browser/api/printer_provider/printer_provider_api_factory.h',
'browser/api/printer_provider/printer_provider_print_job.cc',
'browser/api/printer_provider/printer_provider_print_job.h',
'browser/api/printer_provider_internal/printer_provider_internal_api.cc',
'browser/api/printer_provider_internal/printer_provider_internal_api.h',
'browser/api/printer_provider_internal/printer_provider_internal_api_observer.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment