summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authortbarzic <tbarzic@chromium.org>2015-01-21 16:43:33 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-22 00:44:34 +0000
commit44f4c2fef4f1c0e86977a161459f4b067abf6af6 (patch)
treeeb26f562347eb59fe6fa988bec61c3b0ce5028cb /extensions
parente53409112ade857d53896ee0891d25a0f692ae3c (diff)
downloadchromium_src-44f4c2fef4f1c0e86977a161459f4b067abf6af6.zip
chromium_src-44f4c2fef4f1c0e86977a161459f4b067abf6af6.tar.gz
chromium_src-44f4c2fef4f1c0e86977a161459f4b067abf6af6.tar.bz2
Hook up chrome.printerProvider.onPrintRequested
This adds PrinterProviderAPI service which implements logic for dispatching onPrintRequested event, and keeps track of pending event callbacks. Adds PrinterProviderInternalAPI service and PrinterProviderInternalAPIObserver. The internal API service keeps observer list, which gets notified when printerProviderInternal API functions get called. PrinterProviderAPI observes PrinterProviderInternalAPI service for when print request result is reported, and runs the appropriate callback. The callback is identified by the request_id param passed to the internal API function (whose value is the one passed to chrome.printerProvider event when it's dispatched). BUG=408772 Review URL: https://codereview.chromium.org/853263002 Cr-Commit-Position: refs/heads/master@{#312506}
Diffstat (limited to 'extensions')
-rw-r--r--extensions/browser/BUILD.gn3
-rw-r--r--extensions/browser/api/printer_provider/OWNERS2
-rw-r--r--extensions/browser/api/printer_provider/printer_provider_api.cc141
-rw-r--r--extensions/browser/api/printer_provider/printer_provider_api.h131
-rw-r--r--extensions/browser/api/printer_provider/printer_provider_apitest.cc131
-rw-r--r--extensions/browser/api/printer_provider_internal/printer_provider_internal_api.cc44
-rw-r--r--extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h45
-rw-r--r--extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h33
-rw-r--r--extensions/extensions.gyp3
-rw-r--r--extensions/shell/app_shell.gyp1
-rw-r--r--extensions/test/data/api_test/printer_provider/request_print/manifest.json14
-rw-r--r--extensions/test/data/api_test/printer_provider/request_print/test.js47
12 files changed, 595 insertions, 0 deletions
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index a04436b..e5312b5 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -172,8 +172,11 @@ source_set("browser") {
"api/power/power_api.h",
"api/power/power_api_manager.cc",
"api/power/power_api_manager.h",
+ "api/printer_provider/printer_provider_api.cc",
+ "api/printer_provider/printer_provider_api.h",
"api/printer_provider_internal/printer_provider_internal_api.cc",
"api/printer_provider_internal/printer_provider_internal_api.h",
+ "api/printer_provider_internal/printer_provider_internal_api_observer.h",
"api/runtime/runtime_api.cc",
"api/runtime/runtime_api.h",
"api/runtime/runtime_api_delegate.cc",
diff --git a/extensions/browser/api/printer_provider/OWNERS b/extensions/browser/api/printer_provider/OWNERS
new file mode 100644
index 0000000..0fa42c6
--- /dev/null
+++ b/extensions/browser/api/printer_provider/OWNERS
@@ -0,0 +1,2 @@
+tbarzic@chromium.org
+vitalybuka@chromium.org
diff --git a/extensions/browser/api/printer_provider/printer_provider_api.cc b/extensions/browser/api/printer_provider/printer_provider_api.cc
new file mode 100644
index 0000000..8389f74
--- /dev/null
+++ b/extensions/browser/api/printer_provider/printer_provider_api.cc
@@ -0,0 +1,141 @@
+// 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.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+#include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/common/api/printer_provider.h"
+#include "extensions/common/api/printer_provider_internal.h"
+#include "extensions/common/extension.h"
+
+namespace extensions {
+
+namespace {
+
+static base::LazyInstance<BrowserContextKeyedAPIFactory<PrinterProviderAPI>>
+ g_api_factory = LAZY_INSTANCE_INITIALIZER;
+
+PrinterProviderAPI::PrintError APIPrintErrorToInternalType(
+ core_api::printer_provider_internal::PrintError error) {
+ switch (error) {
+ case core_api::printer_provider_internal::PRINT_ERROR_NONE:
+ // The PrintError parameter is not set, which implies an error.
+ return PrinterProviderAPI::PRINT_ERROR_FAILED;
+ case core_api::printer_provider_internal::PRINT_ERROR_OK:
+ return PrinterProviderAPI::PRINT_ERROR_NONE;
+ case core_api::printer_provider_internal::PRINT_ERROR_FAILED:
+ return PrinterProviderAPI::PRINT_ERROR_FAILED;
+ case core_api::printer_provider_internal::PRINT_ERROR_INVALID_TICKET:
+ return PrinterProviderAPI::PRINT_ERROR_INVALID_TICKET;
+ case core_api::printer_provider_internal::PRINT_ERROR_INVALID_DATA:
+ return PrinterProviderAPI::PRINT_ERROR_INVALID_DATA;
+ }
+ return PrinterProviderAPI::PRINT_ERROR_FAILED;
+}
+
+} // namespace
+
+PrinterProviderAPI::PrintJob::PrintJob() {
+}
+
+PrinterProviderAPI::PrintJob::~PrintJob() {
+}
+
+// static
+BrowserContextKeyedAPIFactory<PrinterProviderAPI>*
+PrinterProviderAPI::GetFactoryInstance() {
+ return g_api_factory.Pointer();
+}
+
+PrinterProviderAPI::PrinterProviderAPI(content::BrowserContext* browser_context)
+ : browser_context_(browser_context), internal_api_observer_(this) {
+ internal_api_observer_.Add(
+ PrinterProviderInternalAPI::GetFactoryInstance()->Get(browser_context));
+}
+
+PrinterProviderAPI::~PrinterProviderAPI() {
+}
+
+void PrinterProviderAPI::DispatchPrintRequested(
+ const std::string& extension_id,
+ const PrinterProviderAPI::PrintJob& job,
+ const PrinterProviderAPI::PrintCallback& callback) {
+ EventRouter* event_router = EventRouter::Get(browser_context_);
+ if (!event_router->ExtensionHasEventListener(
+ extension_id,
+ core_api::printer_provider::OnPrintRequested::kEventName)) {
+ callback.Run(PRINT_ERROR_FAILED);
+ return;
+ }
+
+ core_api::printer_provider::PrintJob print_job;
+ print_job.printer_id = job.printer_id;
+ print_job.content_type = job.content_type;
+ print_job.document =
+ std::vector<char>(job.document_bytes.begin(), job.document_bytes.end());
+
+ int request_id = pending_print_requests_[extension_id].Add(callback);
+
+ 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(print_job.ToValue().release());
+ scoped_ptr<Event> event(
+ new Event(core_api::printer_provider::OnPrintRequested::kEventName,
+ internal_args.Pass()));
+
+ event_router->DispatchEventToExtension(extension_id, event.Pass());
+}
+
+PrinterProviderAPI::PendingPrintRequests::PendingPrintRequests()
+ : last_request_id_(0) {
+}
+
+PrinterProviderAPI::PendingPrintRequests::~PendingPrintRequests() {
+}
+
+int PrinterProviderAPI::PendingPrintRequests::Add(
+ const PrinterProviderAPI::PrintCallback& callback) {
+ pending_requests_.insert(std::make_pair(++last_request_id_, callback));
+ return last_request_id_;
+}
+
+bool PrinterProviderAPI::PendingPrintRequests::Complete(int request_id,
+ PrintError 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(response);
+ return true;
+}
+
+void PrinterProviderAPI::OnPrintResult(
+ const Extension* extension,
+ int request_id,
+ core_api::printer_provider_internal::PrintError error) {
+ pending_print_requests_[extension->id()].Complete(
+ request_id, APIPrintErrorToInternalType(error));
+}
+
+template <>
+void BrowserContextKeyedAPIFactory<
+ PrinterProviderAPI>::DeclareFactoryDependencies() {
+ DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
+ DependsOn(PrinterProviderInternalAPI::GetFactoryInstance());
+}
+
+} // namespace extensions
diff --git a/extensions/browser/api/printer_provider/printer_provider_api.h b/extensions/browser/api/printer_provider/printer_provider_api.h
new file mode 100644
index 0000000..5d2a28c
--- /dev/null
+++ b/extensions/browser/api/printer_provider/printer_provider_api.h
@@ -0,0 +1,131 @@
+// 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_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/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"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class Extension;
+class PrinterProviderInternalAPI;
+}
+
+namespace extensions {
+
+// Implements chrome.printerProvider API events.
+class PrinterProviderAPI : public BrowserContextKeyedAPI,
+ public PrinterProviderInternalAPIObserver {
+ public:
+ // Status returned by chrome.printerProvider.onPrintRequested event.
+ enum PrintError {
+ PRINT_ERROR_NONE,
+ PRINT_ERROR_FAILED,
+ PRINT_ERROR_INVALID_TICKET,
+ PRINT_ERROR_INVALID_DATA
+ };
+
+ // 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. This identifies
+ // a printer within an extension and is provided by the extension 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.
+ std::string document_bytes;
+ };
+
+ using PrintCallback = base::Callback<void(PrintError)>;
+
+ static BrowserContextKeyedAPIFactory<PrinterProviderAPI>*
+ GetFactoryInstance();
+
+ explicit PrinterProviderAPI(content::BrowserContext* browser_context);
+ ~PrinterProviderAPI() override;
+
+ // It dispatches chrome.printerProvider.onPrintRequested event to the
+ // extension with id |extension_id| with the provided print job.
+ // |callback| is passed the print status returned by the extension, and it
+ // must not be null.
+ void DispatchPrintRequested(const std::string& extension_id,
+ const PrintJob& job,
+ const PrintCallback& callback);
+
+ private:
+ friend class BrowserContextKeyedAPIFactory<PrinterProviderAPI>;
+
+ // 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, PrintError result);
+
+ private:
+ int last_request_id_;
+ std::map<int, PrintCallback> pending_requests_;
+ };
+
+ // BrowserContextKeyedAPI implementation.
+ static const char* service_name() { return "PrinterProvider"; }
+
+ // PrinterProviderInternalAPIObserver implementation:
+ void OnPrintResult(
+ const Extension* extension,
+ int request_id,
+ core_api::printer_provider_internal::PrintError error) override;
+
+ content::BrowserContext* browser_context_;
+
+ std::map<std::string, PendingPrintRequests> pending_print_requests_;
+
+ ScopedObserver<PrinterProviderInternalAPI, PrinterProviderInternalAPIObserver>
+ internal_api_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrinterProviderAPI);
+};
+
+template <>
+void BrowserContextKeyedAPIFactory<
+ PrinterProviderAPI>::DeclareFactoryDependencies();
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_PRINTER_PROVIDER_API_H_
diff --git a/extensions/browser/api/printer_provider/printer_provider_apitest.cc b/extensions/browser/api/printer_provider/printer_provider_apitest.cc
new file mode 100644
index 0000000..ae8056c
--- /dev/null
+++ b/extensions/browser/api/printer_provider/printer_provider_apitest.cc
@@ -0,0 +1,131 @@
+// 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 "base/bind.h"
+#include "base/run_loop.h"
+#include "extensions/browser/api/printer_provider/printer_provider_api.h"
+#include "extensions/common/extension.h"
+#include "extensions/shell/test/shell_apitest.h"
+#include "extensions/test/extension_test_message_listener.h"
+#include "extensions/test/result_catcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using extensions::PrinterProviderAPI;
+
+// Callback for PrinterProviderAPI::DispatchPrintRequested calls.
+// It copies |value| to |*result| and runs |callback|.
+void RecordPrintErrorAndRunCallback(PrinterProviderAPI::PrintError* result,
+ const base::Closure& callback,
+ PrinterProviderAPI::PrintError value) {
+ *result = value;
+ if (!callback.is_null())
+ callback.Run();
+}
+
+// Tests for chrome.printerProvider API.
+class PrinterProviderApiTest : public extensions::ShellApiTest {
+ public:
+ PrinterProviderApiTest() {}
+ ~PrinterProviderApiTest() override {}
+
+ void StartPrintRequest(const std::string& extension_id,
+ const PrinterProviderAPI::PrintCallback& callback) {
+ PrinterProviderAPI::PrintJob job;
+ job.printer_id = "printer_id";
+ job.ticket_json = "{}";
+ job.content_type = "content_type";
+ job.document_bytes = "bytes";
+
+ PrinterProviderAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->DispatchPrintRequested(extension_id, job, callback);
+ }
+
+ // Loads chrome.printerProvider test app and initializes is for test
+ // |test_param|.
+ // When the app's background page is loaded, the app will send 'loaded'
+ // message. As a response to the message it will expect string message
+ // specifying the test that should be run. When the app initializes its state
+ // (e.g. registers listener for a chrome.printerProvider event) it will send
+ // message 'ready', at which point the test may be started.
+ // If the app is successfully initialized, |*extension_id_out| will be set to
+ // the loaded extension's id, otherwise it will remain unchanged.
+ void InitializePrinterProviderTestApp(const std::string& app_path,
+ const std::string& test_param,
+ std::string* extension_id_out) {
+ ExtensionTestMessageListener loaded_listener("loaded", true);
+ ExtensionTestMessageListener ready_listener("ready", false);
+
+ const extensions::Extension* extension = LoadApp(app_path);
+ ASSERT_TRUE(extension);
+ const std::string extension_id = extension->id();
+
+ loaded_listener.set_extension_id(extension_id);
+ ready_listener.set_extension_id(extension_id);
+
+ ASSERT_TRUE(loaded_listener.WaitUntilSatisfied());
+
+ loaded_listener.Reply(test_param);
+
+ ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
+
+ *extension_id_out = extension_id;
+ }
+
+ // Runs a test for chrome.printerProvider.onPrintRequested event.
+ // |test_param|: The test that should be run.
+ // |expected_result|: The print result the app is expected to report.
+ void RunPrintRequestTestApp(const std::string& test_param,
+ PrinterProviderAPI::PrintError expected_result) {
+ extensions::ResultCatcher catcher;
+
+ std::string extension_id;
+ InitializePrinterProviderTestApp("api_test/printer_provider/request_print",
+ test_param, &extension_id);
+ if (extension_id.empty())
+ return;
+
+ base::RunLoop run_loop;
+ PrinterProviderAPI::PrintError print_result;
+ StartPrintRequest(extension_id,
+ base::Bind(&RecordPrintErrorAndRunCallback, &print_result,
+ run_loop.QuitClosure()));
+
+ ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+
+ run_loop.Run();
+ EXPECT_EQ(expected_result, print_result);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PrinterProviderApiTest);
+};
+
+IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobSuccess) {
+ RunPrintRequestTestApp("OK", PrinterProviderAPI::PRINT_ERROR_NONE);
+}
+
+IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobAsyncSuccess) {
+ RunPrintRequestTestApp("ASYNC_RESPONSE",
+ PrinterProviderAPI::PRINT_ERROR_NONE);
+}
+
+IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobFailed) {
+ RunPrintRequestTestApp("INVALID_TICKET",
+ PrinterProviderAPI::PRINT_ERROR_INVALID_TICKET);
+}
+
+IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, NoPrintEventListener) {
+ RunPrintRequestTestApp("NO_LISTENER", PrinterProviderAPI::PRINT_ERROR_FAILED);
+}
+
+IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest,
+ PrintRequestInvalidCallbackParam) {
+ RunPrintRequestTestApp("INVALID_VALUE",
+ PrinterProviderAPI::PRINT_ERROR_FAILED);
+}
+
+} // namespace
diff --git a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.cc b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.cc
index 2f344a5..729f361 100644
--- a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.cc
+++ b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.cc
@@ -4,12 +4,53 @@
#include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h"
+#include "base/lazy_instance.h"
+#include "extensions/common/api/printer_provider.h"
#include "extensions/common/api/printer_provider_internal.h"
namespace internal_api = extensions::core_api::printer_provider_internal;
namespace extensions {
+namespace {
+
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<PrinterProviderInternalAPI>> g_api_factory =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// static
+BrowserContextKeyedAPIFactory<PrinterProviderInternalAPI>*
+PrinterProviderInternalAPI::GetFactoryInstance() {
+ return g_api_factory.Pointer();
+}
+
+PrinterProviderInternalAPI::PrinterProviderInternalAPI(
+ content::BrowserContext* browser_context) {
+}
+
+PrinterProviderInternalAPI::~PrinterProviderInternalAPI() {
+}
+
+void PrinterProviderInternalAPI::AddObserver(
+ PrinterProviderInternalAPIObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void PrinterProviderInternalAPI::RemoveObserver(
+ PrinterProviderInternalAPIObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void PrinterProviderInternalAPI::NotifyPrintResult(
+ const Extension* extension,
+ int request_id,
+ core_api::printer_provider_internal::PrintError error) {
+ FOR_EACH_OBSERVER(PrinterProviderInternalAPIObserver, observers_,
+ OnPrintResult(extension, request_id, error));
+}
+
PrinterProviderInternalReportPrintResultFunction::
PrinterProviderInternalReportPrintResultFunction() {
}
@@ -24,6 +65,9 @@ PrinterProviderInternalReportPrintResultFunction::Run() {
internal_api::ReportPrintResult::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
+ PrinterProviderInternalAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->NotifyPrintResult(extension(), params->request_id, params->error);
return RespondNow(NoArguments());
}
diff --git a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
index d24f0bb..bf04aa7 100644
--- a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
+++ b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
@@ -5,10 +5,55 @@
#ifndef EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_INTERNAL_PRINTER_PROVIDER_INTERNAL_API_H_
#define EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_INTERNAL_PRINTER_PROVIDER_INTERNAL_API_H_
+#include "base/macros.h"
+#include "base/observer_list.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_function.h"
+#include "extensions/common/api/printer_provider_internal.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class Extension;
+}
namespace extensions {
+// Internal API instance. Primarily used to enable observers to watch for when
+// printerProviderInternal API functions are called.
+class PrinterProviderInternalAPI : public BrowserContextKeyedAPI {
+ public:
+ static BrowserContextKeyedAPIFactory<PrinterProviderInternalAPI>*
+ GetFactoryInstance();
+
+ explicit PrinterProviderInternalAPI(content::BrowserContext* browser_context);
+ ~PrinterProviderInternalAPI() override;
+
+ void AddObserver(PrinterProviderInternalAPIObserver* observer);
+ void RemoveObserver(PrinterProviderInternalAPIObserver* observer);
+
+ private:
+ friend class BrowserContextKeyedAPIFactory<PrinterProviderInternalAPI>;
+ friend class PrinterProviderInternalReportPrintResultFunction;
+
+ // Notifies observers that a printerProvider.onPrintRequested callback has
+ // been called. Called from
+ // |PrinterProviderInternalReportPrintResultFunction|.
+ void NotifyPrintResult(const Extension* extension,
+ int request_id,
+ core_api::printer_provider_internal::PrintError error);
+
+ // BrowserContextKeyedAPI implementation.
+ static const char* service_name() { return "PrinterProviderInternal"; }
+
+ ObserverList<PrinterProviderInternalAPIObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrinterProviderInternalAPI);
+};
+
class PrinterProviderInternalReportPrintResultFunction
: public UIThreadExtensionFunction {
public:
diff --git a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h
new file mode 100644
index 0000000..8b5aecf
--- /dev/null
+++ b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h
@@ -0,0 +1,33 @@
+// 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_INTERNAL_PRINTER_PROVIDER_INTERNAL_API_OBSERVER_H_
+#define EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_INTERNAL_PRINTER_PROVIDER_INTERNAL_API_OBSERVER_H_
+
+#include "extensions/common/api/printer_provider_internal.h"
+
+namespace extensions {
+
+class Extension;
+
+// Interface for observing chrome.printerProviderInternal API function calls.
+class PrinterProviderInternalAPIObserver {
+ public:
+ // Used by chrome.printerProviderInternal API to report
+ // chrome.printerProvider.onPrintRequested result returned by the extension
+ // |extension|.
+ // |request_id| is the request id passed to the original
+ // chrome.printerProvider.onPrintRequested event.
+ virtual void OnPrintResult(
+ const Extension* extension,
+ int request_id,
+ core_api::printer_provider_internal::PrintError error) = 0;
+
+ protected:
+ virtual ~PrinterProviderInternalAPIObserver() {}
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_PRINTER_PROVIDER_INTERNAL_PRINTER_PROVIDER_INTERNAL_API_OBSERVER_H_
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 38854c3..cac677e 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -462,8 +462,11 @@
'browser/api/power/power_api.h',
'browser/api/power/power_api_manager.cc',
'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_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',
'browser/api/runtime/runtime_api.cc',
'browser/api/runtime/runtime_api.h',
'browser/api/runtime/runtime_api_delegate.cc',
diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp
index ed97b1b..f8ef6ef 100644
--- a/extensions/shell/app_shell.gyp
+++ b/extensions/shell/app_shell.gyp
@@ -315,6 +315,7 @@
'../browser/api/audio/audio_apitest.cc',
'../browser/api/dns/dns_apitest.cc',
'../browser/api/hid/hid_apitest.cc',
+ '../browser/api/printer_provider/printer_provider_apitest.cc',
'../browser/api/socket/socket_apitest.cc',
'../browser/api/sockets_tcp/sockets_tcp_apitest.cc',
'../browser/api/sockets_tcp_server/sockets_tcp_server_apitest.cc',
diff --git a/extensions/test/data/api_test/printer_provider/request_print/manifest.json b/extensions/test/data/api_test/printer_provider/request_print/manifest.json
new file mode 100644
index 0000000..5d1fc90
--- /dev/null
+++ b/extensions/test/data/api_test/printer_provider/request_print/manifest.json
@@ -0,0 +1,14 @@
+{
+ "name": "Test printer provider",
+ "description": "Test extension for chrome.printerProvider.onPrintRequested event",
+ "manifest_version": 2,
+ "version": "0.1",
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ },
+ "permissions": [
+ "printerProvider"
+ ]
+}
diff --git a/extensions/test/data/api_test/printer_provider/request_print/test.js b/extensions/test/data/api_test/printer_provider/request_print/test.js
new file mode 100644
index 0000000..c0d0a4f
--- /dev/null
+++ b/extensions/test/data/api_test/printer_provider/request_print/test.js
@@ -0,0 +1,47 @@
+// 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.
+
+chrome.test.sendMessage('loaded', function(test) {
+ chrome.test.runTests([function printTest() {
+ if (test == 'NO_LISTENER') {
+ chrome.test.sendMessage('ready');
+ chrome.test.succeed();
+ return;
+ }
+
+ chrome.printerProvider.onPrintRequested.addListener(function(job,
+ callback) {
+ chrome.test.assertFalse(!!chrome.printerProviderInternal);
+ chrome.test.assertTrue(!!job);
+
+ if (test == 'ASYNC_RESPONSE') {
+ setTimeout(callback.bind(null, 'OK'), 0);
+ chrome.test.succeed();
+ return;
+ }
+
+ if (test == 'INVALID_VALUE') {
+ chrome.test.assertThrows(
+ callback,
+ ['XXX'],
+ 'Invalid value for argument 1. ' +
+ 'Value must be one of: ' +
+ '[OK, FAILED, INVALID_TICKET, INVALID_DATA].');
+ } else {
+ chrome.test.assertTrue(test == 'OK' || test == 'FAILED' ||
+ test == 'INVALID_TICKET' || test == 'INVALID_DATA');
+ callback(test);
+ }
+
+ chrome.test.assertThrows(
+ callback,
+ [test],
+ 'Event callback must not be called more than once.');
+
+ chrome.test.succeed();
+ });
+
+ chrome.test.sendMessage('ready');
+ }]);
+});