blob: b85603a0d8a226d314d98b1af324cf47e1159e71 [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
Shimi Zhangb4149562017-06-30 02:41:2370void PrintingContextAndroid::PdfWritingDone(int fd, int page_count) {
[email protected]b6f76a12013-11-14 17:29:2471 JNIEnv* env = base::android::AttachCurrentThread();
Shimi Zhangb4149562017-06-30 02:41:2372 Java_PrintingContext_pdfWritingDone(env, fd, page_count);
[email protected]b6f76a12013-11-14 17:29:2473}
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,
Vladislav Kuzkokov48ceab22018-02-14 16:29:2887 PrintSettingsCallback callback) {
[email protected]b6f76a12013-11-14 17:29:2488 // This method is always run in the UI thread.
Vladislav Kuzkokov48ceab22018-02-14 16:29:2889 callback_ = std::move(callback);
[email protected]b6f76a12013-11-14 17:29:2490
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) {
Vladislav Kuzkokov48ceab22018-02-14 16:29:28110 DCHECK(callback_);
[email protected]b6f76a12013-11-14 17:29:24111 if (!success) {
112 // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
Vladislav Kuzkokov48ceab22018-02-14 16:29:28113 std::move(callback_).Run(FAILED);
[email protected]b6f76a12013-11-14 17:29:24114 return;
115 }
116
117 // We use device name variable to store the file descriptor. This is hacky
118 // but necessary. Since device name is not necessary for the upstream
119 // printing code for Android, this is harmless.
torne948f3662016-08-16 15:10:44120 int fd = Java_PrintingContext_getFileDescriptor(env, j_printing_context_);
[email protected]b6f76a12013-11-14 17:29:24121 settings_.set_device_name(base::IntToString16(fd));
122
123 ScopedJavaLocalRef<jintArray> intArr =
torne948f3662016-08-16 15:10:44124 Java_PrintingContext_getPages(env, j_printing_context_);
thestig5f683912016-09-30 22:42:16125 if (intArr.obj()) {
[email protected]b6f76a12013-11-14 17:29:24126 PageRanges range_vector;
thestig5f683912016-09-30 22:42:16127 GetPageRanges(env, intArr.obj(), &range_vector);
[email protected]b6f76a12013-11-14 17:29:24128 settings_.set_ranges(range_vector);
129 }
130
torne948f3662016-08-16 15:10:44131 int dpi = Java_PrintingContext_getDpi(env, j_printing_context_);
132 int width = Java_PrintingContext_getWidth(env, j_printing_context_);
133 int height = Java_PrintingContext_getHeight(env, j_printing_context_);
[email protected]b6f76a12013-11-14 17:29:24134 width = Round(ConvertUnitDouble(width, kInchToMil, 1.0) * dpi);
135 height = Round(ConvertUnitDouble(height, kInchToMil, 1.0) * dpi);
136 SetSizes(&settings_, dpi, width, height);
137
Vladislav Kuzkokov48ceab22018-02-14 16:29:28138 std::move(callback_).Run(OK);
[email protected]b6f76a12013-11-14 17:29:24139}
140
torne6f3f0972015-11-25 18:04:30141void PrintingContextAndroid::ShowSystemDialogDone(
142 JNIEnv* env,
143 const JavaParamRef<jobject>& obj) {
Vladislav Kuzkokov48ceab22018-02-14 16:29:28144 DCHECK(callback_);
dgn4c172eea2014-12-15 21:11:23145 // Settings are not updated, callback is called only to unblock javascript.
Vladislav Kuzkokov48ceab22018-02-14 16:29:28146 std::move(callback_).Run(CANCEL);
dgn4c172eea2014-12-15 21:11:23147}
148
[email protected]b6f76a12013-11-14 17:29:24149PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
150 DCHECK(!in_print_job_);
151
152 ResetSettings();
[email protected]c19b6a62013-11-18 21:53:11153 settings_.set_dpi(kDefaultPdfDpi);
[email protected]b6f76a12013-11-14 17:29:24154 gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
155 SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
156 physical_size.height());
157 return OK;
158}
159
160gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
161 // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
162 int32_t width = 0;
163 int32_t height = 0;
164 UErrorCode error = U_ZERO_ERROR;
Vitaly Bukabd7c9812014-08-26 08:57:54165 ulocdata_getPaperSize(
166 delegate_->GetAppLocale().c_str(), &height, &width, &error);
[email protected]b6f76a12013-11-14 17:29:24167 if (error > U_ZERO_ERROR) {
168 // If the call failed, assume a paper size of 8.5 x 11 inches.
169 LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
170 << error;
171 width = static_cast<int>(
172 kLetterWidthInch * settings_.device_units_per_inch());
173 height = static_cast<int>(
174 kLetterHeightInch * settings_.device_units_per_inch());
175 } else {
176 // ulocdata_getPaperSize returns the width and height in mm.
177 // Convert this to pixels based on the dpi.
178 float multiplier = 100 * settings_.device_units_per_inch();
179 multiplier /= kHundrethsMMPerInch;
180 width *= multiplier;
181 height *= multiplier;
182 }
183 return gfx::Size(width, height);
184}
185
186PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
vitalybuka92ab8ce2014-08-26 23:41:45187 bool external_preview,
vitalybuka95fa3c92015-05-05 03:03:32188 bool show_system_dialog,
189 int page_count) {
vitalybuka92ab8ce2014-08-26 23:41:45190 DCHECK(!show_system_dialog);
[email protected]b6f76a12013-11-14 17:29:24191 DCHECK(!in_print_job_);
192
193 // Intentional No-op.
194
195 return OK;
196}
197
[email protected]b6f76a12013-11-14 17:29:24198PrintingContext::Result PrintingContextAndroid::NewDocument(
[email protected]90007a52013-12-19 23:28:07199 const base::string16& document_name) {
[email protected]b6f76a12013-11-14 17:29:24200 DCHECK(!in_print_job_);
201 in_print_job_ = true;
202
203 return OK;
204}
205
206PrintingContext::Result PrintingContextAndroid::NewPage() {
207 if (abort_printing_)
208 return CANCEL;
209 DCHECK(in_print_job_);
210
211 // Intentional No-op.
212
213 return OK;
214}
215
216PrintingContext::Result PrintingContextAndroid::PageDone() {
217 if (abort_printing_)
218 return CANCEL;
219 DCHECK(in_print_job_);
220
221 // Intentional No-op.
222
223 return OK;
224}
225
226PrintingContext::Result PrintingContextAndroid::DocumentDone() {
227 if (abort_printing_)
228 return CANCEL;
229 DCHECK(in_print_job_);
230
231 ResetSettings();
232 return OK;
233}
234
235void PrintingContextAndroid::Cancel() {
236 abort_printing_ = true;
237 in_print_job_ = false;
238}
239
240void PrintingContextAndroid::ReleaseContext() {
241 // Intentional No-op.
242}
243
Nico Weber8e559562017-10-03 01:25:26244printing::NativeDrawingContext PrintingContextAndroid::context() const {
[email protected]b6f76a12013-11-14 17:29:24245 // Intentional No-op.
thestig5f683912016-09-30 22:42:16246 return nullptr;
[email protected]b6f76a12013-11-14 17:29:24247}
248
[email protected]b6f76a12013-11-14 17:29:24249} // namespace printing