[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 1 | // 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 | |
avi | 126e93c | 2015-12-21 21:48:16 | [diff] [blame] | 7 | #include <stdint.h> |
| 8 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 9 | #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 Zhang | 03f4a53 | 2019-01-23 18:46:31 | [diff] [blame] | 14 | #include "base/files/file.h" |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 15 | #include "base/logging.h" |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 16 | #include "base/memory/ptr_util.h" |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 17 | #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 Kim | fc9e3e8 | 2019-02-13 06:50:23 | [diff] [blame] | 24 | #include "ui/android/window_android.h" |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 25 | |
torne | 8656011 | 2016-08-04 15:59:04 | [diff] [blame] | 26 | using base::android::JavaParamRef; |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame] | 27 | using base::android::JavaRef; |
torne | 8656011 | 2016-08-04 15:59:04 | [diff] [blame] | 28 | using base::android::ScopedJavaLocalRef; |
| 29 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 30 | namespace printing { |
| 31 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 32 | namespace { |
| 33 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 34 | // Sets the page sizes for a |PrintSettings| object. |width| and |height| |
| 35 | // arguments should be in device units. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 36 | void SetSizes(PrintSettings* settings, int dpi, int width, int height) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 37 | 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 Zhang | 01a1d3c0 | 2019-05-21 04:59:10 | [diff] [blame] | 43 | printable_area_device_units, false); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 44 | } |
| 45 | |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame] | 46 | void GetPageRanges(JNIEnv* env, |
| 47 | const JavaRef<jintArray>& int_arr, |
| 48 | PageRanges* range_vector) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 49 | std::vector<int> pages; |
Torne (Richard Coles) | 3c22e830 | 2018-10-12 18:34:22 | [diff] [blame] | 50 | base::android::JavaIntArrayToIntVector(env, int_arr, &pages); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 51 | for (int page : pages) { |
| 52 | PageRange range; |
| 53 | range.from = page; |
| 54 | range.to = page; |
| 55 | range_vector->push_back(range); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 56 | } |
| 57 | } |
| 58 | |
| 59 | } // namespace |
| 60 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 61 | // static |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 62 | std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
| 63 | return base::WrapUnique(new PrintingContextAndroid(delegate)); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | // static |
Shimi Zhang | 5b8fb7c | 2018-09-27 01:20:49 | [diff] [blame] | 67 | void PrintingContextAndroid::PdfWritingDone(int page_count) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 68 | JNIEnv* env = base::android::AttachCurrentThread(); |
Shimi Zhang | 5b8fb7c | 2018-09-27 01:20:49 | [diff] [blame] | 69 | Java_PrintingContext_pdfWritingDone(env, page_count); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 70 | } |
| 71 | |
Jinsuk Kim | fc9e3e8 | 2019-02-13 06:50:23 | [diff] [blame] | 72 | // static |
| 73 | void 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 Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 83 | PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate) |
| 84 | : PrintingContext(delegate) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 85 | // The constructor is run in the IO thread. |
| 86 | } |
| 87 | |
Lei Zhang | 01a1d3c0 | 2019-05-21 04:59:10 | [diff] [blame] | 88 | PrintingContextAndroid::~PrintingContextAndroid() {} |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 89 | |
| 90 | void PrintingContextAndroid::AskUserForSettings( |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 91 | int max_pages, |
| 92 | bool has_selection, |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 93 | bool is_scripted, |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 94 | PrintSettingsCallback callback) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 95 | // This method is always run in the UI thread. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 96 | callback_ = std::move(callback); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 97 | |
| 98 | JNIEnv* env = base::android::AttachCurrentThread(); |
| 99 | if (j_printing_context_.is_null()) { |
Lei Zhang | 01a1d3c0 | 2019-05-21 04:59:10 | [diff] [blame] | 100 | j_printing_context_.Reset( |
| 101 | Java_PrintingContext_create(env, reinterpret_cast<intptr_t>(this))); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 102 | } |
| 103 | |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 104 | if (is_scripted) { |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 105 | Java_PrintingContext_showPrintDialog(env, j_printing_context_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 106 | } else { |
Shimi Zhang | 3089982 | 2017-06-16 01:49:55 | [diff] [blame] | 107 | Java_PrintingContext_askUserForSettings(env, j_printing_context_, |
| 108 | max_pages); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 109 | } |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 110 | } |
| 111 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 112 | void PrintingContextAndroid::AskUserForSettingsReply( |
| 113 | JNIEnv* env, |
| 114 | const JavaParamRef<jobject>& obj, |
| 115 | jboolean success) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 116 | DCHECK(callback_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 117 | if (!success) { |
| 118 | // TODO(cimamoglu): Differentiate between FAILED And CANCEL. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 119 | std::move(callback_).Run(FAILED); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 120 | 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 Zhang | 03f4a53 | 2019-01-23 18:46:31 | [diff] [blame] | 126 | // 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 Tambre | 4279387 | 2019-02-11 19:26:26 | [diff] [blame] | 129 | settings_.set_device_name(base::NumberToString16(fd_)); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 130 | |
| 131 | ScopedJavaLocalRef<jintArray> intArr = |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 132 | Java_PrintingContext_getPages(env, j_printing_context_); |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame] | 133 | if (!intArr.is_null()) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 134 | PageRanges range_vector; |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame] | 135 | GetPageRanges(env, intArr, &range_vector); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 136 | settings_.set_ranges(range_vector); |
| 137 | } |
| 138 | |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 139 | 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 Zhang | 9c970fc7 | 2018-10-01 22:24:17 | [diff] [blame] | 142 | width = ConvertUnit(width, kMilsPerInch, dpi); |
| 143 | height = ConvertUnit(height, kMilsPerInch, dpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 144 | SetSizes(&settings_, dpi, width, height); |
| 145 | |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 146 | std::move(callback_).Run(OK); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 147 | } |
| 148 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 149 | void PrintingContextAndroid::ShowSystemDialogDone( |
| 150 | JNIEnv* env, |
| 151 | const JavaParamRef<jobject>& obj) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 152 | DCHECK(callback_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 153 | // Settings are not updated, callback is called only to unblock javascript. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 154 | std::move(callback_).Run(CANCEL); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 155 | } |
| 156 | |
Lei Zhang | 03f4a53 | 2019-01-23 18:46:31 | [diff] [blame] | 157 | void 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] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 165 | PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() { |
| 166 | DCHECK(!in_print_job_); |
| 167 | |
| 168 | ResetSettings(); |
[email protected] | c19b6a6 | 2013-11-18 21:53:11 | [diff] [blame] | 169 | settings_.set_dpi(kDefaultPdfDpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 170 | gfx::Size physical_size = GetPdfPaperSizeDeviceUnits(); |
| 171 | SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(), |
| 172 | physical_size.height()); |
| 173 | return OK; |
| 174 | } |
| 175 | |
| 176 | gfx::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 Zhang | 01a1d3c0 | 2019-05-21 04:59:10 | [diff] [blame] | 181 | ulocdata_getPaperSize(delegate_->GetAppLocale().c_str(), &height, &width, |
| 182 | &error); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 183 | 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 Zhang | 01a1d3c0 | 2019-05-21 04:59:10 | [diff] [blame] | 187 | 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] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 191 | } else { |
| 192 | // ulocdata_getPaperSize returns the width and height in mm. |
| 193 | // Convert this to pixels based on the dpi. |
Lei Zhang | d11ab16 | 2018-06-26 04:28:50 | [diff] [blame] | 194 | float multiplier = settings_.device_units_per_inch() / kMicronsPerMil; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 195 | width *= multiplier; |
| 196 | height *= multiplier; |
| 197 | } |
| 198 | return gfx::Size(width, height); |
| 199 | } |
| 200 | |
| 201 | PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings( |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 202 | bool external_preview, |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 203 | bool show_system_dialog, |
| 204 | int page_count) { |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 205 | DCHECK(!show_system_dialog); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 206 | DCHECK(!in_print_job_); |
| 207 | |
| 208 | // Intentional No-op. |
| 209 | |
| 210 | return OK; |
| 211 | } |
| 212 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 213 | PrintingContext::Result PrintingContextAndroid::NewDocument( |
[email protected] | 90007a5 | 2013-12-19 23:28:07 | [diff] [blame] | 214 | const base::string16& document_name) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 215 | DCHECK(!in_print_job_); |
| 216 | in_print_job_ = true; |
| 217 | |
| 218 | return OK; |
| 219 | } |
| 220 | |
| 221 | PrintingContext::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 | |
| 231 | PrintingContext::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 | |
| 241 | PrintingContext::Result PrintingContextAndroid::DocumentDone() { |
| 242 | if (abort_printing_) |
| 243 | return CANCEL; |
| 244 | DCHECK(in_print_job_); |
| 245 | |
| 246 | ResetSettings(); |
| 247 | return OK; |
| 248 | } |
| 249 | |
| 250 | void PrintingContextAndroid::Cancel() { |
| 251 | abort_printing_ = true; |
| 252 | in_print_job_ = false; |
| 253 | } |
| 254 | |
| 255 | void PrintingContextAndroid::ReleaseContext() { |
| 256 | // Intentional No-op. |
| 257 | } |
| 258 | |
Nico Weber | 8e55956 | 2017-10-03 01:25:26 | [diff] [blame] | 259 | printing::NativeDrawingContext PrintingContextAndroid::context() const { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 260 | // Intentional No-op. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 261 | return nullptr; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 262 | } |
| 263 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 264 | } // namespace printing |