1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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
|