blob: ec40ab6877f917f3073e819c702b8a136ccf512e [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"
Lei Zhang03f4a532019-01-23 18:46:3114#include "base/files/file.h"
[email protected]b6f76a12013-11-14 17:29:2415#include "base/logging.h"
dchengc3df9ba2016-04-07 23:09:3216#include "base/memory/ptr_util.h"
[email protected]b6f76a12013-11-14 17:29:2417#include "base/strings/string_number_conversions.h"
18#include "base/values.h"
19#include "jni/PrintingContext_jni.h"
20#include "printing/metafile.h"
21#include "printing/print_job_constants.h"
22#include "printing/units.h"
23#include "third_party/icu/source/i18n/unicode/ulocdata.h"
Jinsuk Kimfc9e3e82019-02-13 06:50:2324#include "ui/android/window_android.h"
[email protected]b6f76a12013-11-14 17:29:2425
torne86560112016-08-04 15:59:0426using base::android::JavaParamRef;
Torne (Richard Coles)1b8b5152018-10-02 18:37:3227using base::android::JavaRef;
torne86560112016-08-04 15:59:0428using base::android::ScopedJavaLocalRef;
29
thestig5f683912016-09-30 22:42:1630namespace printing {
31
[email protected]b6f76a12013-11-14 17:29:2432namespace {
33
[email protected]b6f76a12013-11-14 17:29:2434// Sets the page sizes for a |PrintSettings| object. |width| and |height|
35// arguments should be in device units.
thestig5f683912016-09-30 22:42:1636void SetSizes(PrintSettings* settings, int dpi, int width, int height) {
[email protected]b6f76a12013-11-14 17:29:2437 gfx::Size physical_size_device_units(width, height);
38 // Assume full page is printable for now.
39 gfx::Rect printable_area_device_units(0, 0, width, height);
40
41 settings->set_dpi(dpi);
42 settings->SetPrinterPrintableArea(physical_size_device_units,
Lei Zhang01a1d3c02019-05-21 04:59:1043 printable_area_device_units, false);
[email protected]b6f76a12013-11-14 17:29:2444}
45
Torne (Richard Coles)1b8b5152018-10-02 18:37:3246void GetPageRanges(JNIEnv* env,
47 const JavaRef<jintArray>& int_arr,
48 PageRanges* range_vector) {
[email protected]b6f76a12013-11-14 17:29:2449 std::vector<int> pages;
Torne (Richard Coles)3c22e8302018-10-12 18:34:2250 base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
thestig5f683912016-09-30 22:42:1651 for (int page : pages) {
52 PageRange range;
53 range.from = page;
54 range.to = page;
55 range_vector->push_back(range);
[email protected]b6f76a12013-11-14 17:29:2456 }
57}
58
59} // namespace
60
[email protected]b6f76a12013-11-14 17:29:2461// static
dchengc3df9ba2016-04-07 23:09:3262std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
63 return base::WrapUnique(new PrintingContextAndroid(delegate));
[email protected]b6f76a12013-11-14 17:29:2464}
65
66// static
Shimi Zhang5b8fb7c2018-09-27 01:20:4967void PrintingContextAndroid::PdfWritingDone(int page_count) {
[email protected]b6f76a12013-11-14 17:29:2468 JNIEnv* env = base::android::AttachCurrentThread();
Shimi Zhang5b8fb7c2018-09-27 01:20:4969 Java_PrintingContext_pdfWritingDone(env, page_count);
[email protected]b6f76a12013-11-14 17:29:2470}
71
Jinsuk Kimfc9e3e82019-02-13 06:50:2372// static
73void PrintingContextAndroid::SetPendingPrint(
74 ui::WindowAndroid* window,
75 const ScopedJavaLocalRef<jobject>& printable,
76 int render_process_id,
77 int render_frame_id) {
78 JNIEnv* env = base::android::AttachCurrentThread();
79 Java_PrintingContext_setPendingPrint(env, window->GetJavaObject(), printable,
80 render_process_id, render_frame_id);
81}
82
Vitaly Bukabd7c9812014-08-26 08:57:5483PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate)
84 : PrintingContext(delegate) {
[email protected]b6f76a12013-11-14 17:29:2485 // The constructor is run in the IO thread.
86}
87
Lei Zhang01a1d3c02019-05-21 04:59:1088PrintingContextAndroid::~PrintingContextAndroid() {}
[email protected]b6f76a12013-11-14 17:29:2489
90void PrintingContextAndroid::AskUserForSettings(
[email protected]b6f76a12013-11-14 17:29:2491 int max_pages,
92 bool has_selection,
dgn4c172eea2014-12-15 21:11:2393 bool is_scripted,
Vladislav Kuzkokov48ceab22018-02-14 16:29:2894 PrintSettingsCallback callback) {
[email protected]b6f76a12013-11-14 17:29:2495 // This method is always run in the UI thread.
Vladislav Kuzkokov48ceab22018-02-14 16:29:2896 callback_ = std::move(callback);
[email protected]b6f76a12013-11-14 17:29:2497
98 JNIEnv* env = base::android::AttachCurrentThread();
99 if (j_printing_context_.is_null()) {
Lei Zhang01a1d3c02019-05-21 04:59:10100 j_printing_context_.Reset(
101 Java_PrintingContext_create(env, reinterpret_cast<intptr_t>(this)));
[email protected]b6f76a12013-11-14 17:29:24102 }
103
dgn4c172eea2014-12-15 21:11:23104 if (is_scripted) {
torne948f3662016-08-16 15:10:44105 Java_PrintingContext_showPrintDialog(env, j_printing_context_);
dgn4c172eea2014-12-15 21:11:23106 } else {
Shimi Zhang30899822017-06-16 01:49:55107 Java_PrintingContext_askUserForSettings(env, j_printing_context_,
108 max_pages);
dgn4c172eea2014-12-15 21:11:23109 }
[email protected]b6f76a12013-11-14 17:29:24110}
111
torne6f3f0972015-11-25 18:04:30112void PrintingContextAndroid::AskUserForSettingsReply(
113 JNIEnv* env,
114 const JavaParamRef<jobject>& obj,
115 jboolean success) {
Vladislav Kuzkokov48ceab22018-02-14 16:29:28116 DCHECK(callback_);
[email protected]b6f76a12013-11-14 17:29:24117 if (!success) {
118 // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
Vladislav Kuzkokov48ceab22018-02-14 16:29:28119 std::move(callback_).Run(FAILED);
[email protected]b6f76a12013-11-14 17:29:24120 return;
121 }
122
123 // We use device name variable to store the file descriptor. This is hacky
124 // but necessary. Since device name is not necessary for the upstream
125 // printing code for Android, this is harmless.
Lei Zhang03f4a532019-01-23 18:46:31126 // TODO(thestig): See if the call to set_device_name() can be removed.
127 fd_ = Java_PrintingContext_getFileDescriptor(env, j_printing_context_);
128 DCHECK(is_file_descriptor_valid());
Raul Tambre42793872019-02-11 19:26:26129 settings_.set_device_name(base::NumberToString16(fd_));
[email protected]b6f76a12013-11-14 17:29:24130
131 ScopedJavaLocalRef<jintArray> intArr =
torne948f3662016-08-16 15:10:44132 Java_PrintingContext_getPages(env, j_printing_context_);
Torne (Richard Coles)1b8b5152018-10-02 18:37:32133 if (!intArr.is_null()) {
[email protected]b6f76a12013-11-14 17:29:24134 PageRanges range_vector;
Torne (Richard Coles)1b8b5152018-10-02 18:37:32135 GetPageRanges(env, intArr, &range_vector);
[email protected]b6f76a12013-11-14 17:29:24136 settings_.set_ranges(range_vector);
137 }
138
torne948f3662016-08-16 15:10:44139 int dpi = Java_PrintingContext_getDpi(env, j_printing_context_);
140 int width = Java_PrintingContext_getWidth(env, j_printing_context_);
141 int height = Java_PrintingContext_getHeight(env, j_printing_context_);
Shimi Zhang9c970fc72018-10-01 22:24:17142 width = ConvertUnit(width, kMilsPerInch, dpi);
143 height = ConvertUnit(height, kMilsPerInch, dpi);
[email protected]b6f76a12013-11-14 17:29:24144 SetSizes(&settings_, dpi, width, height);
145
Vladislav Kuzkokov48ceab22018-02-14 16:29:28146 std::move(callback_).Run(OK);
[email protected]b6f76a12013-11-14 17:29:24147}
148
torne6f3f0972015-11-25 18:04:30149void PrintingContextAndroid::ShowSystemDialogDone(
150 JNIEnv* env,
151 const JavaParamRef<jobject>& obj) {
Vladislav Kuzkokov48ceab22018-02-14 16:29:28152 DCHECK(callback_);
dgn4c172eea2014-12-15 21:11:23153 // Settings are not updated, callback is called only to unblock javascript.
Vladislav Kuzkokov48ceab22018-02-14 16:29:28154 std::move(callback_).Run(CANCEL);
dgn4c172eea2014-12-15 21:11:23155}
156
Lei Zhang03f4a532019-01-23 18:46:31157void PrintingContextAndroid::PrintDocument(const MetafilePlayer& metafile) {
158 DCHECK(is_file_descriptor_valid());
159
160 base::File file(fd_);
161 metafile.SaveTo(&file);
162 file.TakePlatformFile();
163}
164
[email protected]b6f76a12013-11-14 17:29:24165PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
166 DCHECK(!in_print_job_);
167
168 ResetSettings();
[email protected]c19b6a62013-11-18 21:53:11169 settings_.set_dpi(kDefaultPdfDpi);
[email protected]b6f76a12013-11-14 17:29:24170 gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
171 SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
172 physical_size.height());
173 return OK;
174}
175
176gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
177 // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
178 int32_t width = 0;
179 int32_t height = 0;
180 UErrorCode error = U_ZERO_ERROR;
Lei Zhang01a1d3c02019-05-21 04:59:10181 ulocdata_getPaperSize(delegate_->GetAppLocale().c_str(), &height, &width,
182 &error);
[email protected]b6f76a12013-11-14 17:29:24183 if (error > U_ZERO_ERROR) {
184 // If the call failed, assume a paper size of 8.5 x 11 inches.
185 LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
186 << error;
Lei Zhang01a1d3c02019-05-21 04:59:10187 width =
188 static_cast<int>(kLetterWidthInch * settings_.device_units_per_inch());
189 height =
190 static_cast<int>(kLetterHeightInch * settings_.device_units_per_inch());
[email protected]b6f76a12013-11-14 17:29:24191 } else {
192 // ulocdata_getPaperSize returns the width and height in mm.
193 // Convert this to pixels based on the dpi.
Lei Zhangd11ab162018-06-26 04:28:50194 float multiplier = settings_.device_units_per_inch() / kMicronsPerMil;
[email protected]b6f76a12013-11-14 17:29:24195 width *= multiplier;
196 height *= multiplier;
197 }
198 return gfx::Size(width, height);
199}
200
201PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
vitalybuka92ab8ce2014-08-26 23:41:45202 bool external_preview,
vitalybuka95fa3c92015-05-05 03:03:32203 bool show_system_dialog,
204 int page_count) {
vitalybuka92ab8ce2014-08-26 23:41:45205 DCHECK(!show_system_dialog);
[email protected]b6f76a12013-11-14 17:29:24206 DCHECK(!in_print_job_);
207
208 // Intentional No-op.
209
210 return OK;
211}
212
[email protected]b6f76a12013-11-14 17:29:24213PrintingContext::Result PrintingContextAndroid::NewDocument(
[email protected]90007a52013-12-19 23:28:07214 const base::string16& document_name) {
[email protected]b6f76a12013-11-14 17:29:24215 DCHECK(!in_print_job_);
216 in_print_job_ = true;
217
218 return OK;
219}
220
221PrintingContext::Result PrintingContextAndroid::NewPage() {
222 if (abort_printing_)
223 return CANCEL;
224 DCHECK(in_print_job_);
225
226 // Intentional No-op.
227
228 return OK;
229}
230
231PrintingContext::Result PrintingContextAndroid::PageDone() {
232 if (abort_printing_)
233 return CANCEL;
234 DCHECK(in_print_job_);
235
236 // Intentional No-op.
237
238 return OK;
239}
240
241PrintingContext::Result PrintingContextAndroid::DocumentDone() {
242 if (abort_printing_)
243 return CANCEL;
244 DCHECK(in_print_job_);
245
246 ResetSettings();
247 return OK;
248}
249
250void PrintingContextAndroid::Cancel() {
251 abort_printing_ = true;
252 in_print_job_ = false;
253}
254
255void PrintingContextAndroid::ReleaseContext() {
256 // Intentional No-op.
257}
258
Nico Weber8e559562017-10-03 01:25:26259printing::NativeDrawingContext PrintingContextAndroid::context() const {
[email protected]b6f76a12013-11-14 17:29:24260 // Intentional No-op.
thestig5f683912016-09-30 22:42:16261 return nullptr;
[email protected]b6f76a12013-11-14 17:29:24262}
263
[email protected]b6f76a12013-11-14 17:29:24264} // namespace printing