blob: 7b5f3b1c48cd32a57217f213480bb9e6f8864775 [file] [log] [blame]
[email protected]b6f76a12013-11-14 17:29:241// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "printing/printing_context_android.h"
6
avi126e93c2015-12-21 21:48:167#include <stdint.h>
8
[email protected]b6f76a12013-11-14 17:29:249#include <vector>
10
11#include "base/android/jni_android.h"
12#include "base/android/jni_array.h"
13#include "base/android/jni_string.h"
14#include "base/logging.h"
dchengc3df9ba2016-04-07 23:09:3215#include "base/memory/ptr_util.h"
[email protected]b6f76a12013-11-14 17:29:2416#include "base/strings/string_number_conversions.h"
17#include "base/values.h"
18#include "jni/PrintingContext_jni.h"
19#include "printing/metafile.h"
20#include "printing/print_job_constants.h"
21#include "printing/units.h"
22#include "third_party/icu/source/i18n/unicode/ulocdata.h"
23
torne86560112016-08-04 15:59:0424using base::android::JavaParamRef;
25using base::android::ScopedJavaLocalRef;
26
thestig5f683912016-09-30 22:42:1627namespace printing {
28
[email protected]b6f76a12013-11-14 17:29:2429namespace {
30
31// 1 inch in mils.
32const int kInchToMil = 1000;
33
thestig5f683912016-09-30 22:42:1634int Round(double x) {
[email protected]b6f76a12013-11-14 17:29:2435 return static_cast<int>(x + 0.5);
36}
37
38// Sets the page sizes for a |PrintSettings| object. |width| and |height|
39// arguments should be in device units.
thestig5f683912016-09-30 22:42:1640void SetSizes(PrintSettings* settings, int dpi, int width, int height) {
[email protected]b6f76a12013-11-14 17:29:2441 gfx::Size physical_size_device_units(width, height);
42 // Assume full page is printable for now.
43 gfx::Rect printable_area_device_units(0, 0, width, height);
44
45 settings->set_dpi(dpi);
46 settings->SetPrinterPrintableArea(physical_size_device_units,
47 printable_area_device_units,
48 false);
49}
50
thestig5f683912016-09-30 22:42:1651void GetPageRanges(JNIEnv* env, jintArray int_arr, PageRanges* range_vector) {
[email protected]b6f76a12013-11-14 17:29:2452 std::vector<int> pages;
53 base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
thestig5f683912016-09-30 22:42:1654 for (int page : pages) {
55 PageRange range;
56 range.from = page;
57 range.to = page;
58 range_vector->push_back(range);
[email protected]b6f76a12013-11-14 17:29:2459 }
60}
61
62} // namespace
63
[email protected]b6f76a12013-11-14 17:29:2464// static
dchengc3df9ba2016-04-07 23:09:3265std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
66 return base::WrapUnique(new PrintingContextAndroid(delegate));
[email protected]b6f76a12013-11-14 17:29:2467}
68
69// static
70void PrintingContextAndroid::PdfWritingDone(int fd, bool success) {
71 JNIEnv* env = base::android::AttachCurrentThread();
72 Java_PrintingContext_pdfWritingDone(env, fd, success);
73}
74
Vitaly Bukabd7c9812014-08-26 08:57:5475PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate)
76 : PrintingContext(delegate) {
[email protected]b6f76a12013-11-14 17:29:2477 // The constructor is run in the IO thread.
78}
79
80PrintingContextAndroid::~PrintingContextAndroid() {
81}
82
83void PrintingContextAndroid::AskUserForSettings(
[email protected]b6f76a12013-11-14 17:29:2484 int max_pages,
85 bool has_selection,
dgn4c172eea2014-12-15 21:11:2386 bool is_scripted,
[email protected]b6f76a12013-11-14 17:29:2487 const PrintSettingsCallback& callback) {
88 // This method is always run in the UI thread.
89 callback_ = callback;
90
91 JNIEnv* env = base::android::AttachCurrentThread();
92 if (j_printing_context_.is_null()) {
93 j_printing_context_.Reset(Java_PrintingContext_create(
94 env,
[email protected]879517bd2013-11-22 20:36:3195 reinterpret_cast<intptr_t>(this)));
[email protected]b6f76a12013-11-14 17:29:2496 }
97
dgn4c172eea2014-12-15 21:11:2398 if (is_scripted) {
torne948f3662016-08-16 15:10:4499 Java_PrintingContext_showPrintDialog(env, j_printing_context_);
dgn4c172eea2014-12-15 21:11:23100 } else {
Shimi Zhang30899822017-06-16 01:49:55101 Java_PrintingContext_askUserForSettings(env, j_printing_context_,
102 max_pages);
dgn4c172eea2014-12-15 21:11:23103 }
[email protected]b6f76a12013-11-14 17:29:24104}
105
torne6f3f0972015-11-25 18:04:30106void PrintingContextAndroid::AskUserForSettingsReply(
107 JNIEnv* env,
108 const JavaParamRef<jobject>& obj,
109 jboolean success) {
[email protected]b6f76a12013-11-14 17:29:24110 if (!success) {
111 // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
112 callback_.Run(FAILED);
113 return;
114 }
115
116 // We use device name variable to store the file descriptor. This is hacky
117 // but necessary. Since device name is not necessary for the upstream
118 // printing code for Android, this is harmless.
torne948f3662016-08-16 15:10:44119 int fd = Java_PrintingContext_getFileDescriptor(env, j_printing_context_);
[email protected]b6f76a12013-11-14 17:29:24120 settings_.set_device_name(base::IntToString16(fd));
121
122 ScopedJavaLocalRef<jintArray> intArr =
torne948f3662016-08-16 15:10:44123 Java_PrintingContext_getPages(env, j_printing_context_);
thestig5f683912016-09-30 22:42:16124 if (intArr.obj()) {
[email protected]b6f76a12013-11-14 17:29:24125 PageRanges range_vector;
thestig5f683912016-09-30 22:42:16126 GetPageRanges(env, intArr.obj(), &range_vector);
[email protected]b6f76a12013-11-14 17:29:24127 settings_.set_ranges(range_vector);
128 }
129
torne948f3662016-08-16 15:10:44130 int dpi = Java_PrintingContext_getDpi(env, j_printing_context_);
131 int width = Java_PrintingContext_getWidth(env, j_printing_context_);
132 int height = Java_PrintingContext_getHeight(env, j_printing_context_);
[email protected]b6f76a12013-11-14 17:29:24133 width = Round(ConvertUnitDouble(width, kInchToMil, 1.0) * dpi);
134 height = Round(ConvertUnitDouble(height, kInchToMil, 1.0) * dpi);
135 SetSizes(&settings_, dpi, width, height);
136
137 callback_.Run(OK);
138}
139
torne6f3f0972015-11-25 18:04:30140void PrintingContextAndroid::ShowSystemDialogDone(
141 JNIEnv* env,
142 const JavaParamRef<jobject>& obj) {
dgn4c172eea2014-12-15 21:11:23143 // Settings are not updated, callback is called only to unblock javascript.
144 callback_.Run(CANCEL);
145}
146
[email protected]b6f76a12013-11-14 17:29:24147PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
148 DCHECK(!in_print_job_);
149
150 ResetSettings();
[email protected]c19b6a62013-11-18 21:53:11151 settings_.set_dpi(kDefaultPdfDpi);
[email protected]b6f76a12013-11-14 17:29:24152 gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
153 SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
154 physical_size.height());
155 return OK;
156}
157
158gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
159 // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
160 int32_t width = 0;
161 int32_t height = 0;
162 UErrorCode error = U_ZERO_ERROR;
Vitaly Bukabd7c9812014-08-26 08:57:54163 ulocdata_getPaperSize(
164 delegate_->GetAppLocale().c_str(), &height, &width, &error);
[email protected]b6f76a12013-11-14 17:29:24165 if (error > U_ZERO_ERROR) {
166 // If the call failed, assume a paper size of 8.5 x 11 inches.
167 LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
168 << error;
169 width = static_cast<int>(
170 kLetterWidthInch * settings_.device_units_per_inch());
171 height = static_cast<int>(
172 kLetterHeightInch * settings_.device_units_per_inch());
173 } else {
174 // ulocdata_getPaperSize returns the width and height in mm.
175 // Convert this to pixels based on the dpi.
176 float multiplier = 100 * settings_.device_units_per_inch();
177 multiplier /= kHundrethsMMPerInch;
178 width *= multiplier;
179 height *= multiplier;
180 }
181 return gfx::Size(width, height);
182}
183
184PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
vitalybuka92ab8ce2014-08-26 23:41:45185 bool external_preview,
vitalybuka95fa3c92015-05-05 03:03:32186 bool show_system_dialog,
187 int page_count) {
vitalybuka92ab8ce2014-08-26 23:41:45188 DCHECK(!show_system_dialog);
[email protected]b6f76a12013-11-14 17:29:24189 DCHECK(!in_print_job_);
190
191 // Intentional No-op.
192
193 return OK;
194}
195
[email protected]b6f76a12013-11-14 17:29:24196PrintingContext::Result PrintingContextAndroid::NewDocument(
[email protected]90007a52013-12-19 23:28:07197 const base::string16& document_name) {
[email protected]b6f76a12013-11-14 17:29:24198 DCHECK(!in_print_job_);
199 in_print_job_ = true;
200
201 return OK;
202}
203
204PrintingContext::Result PrintingContextAndroid::NewPage() {
205 if (abort_printing_)
206 return CANCEL;
207 DCHECK(in_print_job_);
208
209 // Intentional No-op.
210
211 return OK;
212}
213
214PrintingContext::Result PrintingContextAndroid::PageDone() {
215 if (abort_printing_)
216 return CANCEL;
217 DCHECK(in_print_job_);
218
219 // Intentional No-op.
220
221 return OK;
222}
223
224PrintingContext::Result PrintingContextAndroid::DocumentDone() {
225 if (abort_printing_)
226 return CANCEL;
227 DCHECK(in_print_job_);
228
229 ResetSettings();
230 return OK;
231}
232
233void PrintingContextAndroid::Cancel() {
234 abort_printing_ = true;
235 in_print_job_ = false;
236}
237
238void PrintingContextAndroid::ReleaseContext() {
239 // Intentional No-op.
240}
241
tfarina876d1e02016-10-11 23:12:53242skia::NativeDrawingContext PrintingContextAndroid::context() const {
[email protected]b6f76a12013-11-14 17:29:24243 // Intentional No-op.
thestig5f683912016-09-30 22:42:16244 return nullptr;
[email protected]b6f76a12013-11-14 17:29:24245}
246
247// static
248bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) {
thestig5f683912016-09-30 22:42:16249 return RegisterNativesImpl(env);
[email protected]b6f76a12013-11-14 17:29:24250}
251
252} // namespace printing