summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorsudarsana.nagineni <sudarsana.nagineni@intel.com>2015-02-09 06:12:47 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-09 14:13:16 +0000
commitdc80f4b7a1e17819a54b32a246f40766335cdff0 (patch)
tree1cf64907a8785a947bb69677e6c77562896a3fe1 /extensions
parent0d3f0b88b3700e1979d0b7af999269e58261c9a2 (diff)
downloadchromium_src-dc80f4b7a1e17819a54b32a246f40766335cdff0.zip
chromium_src-dc80f4b7a1e17819a54b32a246f40766335cdff0.tar.gz
chromium_src-dc80f4b7a1e17819a54b32a246f40766335cdff0.tar.bz2
Move chrome.documentScan API to extensions/.
Move the chrome.documentScan extension API from chrome/ to extensions/. BUG=455695 Review URL: https://codereview.chromium.org/899523004 Cr-Commit-Position: refs/heads/master@{#315293}
Diffstat (limited to 'extensions')
-rw-r--r--extensions/browser/BUILD.gn7
-rw-r--r--extensions/browser/api/document_scan/DEPS3
-rw-r--r--extensions/browser/api/document_scan/document_scan_api.cc124
-rw-r--r--extensions/browser/api/document_scan/document_scan_api.h54
-rw-r--r--extensions/browser/api/document_scan/document_scan_api_unittest.cc120
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface.cc25
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface.h59
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface_chromeos.cc131
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface_chromeos.h48
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc127
-rw-r--r--extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc43
-rw-r--r--extensions/browser/api/document_scan/mock_document_scan_interface.cc19
-rw-r--r--extensions/browser/api/document_scan/mock_document_scan_interface.h36
-rw-r--r--extensions/common/api/_api_features.json5
-rw-r--r--extensions/common/api/_permission_features.json4
-rw-r--r--extensions/common/api/document_scan.idl37
-rw-r--r--extensions/common/api/schemas.gypi1
-rw-r--r--extensions/common/permissions/extensions_api_permissions.cc5
-rw-r--r--extensions/extensions.gyp11
-rw-r--r--extensions/extensions_tests.gyp8
20 files changed, 866 insertions, 1 deletions
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index b29dea2..e8c1b5a 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -141,6 +141,10 @@ source_set("browser") {
"api/dns/dns_api.h",
"api/dns/host_resolver_wrapper.cc",
"api/dns/host_resolver_wrapper.h",
+ "api/document_scan/document_scan_api.cc",
+ "api/document_scan/document_scan_api.h",
+ "api/document_scan/document_scan_interface.cc",
+ "api/document_scan/document_scan_interface.h",
"api/execute_code_function.cc",
"api/execute_code_function.h",
"api/extensions_api_client.cc",
@@ -581,6 +585,7 @@ source_set("browser") {
"api/diagnostics/diagnostics_api.cc",
"api/diagnostics/diagnostics_api.h",
"api/diagnostics/diagnostics_api_chromeos.cc",
+ "api/document_scan/document_scan_interface_chromeos.cc",
"api/networking_config/networking_config_api.cc",
"api/networking_config/networking_config_api.h",
"api/networking_config/networking_config_service.cc",
@@ -593,6 +598,8 @@ source_set("browser") {
"api/vpn_provider/vpn_service.h",
"api/vpn_provider/vpn_service_factory.h",
]
+ } else {
+ sources += [ "api/document_scan/document_scan_interface_nonchromeos.cc" ]
}
if (is_desktop_linux) {
diff --git a/extensions/browser/api/document_scan/DEPS b/extensions/browser/api/document_scan/DEPS
new file mode 100644
index 0000000..a0e2dba
--- /dev/null
+++ b/extensions/browser/api/document_scan/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/cros_system_api",
+]
diff --git a/extensions/browser/api/document_scan/document_scan_api.cc b/extensions/browser/api/document_scan/document_scan_api.cc
new file mode 100644
index 0000000..464b7db
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_api.cc
@@ -0,0 +1,124 @@
+// Copyright 2014 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/document_scan/document_scan_api.h"
+
+#include <algorithm>
+
+#include "content/public/browser/browser_thread.h"
+#include "extensions/browser/extension_system.h"
+
+using content::BrowserThread;
+
+namespace {
+
+const char kScannerNotAvailable[] = "Scanner not available";
+const char kUserGestureRequiredError[] =
+ "User gesture required to perform scan";
+
+} // namespace
+
+namespace extensions {
+
+namespace core_api {
+
+DocumentScanScanFunction::DocumentScanScanFunction()
+ : document_scan_interface_(DocumentScanInterface::CreateInstance()) {
+}
+
+DocumentScanScanFunction::~DocumentScanScanFunction() {
+}
+
+bool DocumentScanScanFunction::Prepare() {
+ set_work_thread_id(BrowserThread::FILE);
+ params_ = document_scan::Scan::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
+}
+
+void DocumentScanScanFunction::AsyncWorkStart() {
+ if (!user_gesture()) {
+ error_ = kUserGestureRequiredError;
+ AsyncWorkCompleted();
+ return;
+ }
+
+ // Add a reference, which is balanced in OnScannerListReceived to keep the
+ // object around and allow the callback to be invoked.
+ AddRef();
+
+ document_scan_interface_->ListScanners(
+ base::Bind(&DocumentScanScanFunction::OnScannerListReceived,
+ base::Unretained(this)));
+}
+
+void DocumentScanScanFunction::OnScannerListReceived(
+ const std::vector<DocumentScanInterface::ScannerDescription>&
+ scanner_descriptions,
+ const std::string& error) {
+ std::vector<DocumentScanInterface::ScannerDescription>::const_iterator
+ scanner_i = scanner_descriptions.begin();
+
+ // If no |scanner_descriptions| is empty, this is an error. If no
+ // MIME types are specified, the first scanner is chosen. If MIME
+ // types are specified, the first scanner that supports one of these
+ // MIME types is selected.
+ if (params_->options.mime_types) {
+ std::vector<std::string>& mime_types = *params_->options.mime_types.get();
+ for (; scanner_i != scanner_descriptions.end(); ++scanner_i) {
+ if (std::find(mime_types.begin(), mime_types.end(),
+ scanner_i->image_mime_type) != mime_types.end()) {
+ break;
+ }
+ }
+ }
+
+ if (scanner_i == scanner_descriptions.end()) {
+ error_ = kScannerNotAvailable;
+ AsyncWorkCompleted();
+
+ // Balance the AddRef in AsyncWorkStart().
+ Release();
+ return;
+ }
+
+ // TODO(pstew): Call a delegate method here to select a scanner and options.
+
+ document_scan_interface_->Scan(
+ scanner_i->name, DocumentScanInterface::kScanModeColor, 0,
+ base::Bind(&DocumentScanScanFunction::OnResultsReceived,
+ base::Unretained(this)));
+}
+
+void DocumentScanScanFunction::OnResultsReceived(
+ const std::string& scanned_image,
+ const std::string& mime_type,
+ const std::string& error) {
+ // TODO(pstew): Enlist a delegate to display received scan in the UI
+ // and confirm that this scan should be sent to the caller. If this
+ // is a multi-page scan, provide a means for adding additional scanned
+ // images up to the requested limit.
+
+ if (error.empty()) {
+ document_scan::ScanResults scan_results;
+ if (!scanned_image.empty()) {
+ scan_results.data_urls.push_back(scanned_image);
+ }
+ scan_results.mime_type = mime_type;
+ results_ = document_scan::Scan::Results::Create(scan_results);
+ }
+ error_ = error;
+ AsyncWorkCompleted();
+
+ // Balance the AddRef in AsyncWorkStart().
+ Release();
+}
+
+bool DocumentScanScanFunction::Respond() {
+ return error_.empty();
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/document_scan_api.h b/extensions/browser/api/document_scan/document_scan_api.h
new file mode 100644
index 0000000..806d768
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_api.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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_DOCUMENT_SCAN_DOCUMENT_SCAN_API_H_
+#define EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_API_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "extensions/browser/api/async_api_function.h"
+#include "extensions/browser/api/document_scan/document_scan_interface.h"
+#include "extensions/common/api/document_scan.h"
+
+namespace extensions {
+
+namespace core_api {
+
+class DocumentScanScanFunction : public AsyncApiFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("documentScan.scan", DOCUMENT_SCAN_SCAN)
+ DocumentScanScanFunction();
+
+ protected:
+ ~DocumentScanScanFunction() override;
+
+ // AsyncApiFunction:
+ bool Prepare() override;
+ void AsyncWorkStart() override;
+ bool Respond() override;
+
+ private:
+ friend class DocumentScanScanFunctionTest;
+
+ void OnScannerListReceived(
+ const std::vector<DocumentScanInterface::ScannerDescription>&
+ scanner_descriptions,
+ const std::string& error);
+ void OnResultsReceived(const std::string& scanned_image,
+ const std::string& mime_type,
+ const std::string& error);
+
+ scoped_ptr<document_scan::Scan::Params> params_;
+ scoped_ptr<DocumentScanInterface> document_scan_interface_;
+
+ DISALLOW_COPY_AND_ASSIGN(DocumentScanScanFunction);
+};
+
+} // namespace core_api
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_API_H_
diff --git a/extensions/browser/api/document_scan/document_scan_api_unittest.cc b/extensions/browser/api/document_scan/document_scan_api_unittest.cc
new file mode 100644
index 0000000..1c8f597
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_api_unittest.cc
@@ -0,0 +1,120 @@
+// Copyright 2014 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/document_scan/document_scan_api.h"
+
+#include <string>
+#include <vector>
+
+#include "extensions/browser/api/document_scan/mock_document_scan_interface.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/api_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace extensions {
+
+namespace core_api {
+
+// Tests of networking_private_crypto support for Networking Private API.
+class DocumentScanScanFunctionTest : public ApiUnitTest {
+ public:
+ DocumentScanScanFunctionTest()
+ : function_(new DocumentScanScanFunction()),
+ document_scan_interface_(new MockDocumentScanInterface()) {}
+ ~DocumentScanScanFunctionTest() override {}
+
+ void SetUp() override {
+ ApiUnitTest::SetUp();
+ // Passes ownership.
+ function_->document_scan_interface_.reset(document_scan_interface_);
+ }
+
+ protected:
+ std::string RunFunctionAndReturnError(const std::string& args) {
+ function_->set_extension(extension());
+ std::string error = api_test_utils::RunFunctionAndReturnError(
+ function_, args, browser_context(), api_test_utils::NONE);
+ return error;
+ }
+
+ DocumentScanScanFunction* function_;
+ MockDocumentScanInterface* document_scan_interface_; // Owned by function_.
+};
+
+ACTION_P2(InvokeListScannersCallback, scanner_list, error) {
+ ::std::tr1::get<0>(args).Run(scanner_list, error);
+}
+
+ACTION_P3(InvokeScanCallback, data, mime_type, error) {
+ ::std::tr1::get<3>(args).Run(data, mime_type, error);
+}
+
+TEST_F(DocumentScanScanFunctionTest, GestureRequired) {
+ EXPECT_EQ("User gesture required to perform scan",
+ RunFunctionAndReturnError("[{}]"));
+}
+
+TEST_F(DocumentScanScanFunctionTest, NoScanners) {
+ function_->set_user_gesture(true);
+ EXPECT_CALL(*document_scan_interface_, ListScanners(_))
+ .WillOnce(InvokeListScannersCallback(
+ std::vector<DocumentScanInterface::ScannerDescription>(), ""));
+ EXPECT_EQ("Scanner not available", RunFunctionAndReturnError("[{}]"));
+}
+
+TEST_F(DocumentScanScanFunctionTest, NoMatchingScanners) {
+ function_->set_user_gesture(true);
+ std::vector<DocumentScanInterface::ScannerDescription> scanner_list;
+ DocumentScanInterface::ScannerDescription scanner;
+ scanner.image_mime_type = "img/fresco";
+ scanner_list.push_back(scanner);
+ EXPECT_CALL(*document_scan_interface_, ListScanners(_))
+ .WillOnce(InvokeListScannersCallback(scanner_list, ""));
+ EXPECT_EQ(
+ "Scanner not available",
+ RunFunctionAndReturnError("[{\"mimeTypes\": [\"img/silverpoint\"]}]"));
+}
+
+TEST_F(DocumentScanScanFunctionTest, ScanFailure) {
+ function_->set_user_gesture(true);
+ std::vector<DocumentScanInterface::ScannerDescription> scanner_list;
+ DocumentScanInterface::ScannerDescription scanner;
+ const char kMimeType[] = "img/tempera";
+ const char kScannerName[] = "Michelangelo";
+ scanner.name = kScannerName;
+ scanner.image_mime_type = kMimeType;
+ scanner_list.push_back(scanner);
+ EXPECT_CALL(*document_scan_interface_, ListScanners(_))
+ .WillOnce(InvokeListScannersCallback(scanner_list, ""));
+ const char kScanError[] = "Someone ate all the eggs";
+ EXPECT_CALL(*document_scan_interface_, Scan(kScannerName, _, _, _))
+ .WillOnce(InvokeScanCallback("", "", kScanError));
+ EXPECT_EQ(kScanError,
+ RunFunctionAndReturnError("[{\"mimeTypes\": [\"img/tempera\"]}]"));
+}
+
+TEST_F(DocumentScanScanFunctionTest, Success) {
+ std::vector<DocumentScanInterface::ScannerDescription> scanner_list;
+ scanner_list.push_back(DocumentScanInterface::ScannerDescription());
+ EXPECT_CALL(*document_scan_interface_, ListScanners(_))
+ .WillOnce(InvokeListScannersCallback(scanner_list, ""));
+ const char kScanData[] = "A beautiful picture";
+ const char kMimeType[] = "img/encaustic";
+ EXPECT_CALL(*document_scan_interface_, Scan(_, _, _, _))
+ .WillOnce(InvokeScanCallback(kScanData, kMimeType, ""));
+ function_->set_user_gesture(true);
+ scoped_ptr<base::DictionaryValue> result(
+ RunFunctionAndReturnDictionary(function_, "[{}]"));
+ ASSERT_NE(nullptr, result.get());
+ document_scan::ScanResults scan_results;
+ EXPECT_TRUE(document_scan::ScanResults::Populate(*result, &scan_results));
+ EXPECT_THAT(scan_results.data_urls, testing::ElementsAre(kScanData));
+ EXPECT_EQ(kMimeType, scan_results.mime_type);
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/document_scan_interface.cc b/extensions/browser/api/document_scan/document_scan_interface.cc
new file mode 100644
index 0000000..2a599a3
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface.cc
@@ -0,0 +1,25 @@
+// Copyright 2014 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/document_scan/document_scan_interface.h"
+
+namespace extensions {
+
+namespace core_api {
+
+DocumentScanInterface::DocumentScanInterface() {
+}
+
+DocumentScanInterface::~DocumentScanInterface() {
+}
+
+DocumentScanInterface::ScannerDescription::ScannerDescription() {
+}
+
+DocumentScanInterface::ScannerDescription::~ScannerDescription() {
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/document_scan_interface.h b/extensions/browser/api/document_scan/document_scan_interface.h
new file mode 100644
index 0000000..9b8699d
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface.h
@@ -0,0 +1,59 @@
+// Copyright 2014 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_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_H_
+#define EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace extensions {
+
+namespace core_api {
+
+class DocumentScanInterface {
+ public:
+ struct ScannerDescription {
+ ScannerDescription();
+ ~ScannerDescription();
+ std::string name;
+ std::string manufacturer;
+ std::string model;
+ std::string scanner_type;
+ std::string image_mime_type;
+ };
+
+ enum ScanMode { kScanModeColor, kScanModeGray, kScanModeLineart };
+
+ typedef base::Callback<void(
+ const std::vector<ScannerDescription>& scanner_descriptions,
+ const std::string& error)> ListScannersResultsCallback;
+
+ typedef base::Callback<void(const std::string& scanned_image,
+ const std::string& mime_type,
+ const std::string& error)> ScanResultsCallback;
+
+ virtual ~DocumentScanInterface();
+
+ virtual void Scan(const std::string& scanner_name,
+ ScanMode mode,
+ int resolution_dpi,
+ const ScanResultsCallback& callback) = 0;
+ virtual void ListScanners(const ListScannersResultsCallback& callback) = 0;
+
+ // Creates a platform-specific DocumentScanInterface instance.
+ static DocumentScanInterface* CreateInstance();
+
+ protected:
+ DocumentScanInterface();
+};
+
+} // namespace core_api
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_H_
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc b/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
new file mode 100644
index 0000000..b270a3f
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
@@ -0,0 +1,131 @@
+// Copyright 2014 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/document_scan/document_scan_interface_chromeos.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/lorgnette_manager_client.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace {
+
+const char kImageScanFailedError[] = "Image scan failed";
+const char kScannerImageMimeTypePng[] = "image/png";
+const char kPngImageDataUrlPrefix[] = "data:image/png;base64,";
+
+} // namespace
+
+namespace extensions {
+
+namespace core_api {
+
+DocumentScanInterfaceChromeos::DocumentScanInterfaceChromeos()
+ : lorgnette_manager_client_(nullptr) {
+}
+
+DocumentScanInterfaceChromeos::~DocumentScanInterfaceChromeos() {
+}
+
+void DocumentScanInterfaceChromeos::ListScanners(
+ const ListScannersResultsCallback& callback) {
+ GetLorgnetteManagerClient()->ListScanners(
+ base::Bind(&DocumentScanInterfaceChromeos::OnScannerListReceived,
+ base::Unretained(this), callback));
+}
+
+void DocumentScanInterfaceChromeos::OnScannerListReceived(
+ const ListScannersResultsCallback& callback,
+ bool succeeded,
+ const chromeos::LorgnetteManagerClient::ScannerTable& scanners) {
+ std::vector<ScannerDescription> scanner_descriptions;
+ for (const auto& scanner : scanners) {
+ ScannerDescription description;
+ description.name = scanner.first;
+ const auto& entry = scanner.second;
+ auto info_it = entry.find(lorgnette::kScannerPropertyManufacturer);
+ if (info_it != entry.end()) {
+ description.manufacturer = info_it->second;
+ }
+ info_it = entry.find(lorgnette::kScannerPropertyModel);
+ if (info_it != entry.end()) {
+ description.model = info_it->second;
+ }
+ info_it = entry.find(lorgnette::kScannerPropertyType);
+ if (info_it != entry.end()) {
+ description.scanner_type = info_it->second;
+ }
+ description.image_mime_type = kScannerImageMimeTypePng;
+ scanner_descriptions.push_back(description);
+ }
+ const std::string kNoError;
+ callback.Run(scanner_descriptions, kNoError);
+}
+
+void DocumentScanInterfaceChromeos::Scan(const std::string& scanner_name,
+ ScanMode mode,
+ int resolution_dpi,
+ const ScanResultsCallback& callback) {
+ VLOG(1) << "Choosing scanner " << scanner_name;
+ chromeos::LorgnetteManagerClient::ScanProperties properties;
+ switch (mode) {
+ case kScanModeColor:
+ properties.mode = lorgnette::kScanPropertyModeColor;
+ break;
+
+ case kScanModeGray:
+ properties.mode = lorgnette::kScanPropertyModeGray;
+ break;
+
+ case kScanModeLineart:
+ properties.mode = lorgnette::kScanPropertyModeLineart;
+ break;
+ }
+
+ if (resolution_dpi != 0) {
+ properties.resolution_dpi = resolution_dpi;
+ }
+
+ GetLorgnetteManagerClient()->ScanImageToString(
+ scanner_name, properties,
+ base::Bind(&DocumentScanInterfaceChromeos::OnScanCompleted,
+ base::Unretained(this), callback));
+}
+
+void DocumentScanInterfaceChromeos::OnScanCompleted(
+ const ScanResultsCallback& callback,
+ bool succeeded,
+ const std::string& image_data) {
+ VLOG(1) << "ScanImage returns " << succeeded;
+ std::string error_string;
+ if (!succeeded) {
+ error_string = kImageScanFailedError;
+ }
+
+ std::string image_base64;
+ base::Base64Encode(image_data, &image_base64);
+ std::string image_url(std::string(kPngImageDataUrlPrefix) + image_base64);
+
+ callback.Run(image_url, kScannerImageMimeTypePng, error_string);
+}
+
+chromeos::LorgnetteManagerClient*
+DocumentScanInterfaceChromeos::GetLorgnetteManagerClient() {
+ if (!lorgnette_manager_client_) {
+ lorgnette_manager_client_ =
+ chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient();
+ CHECK(lorgnette_manager_client_);
+ }
+ return lorgnette_manager_client_;
+}
+
+// static
+DocumentScanInterface* DocumentScanInterface::CreateInstance() {
+ return new DocumentScanInterfaceChromeos();
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos.h b/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
new file mode 100644
index 0000000..cd50d50
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_CHROMEOS_H_
+#define EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_CHROMEOS_H_
+
+#include "extensions/browser/api/document_scan/document_scan_interface.h"
+#include "chromeos/dbus/lorgnette_manager_client.h"
+
+namespace extensions {
+
+namespace core_api {
+
+class DocumentScanInterfaceChromeos : public DocumentScanInterface {
+ public:
+ DocumentScanInterfaceChromeos();
+ ~DocumentScanInterfaceChromeos() override;
+
+ void ListScanners(const ListScannersResultsCallback& callback) override;
+ void Scan(const std::string& scanner_name,
+ ScanMode mode,
+ int resolution_dpi,
+ const ScanResultsCallback& callback) override;
+
+ private:
+ friend class DocumentScanInterfaceChromeosTest;
+
+ void OnScannerListReceived(
+ const ListScannersResultsCallback& callback,
+ bool succeeded,
+ const chromeos::LorgnetteManagerClient::ScannerTable& scanners);
+ void OnScanCompleted(const ScanResultsCallback& callback,
+ bool succeeded,
+ const std::string& image_data);
+ chromeos::LorgnetteManagerClient* GetLorgnetteManagerClient();
+
+ // Guaranteed to outlive |this|.
+ chromeos::LorgnetteManagerClient* lorgnette_manager_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceChromeos);
+};
+
+} // namespace core_api
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_DOCUMENT_SCAN_INTERFACE_CHROMEOS_H_
diff --git a/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc b/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
new file mode 100644
index 0000000..e34de36
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
@@ -0,0 +1,127 @@
+// Copyright 2014 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/document_scan/document_scan_interface_chromeos.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "chromeos/dbus/mock_lorgnette_manager_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+using testing::_;
+
+namespace extensions {
+
+namespace core_api {
+
+// Tests of networking_private_crypto support for Networking Private API.
+class DocumentScanInterfaceChromeosTest : public testing::Test {
+ public:
+ DocumentScanInterfaceChromeosTest()
+ : client_(new chromeos::MockLorgnetteManagerClient()) {}
+ ~DocumentScanInterfaceChromeosTest() override {}
+
+ void SetUp() override {
+ scan_interface_.lorgnette_manager_client_ = client_.get();
+ }
+
+ MOCK_METHOD2(OnListScannersResultReceived,
+ void(const std::vector<
+ DocumentScanInterface::ScannerDescription>& scanners,
+ const std::string& error));
+
+ MOCK_METHOD3(OnScanCompleted,
+ void(const std::string& scanned_image,
+ const std::string& mime_type,
+ const std::string& error));
+
+ protected:
+ DocumentScanInterfaceChromeos scan_interface_;
+ scoped_ptr<chromeos::MockLorgnetteManagerClient> client_;
+};
+
+ACTION_P2(InvokeListScannersCallback, scanner_list, error) {
+ ::std::tr1::get<0>(args).Run(scanner_list, error);
+}
+
+ACTION_P2(InvokeScanCallback, succeeded, image_data) {
+ ::std::tr1::get<2>(args).Run(succeeded, image_data);
+}
+
+MATCHER_P5(IsScannerDescription, name, manufacturer, model, type, mime, "") {
+ return arg.name == name && arg.manufacturer == manufacturer &&
+ arg.model == model && arg.scanner_type == type &&
+ arg.image_mime_type == mime;
+}
+
+MATCHER_P2(IsScannerProperties, mode, resolution, "") {
+ return arg.mode == mode && arg.resolution_dpi == resolution;
+}
+
+TEST_F(DocumentScanInterfaceChromeosTest, ListScanners) {
+ chromeos::LorgnetteManagerClient::ScannerTable scanners;
+ const char kScannerName[] = "Monet";
+ chromeos::LorgnetteManagerClient::ScannerTableEntry entry;
+ const char kScannerManufacturer[] = "Jacques-Louis David";
+ entry[lorgnette::kScannerPropertyManufacturer] = kScannerManufacturer;
+ const char kScannerModel[] = "Le Havre";
+ entry[lorgnette::kScannerPropertyModel] = kScannerModel;
+ const char kScannerType[] = "Impressionism";
+ entry[lorgnette::kScannerPropertyType] = kScannerType;
+ scanners[kScannerName] = entry;
+ EXPECT_CALL(*client_, ListScanners(_))
+ .WillOnce(InvokeListScannersCallback(true, scanners));
+ EXPECT_CALL(*this, OnListScannersResultReceived(
+ testing::ElementsAre(IsScannerDescription(
+ kScannerName, kScannerManufacturer, kScannerModel,
+ kScannerType, "image/png")),
+ ""));
+ scan_interface_.ListScanners(base::Bind(
+ &DocumentScanInterfaceChromeosTest::OnListScannersResultReceived,
+ base::Unretained(this)));
+}
+
+TEST_F(DocumentScanInterfaceChromeosTest, ScanFailure) {
+ const char kScannerName[] = "Monet";
+ const int kResolution = 4096;
+ EXPECT_CALL(*client_, ScanImageToString(
+ kScannerName,
+ IsScannerProperties(
+ lorgnette::kScanPropertyModeColor, kResolution),
+ _)).WillOnce(InvokeScanCallback(false, ""));
+ EXPECT_CALL(*this, OnScanCompleted("data:image/png;base64,", "image/png",
+ "Image scan failed"));
+ scan_interface_.Scan(
+ kScannerName, DocumentScanInterface::kScanModeColor, kResolution,
+ base::Bind(&DocumentScanInterfaceChromeosTest::OnScanCompleted,
+ base::Unretained(this)));
+}
+
+TEST_F(DocumentScanInterfaceChromeosTest, ScanSuccess) {
+ const char kScannerName[] = "Monet";
+ const int kResolution = 4096;
+ EXPECT_CALL(
+ *client_,
+ ScanImageToString(
+ kScannerName,
+ IsScannerProperties(lorgnette::kScanPropertyModeColor, kResolution),
+ _)).WillOnce(InvokeScanCallback(true, std::string("PrettyPicture")));
+
+ // Data URL plus base64 representation of "PrettyPicture".
+ const char kExpectedImageData[] =
+ "data:image/png;base64,UHJldHR5UGljdHVyZQ==";
+
+ EXPECT_CALL(*this, OnScanCompleted(kExpectedImageData, "image/png", ""));
+ scan_interface_.Scan(
+ kScannerName, DocumentScanInterface::kScanModeColor, kResolution,
+ base::Bind(&DocumentScanInterfaceChromeosTest::OnScanCompleted,
+ base::Unretained(this)));
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc b/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc
new file mode 100644
index 0000000..6e8e50b
--- /dev/null
+++ b/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 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/document_scan/document_scan_interface.h"
+
+namespace {
+
+const char kScanFunctionNotImplementedError[] = "Scan function not implemented";
+
+} // namespace
+
+namespace extensions {
+
+namespace core_api {
+
+class DocumentScanInterfaceImpl : public DocumentScanInterface {
+ public:
+ DocumentScanInterfaceImpl() {}
+ ~DocumentScanInterfaceImpl() override {}
+
+ void ListScanners(const ListScannersResultsCallback& callback) override {
+ callback.Run(std::vector<ScannerDescription>(), "");
+ }
+ void Scan(const std::string& scanner_name,
+ ScanMode mode,
+ int resolution_dpi,
+ const ScanResultsCallback& callback) override {
+ callback.Run("", "", kScanFunctionNotImplementedError);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl);
+};
+
+// static
+DocumentScanInterface* DocumentScanInterface::CreateInstance() {
+ return new DocumentScanInterfaceImpl();
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/mock_document_scan_interface.cc b/extensions/browser/api/document_scan/mock_document_scan_interface.cc
new file mode 100644
index 0000000..6734840
--- /dev/null
+++ b/extensions/browser/api/document_scan/mock_document_scan_interface.cc
@@ -0,0 +1,19 @@
+// Copyright 2014 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/document_scan/mock_document_scan_interface.h"
+
+namespace extensions {
+
+namespace core_api {
+
+MockDocumentScanInterface::MockDocumentScanInterface() {
+}
+
+MockDocumentScanInterface::~MockDocumentScanInterface() {
+}
+
+} // namespace core_api
+
+} // namespace extensions
diff --git a/extensions/browser/api/document_scan/mock_document_scan_interface.h b/extensions/browser/api/document_scan/mock_document_scan_interface.h
new file mode 100644
index 0000000..3ced6c7
--- /dev/null
+++ b/extensions/browser/api/document_scan/mock_document_scan_interface.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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_DOCUMENT_SCAN_MOCK_DOCUMENT_SCAN_INTERFACE_H_
+#define EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_MOCK_DOCUMENT_SCAN_INTERFACE_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "extensions/browser/api/document_scan/document_scan_interface.h"
+
+namespace extensions {
+
+namespace core_api {
+
+class MockDocumentScanInterface : public DocumentScanInterface {
+ public:
+ MockDocumentScanInterface();
+ ~MockDocumentScanInterface() override;
+
+ MOCK_METHOD4(Scan,
+ void(const std::string& scanner_name,
+ ScanMode mode,
+ int resolution_dpi,
+ const ScanResultsCallback& callback));
+ MOCK_METHOD1(ListScanners, void(const ListScannersResultsCallback& callback));
+ MOCK_CONST_METHOD0(GetImageMimeType, std::string());
+};
+
+} // namespace core_api
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_DOCUMENT_SCAN_MOCK_DOCUMENT_SCAN_INTERFACE_H_
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index efcb46e..b49624a 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -115,6 +115,11 @@
"dependencies": ["permission:dns"],
"contexts": ["blessed_extension"]
},
+ "documentScan": {
+ "platforms": ["chromeos"],
+ "dependencies": ["permission:documentScan"],
+ "contexts": ["blessed_extension"]
+ },
// This is not a real API, only here for documentation purposes.
// See http://crbug.com/275944 for background.
"extensionTypes": {
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
index d2f39ff..59407f1 100644
--- a/extensions/common/api/_permission_features.json
+++ b/extensions/common/api/_permission_features.json
@@ -181,6 +181,10 @@
]
}
],
+ "documentScan": {
+ "channel": "dev",
+ "extension_types": ["extension", "platform_app"]
+ },
"extensionview": {
"channel": "dev",
"extension_types": ["platform_app"]
diff --git a/extensions/common/api/document_scan.idl b/extensions/common/api/document_scan.idl
new file mode 100644
index 0000000..a2bdcca
--- /dev/null
+++ b/extensions/common/api/document_scan.idl
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+// Use the <code>chrome.documentScan</code> API to discover and retrieve
+// images from attached paper document scanners.
+namespace documentScan {
+ dictionary ScanOptions {
+ // The MIME types that are accepted by the caller.
+ DOMString[]? mimeTypes;
+
+ // The number of scanned images allowed (defaults to 1).
+ long? maxImages;
+ };
+
+ dictionary ScanResults {
+ // The data image URLs in a form that can be passed as the "src" value to
+ // an image tag.
+ DOMString[] dataUrls;
+
+ // The MIME type of <code>dataUrls</code>.
+ DOMString mimeType;
+ };
+
+ // Callback from the <code>scan</code> method.
+ // |result| The results from the scan, if successful.
+ // Otherwise will return null and set runtime.lastError.
+ callback ScanCallback = void (ScanResults result);
+
+ interface Functions {
+ // Performs a document scan. On success, the PNG data will be
+ // sent to the callback.
+ // |options| : Object containing scan parameters.
+ // |callback| : Called with the result and data from the scan.
+ static void scan(ScanOptions options, ScanCallback callback);
+ };
+};
diff --git a/extensions/common/api/schemas.gypi b/extensions/common/api/schemas.gypi
index 0d170f9..ee46bd2 100644
--- a/extensions/common/api/schemas.gypi
+++ b/extensions/common/api/schemas.gypi
@@ -20,6 +20,7 @@
'bluetooth_private.json',
'bluetooth_socket.idl',
'cast_channel.idl',
+ 'document_scan.idl',
'dns.idl',
'events.json',
'extensions_manifest_types.json',
diff --git a/extensions/common/permissions/extensions_api_permissions.cc b/extensions/common/permissions/extensions_api_permissions.cc
index d9a811e..869e313 100644
--- a/extensions/common/permissions/extensions_api_permissions.cc
+++ b/extensions/common/permissions/extensions_api_permissions.cc
@@ -65,6 +65,11 @@ std::vector<APIPermissionInfo*> ExtensionsAPIPermissions::GetAllPermissions()
"diagnostics",
APIPermissionInfo::kFlagCannotBeOptional},
{APIPermission::kDns, "dns"},
+ {APIPermission::kDocumentScan,
+ "documentScan",
+ APIPermissionInfo::kFlagNone,
+ IDS_EXTENSION_PROMPT_WARNING_DOCUMENT_SCAN,
+ PermissionMessage::kDocumentScan},
{APIPermission::kExtensionView,
"extensionview",
APIPermissionInfo::kFlagCannotBeOptional},
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index ace05eaf..e4597a3 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -463,6 +463,11 @@
'browser/api/dns/dns_api.h',
'browser/api/dns/host_resolver_wrapper.cc',
'browser/api/dns/host_resolver_wrapper.h',
+ 'browser/api/document_scan/document_scan_api.cc',
+ 'browser/api/document_scan/document_scan_api.h',
+ 'browser/api/document_scan/document_scan_interface.cc',
+ 'browser/api/document_scan/document_scan_interface.h',
+ 'browser/api/document_scan/document_scan_interface_chromeos.cc',
'browser/api/execute_code_function.cc',
'browser/api/execute_code_function.h',
'browser/api/extension_view/extension_view_internal_api.cc',
@@ -901,7 +906,11 @@
'browser/api/vpn_provider/vpn_service.cc',
'browser/api/vpn_provider/vpn_service.h',
'browser/api/vpn_provider/vpn_service_factory.h'
- ]
+ ],
+ }, { # chromeos==0
+ 'sources': [
+ 'browser/api/document_scan/document_scan_interface_nonchromeos.cc',
+ ],
}],
['OS == "win" or OS == "mac"', {
'dependencies': [
diff --git a/extensions/extensions_tests.gyp b/extensions/extensions_tests.gyp
index a66e54c..30a8330 100644
--- a/extensions/extensions_tests.gyp
+++ b/extensions/extensions_tests.gyp
@@ -61,6 +61,9 @@
'browser/api/declarative/rules_registry_unittest.cc',
'browser/api/declarative_webrequest/webrequest_condition_unittest.cc',
'browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc',
+ 'browser/api/document_scan/document_scan_api_unittest.cc',
+ 'browser/api/document_scan/document_scan_interface_chromeos_unittest.cc',
+ 'browser/api/document_scan/mock_document_scan_interface.cc',
'browser/api/idle/idle_api_unittest.cc',
'browser/api/mime_handler_private/mime_handler_private_unittest.cc',
'browser/api/networking_config/networking_config_service_chromeos_unittest.cc',
@@ -162,6 +165,11 @@
'../base/allocator/allocator.gyp:allocator',
],
}],
+ ['chromeos==1', {
+ 'dependencies': [
+ '<(DEPTH)/chromeos/chromeos.gyp:chromeos_test_support',
+ ],
+ }],
],
},
{