[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" |
| 14 | #include "base/logging.h" |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 15 | #include "base/memory/ptr_util.h" |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 16 | #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 | |
torne | 8656011 | 2016-08-04 15:59:04 | [diff] [blame] | 24 | using base::android::JavaParamRef; |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame^] | 25 | using base::android::JavaRef; |
torne | 8656011 | 2016-08-04 15:59:04 | [diff] [blame] | 26 | using base::android::ScopedJavaLocalRef; |
| 27 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 28 | namespace printing { |
| 29 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 30 | namespace { |
| 31 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 32 | // Sets the page sizes for a |PrintSettings| object. |width| and |height| |
| 33 | // arguments should be in device units. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 34 | void SetSizes(PrintSettings* settings, int dpi, int width, int height) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 35 | gfx::Size physical_size_device_units(width, height); |
| 36 | // Assume full page is printable for now. |
| 37 | gfx::Rect printable_area_device_units(0, 0, width, height); |
| 38 | |
| 39 | settings->set_dpi(dpi); |
| 40 | settings->SetPrinterPrintableArea(physical_size_device_units, |
| 41 | printable_area_device_units, |
| 42 | false); |
| 43 | } |
| 44 | |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame^] | 45 | void GetPageRanges(JNIEnv* env, |
| 46 | const JavaRef<jintArray>& int_arr, |
| 47 | PageRanges* range_vector) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 48 | std::vector<int> pages; |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame^] | 49 | base::android::JavaIntArrayToIntVector(env, int_arr.obj(), &pages); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 50 | for (int page : pages) { |
| 51 | PageRange range; |
| 52 | range.from = page; |
| 53 | range.to = page; |
| 54 | range_vector->push_back(range); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 55 | } |
| 56 | } |
| 57 | |
| 58 | } // namespace |
| 59 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 60 | // static |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 61 | std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
| 62 | return base::WrapUnique(new PrintingContextAndroid(delegate)); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | // static |
Shimi Zhang | 5b8fb7c | 2018-09-27 01:20:49 | [diff] [blame] | 66 | void PrintingContextAndroid::PdfWritingDone(int page_count) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 67 | JNIEnv* env = base::android::AttachCurrentThread(); |
Shimi Zhang | 5b8fb7c | 2018-09-27 01:20:49 | [diff] [blame] | 68 | Java_PrintingContext_pdfWritingDone(env, page_count); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 69 | } |
| 70 | |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 71 | PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate) |
| 72 | : PrintingContext(delegate) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 73 | // The constructor is run in the IO thread. |
| 74 | } |
| 75 | |
| 76 | PrintingContextAndroid::~PrintingContextAndroid() { |
| 77 | } |
| 78 | |
| 79 | void PrintingContextAndroid::AskUserForSettings( |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 80 | int max_pages, |
| 81 | bool has_selection, |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 82 | bool is_scripted, |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 83 | PrintSettingsCallback callback) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 84 | // This method is always run in the UI thread. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 85 | callback_ = std::move(callback); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 86 | |
| 87 | JNIEnv* env = base::android::AttachCurrentThread(); |
| 88 | if (j_printing_context_.is_null()) { |
| 89 | j_printing_context_.Reset(Java_PrintingContext_create( |
| 90 | env, |
[email protected] | 879517bd | 2013-11-22 20:36:31 | [diff] [blame] | 91 | reinterpret_cast<intptr_t>(this))); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 92 | } |
| 93 | |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 94 | if (is_scripted) { |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 95 | Java_PrintingContext_showPrintDialog(env, j_printing_context_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 96 | } else { |
Shimi Zhang | 3089982 | 2017-06-16 01:49:55 | [diff] [blame] | 97 | Java_PrintingContext_askUserForSettings(env, j_printing_context_, |
| 98 | max_pages); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 99 | } |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 100 | } |
| 101 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 102 | void PrintingContextAndroid::AskUserForSettingsReply( |
| 103 | JNIEnv* env, |
| 104 | const JavaParamRef<jobject>& obj, |
| 105 | jboolean success) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 106 | DCHECK(callback_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 107 | if (!success) { |
| 108 | // TODO(cimamoglu): Differentiate between FAILED And CANCEL. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 109 | std::move(callback_).Run(FAILED); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 110 | return; |
| 111 | } |
| 112 | |
| 113 | // We use device name variable to store the file descriptor. This is hacky |
| 114 | // but necessary. Since device name is not necessary for the upstream |
| 115 | // printing code for Android, this is harmless. |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 116 | int fd = Java_PrintingContext_getFileDescriptor(env, j_printing_context_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 117 | settings_.set_device_name(base::IntToString16(fd)); |
| 118 | |
| 119 | ScopedJavaLocalRef<jintArray> intArr = |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 120 | Java_PrintingContext_getPages(env, j_printing_context_); |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame^] | 121 | if (!intArr.is_null()) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 122 | PageRanges range_vector; |
Torne (Richard Coles) | 1b8b515 | 2018-10-02 18:37:32 | [diff] [blame^] | 123 | GetPageRanges(env, intArr, &range_vector); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 124 | settings_.set_ranges(range_vector); |
| 125 | } |
| 126 | |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 127 | int dpi = Java_PrintingContext_getDpi(env, j_printing_context_); |
| 128 | int width = Java_PrintingContext_getWidth(env, j_printing_context_); |
| 129 | int height = Java_PrintingContext_getHeight(env, j_printing_context_); |
Shimi Zhang | 9c970fc7 | 2018-10-01 22:24:17 | [diff] [blame] | 130 | width = ConvertUnit(width, kMilsPerInch, dpi); |
| 131 | height = ConvertUnit(height, kMilsPerInch, dpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 132 | SetSizes(&settings_, dpi, width, height); |
| 133 | |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 134 | std::move(callback_).Run(OK); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 135 | } |
| 136 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 137 | void PrintingContextAndroid::ShowSystemDialogDone( |
| 138 | JNIEnv* env, |
| 139 | const JavaParamRef<jobject>& obj) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 140 | DCHECK(callback_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 141 | // Settings are not updated, callback is called only to unblock javascript. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 142 | std::move(callback_).Run(CANCEL); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 143 | } |
| 144 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 145 | PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() { |
| 146 | DCHECK(!in_print_job_); |
| 147 | |
| 148 | ResetSettings(); |
[email protected] | c19b6a6 | 2013-11-18 21:53:11 | [diff] [blame] | 149 | settings_.set_dpi(kDefaultPdfDpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 150 | gfx::Size physical_size = GetPdfPaperSizeDeviceUnits(); |
| 151 | SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(), |
| 152 | physical_size.height()); |
| 153 | return OK; |
| 154 | } |
| 155 | |
| 156 | gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() { |
| 157 | // NOTE: This implementation is the same as in PrintingContextNoSystemDialog. |
| 158 | int32_t width = 0; |
| 159 | int32_t height = 0; |
| 160 | UErrorCode error = U_ZERO_ERROR; |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 161 | ulocdata_getPaperSize( |
| 162 | delegate_->GetAppLocale().c_str(), &height, &width, &error); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 163 | if (error > U_ZERO_ERROR) { |
| 164 | // If the call failed, assume a paper size of 8.5 x 11 inches. |
| 165 | LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: " |
| 166 | << error; |
| 167 | width = static_cast<int>( |
| 168 | kLetterWidthInch * settings_.device_units_per_inch()); |
| 169 | height = static_cast<int>( |
| 170 | kLetterHeightInch * settings_.device_units_per_inch()); |
| 171 | } else { |
| 172 | // ulocdata_getPaperSize returns the width and height in mm. |
| 173 | // Convert this to pixels based on the dpi. |
Lei Zhang | d11ab16 | 2018-06-26 04:28:50 | [diff] [blame] | 174 | float multiplier = settings_.device_units_per_inch() / kMicronsPerMil; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 175 | width *= multiplier; |
| 176 | height *= multiplier; |
| 177 | } |
| 178 | return gfx::Size(width, height); |
| 179 | } |
| 180 | |
| 181 | PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings( |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 182 | bool external_preview, |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 183 | bool show_system_dialog, |
| 184 | int page_count) { |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 185 | DCHECK(!show_system_dialog); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 186 | DCHECK(!in_print_job_); |
| 187 | |
| 188 | // Intentional No-op. |
| 189 | |
| 190 | return OK; |
| 191 | } |
| 192 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 193 | PrintingContext::Result PrintingContextAndroid::NewDocument( |
[email protected] | 90007a5 | 2013-12-19 23:28:07 | [diff] [blame] | 194 | const base::string16& document_name) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 195 | DCHECK(!in_print_job_); |
| 196 | in_print_job_ = true; |
| 197 | |
| 198 | return OK; |
| 199 | } |
| 200 | |
| 201 | PrintingContext::Result PrintingContextAndroid::NewPage() { |
| 202 | if (abort_printing_) |
| 203 | return CANCEL; |
| 204 | DCHECK(in_print_job_); |
| 205 | |
| 206 | // Intentional No-op. |
| 207 | |
| 208 | return OK; |
| 209 | } |
| 210 | |
| 211 | PrintingContext::Result PrintingContextAndroid::PageDone() { |
| 212 | if (abort_printing_) |
| 213 | return CANCEL; |
| 214 | DCHECK(in_print_job_); |
| 215 | |
| 216 | // Intentional No-op. |
| 217 | |
| 218 | return OK; |
| 219 | } |
| 220 | |
| 221 | PrintingContext::Result PrintingContextAndroid::DocumentDone() { |
| 222 | if (abort_printing_) |
| 223 | return CANCEL; |
| 224 | DCHECK(in_print_job_); |
| 225 | |
| 226 | ResetSettings(); |
| 227 | return OK; |
| 228 | } |
| 229 | |
| 230 | void PrintingContextAndroid::Cancel() { |
| 231 | abort_printing_ = true; |
| 232 | in_print_job_ = false; |
| 233 | } |
| 234 | |
| 235 | void PrintingContextAndroid::ReleaseContext() { |
| 236 | // Intentional No-op. |
| 237 | } |
| 238 | |
Nico Weber | 8e55956 | 2017-10-03 01:25:26 | [diff] [blame] | 239 | printing::NativeDrawingContext PrintingContextAndroid::context() const { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 240 | // Intentional No-op. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 241 | return nullptr; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 242 | } |
| 243 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 244 | } // namespace printing |