[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; |
| 25 | using base::android::ScopedJavaLocalRef; |
| 26 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 27 | namespace printing { |
| 28 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | // 1 inch in mils. |
| 32 | const int kInchToMil = 1000; |
| 33 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 34 | int Round(double x) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 35 | 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. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 40 | void SetSizes(PrintSettings* settings, int dpi, int width, int height) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 41 | 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 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 51 | void GetPageRanges(JNIEnv* env, jintArray int_arr, PageRanges* range_vector) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 52 | std::vector<int> pages; |
| 53 | base::android::JavaIntArrayToIntVector(env, int_arr, &pages); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 54 | for (int page : pages) { |
| 55 | PageRange range; |
| 56 | range.from = page; |
| 57 | range.to = page; |
| 58 | range_vector->push_back(range); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 59 | } |
| 60 | } |
| 61 | |
| 62 | } // namespace |
| 63 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 64 | // static |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 65 | std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
| 66 | return base::WrapUnique(new PrintingContextAndroid(delegate)); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | // static |
Shimi Zhang | b414956 | 2017-06-30 02:41:23 | [diff] [blame] | 70 | void PrintingContextAndroid::PdfWritingDone(int fd, int page_count) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 71 | JNIEnv* env = base::android::AttachCurrentThread(); |
Shimi Zhang | b414956 | 2017-06-30 02:41:23 | [diff] [blame] | 72 | Java_PrintingContext_pdfWritingDone(env, fd, page_count); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 73 | } |
| 74 | |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 75 | PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate) |
| 76 | : PrintingContext(delegate) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 77 | // The constructor is run in the IO thread. |
| 78 | } |
| 79 | |
| 80 | PrintingContextAndroid::~PrintingContextAndroid() { |
| 81 | } |
| 82 | |
| 83 | void PrintingContextAndroid::AskUserForSettings( |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 84 | int max_pages, |
| 85 | bool has_selection, |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 86 | bool is_scripted, |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 87 | PrintSettingsCallback callback) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 88 | // This method is always run in the UI thread. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 89 | callback_ = std::move(callback); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 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] | 879517bd | 2013-11-22 20:36:31 | [diff] [blame] | 95 | reinterpret_cast<intptr_t>(this))); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 96 | } |
| 97 | |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 98 | if (is_scripted) { |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 99 | Java_PrintingContext_showPrintDialog(env, j_printing_context_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 100 | } else { |
Shimi Zhang | 3089982 | 2017-06-16 01:49:55 | [diff] [blame] | 101 | Java_PrintingContext_askUserForSettings(env, j_printing_context_, |
| 102 | max_pages); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 103 | } |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 104 | } |
| 105 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 106 | void PrintingContextAndroid::AskUserForSettingsReply( |
| 107 | JNIEnv* env, |
| 108 | const JavaParamRef<jobject>& obj, |
| 109 | jboolean success) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 110 | DCHECK(callback_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 111 | if (!success) { |
| 112 | // TODO(cimamoglu): Differentiate between FAILED And CANCEL. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 113 | std::move(callback_).Run(FAILED); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 114 | 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. |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 120 | int fd = Java_PrintingContext_getFileDescriptor(env, j_printing_context_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 121 | settings_.set_device_name(base::IntToString16(fd)); |
| 122 | |
| 123 | ScopedJavaLocalRef<jintArray> intArr = |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 124 | Java_PrintingContext_getPages(env, j_printing_context_); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 125 | if (intArr.obj()) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 126 | PageRanges range_vector; |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 127 | GetPageRanges(env, intArr.obj(), &range_vector); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 128 | settings_.set_ranges(range_vector); |
| 129 | } |
| 130 | |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 131 | 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] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 134 | 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 Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 138 | std::move(callback_).Run(OK); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 139 | } |
| 140 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 141 | void PrintingContextAndroid::ShowSystemDialogDone( |
| 142 | JNIEnv* env, |
| 143 | const JavaParamRef<jobject>& obj) { |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 144 | DCHECK(callback_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 145 | // Settings are not updated, callback is called only to unblock javascript. |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 146 | std::move(callback_).Run(CANCEL); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 147 | } |
| 148 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 149 | PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() { |
| 150 | DCHECK(!in_print_job_); |
| 151 | |
| 152 | ResetSettings(); |
[email protected] | c19b6a6 | 2013-11-18 21:53:11 | [diff] [blame] | 153 | settings_.set_dpi(kDefaultPdfDpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 154 | gfx::Size physical_size = GetPdfPaperSizeDeviceUnits(); |
| 155 | SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(), |
| 156 | physical_size.height()); |
| 157 | return OK; |
| 158 | } |
| 159 | |
| 160 | gfx::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 Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 165 | ulocdata_getPaperSize( |
| 166 | delegate_->GetAppLocale().c_str(), &height, &width, &error); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 167 | 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 | |
| 186 | PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings( |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 187 | bool external_preview, |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 188 | bool show_system_dialog, |
| 189 | int page_count) { |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 190 | DCHECK(!show_system_dialog); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 191 | DCHECK(!in_print_job_); |
| 192 | |
| 193 | // Intentional No-op. |
| 194 | |
| 195 | return OK; |
| 196 | } |
| 197 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 198 | PrintingContext::Result PrintingContextAndroid::NewDocument( |
[email protected] | 90007a5 | 2013-12-19 23:28:07 | [diff] [blame] | 199 | const base::string16& document_name) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 200 | DCHECK(!in_print_job_); |
| 201 | in_print_job_ = true; |
| 202 | |
| 203 | return OK; |
| 204 | } |
| 205 | |
| 206 | PrintingContext::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 | |
| 216 | PrintingContext::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 | |
| 226 | PrintingContext::Result PrintingContextAndroid::DocumentDone() { |
| 227 | if (abort_printing_) |
| 228 | return CANCEL; |
| 229 | DCHECK(in_print_job_); |
| 230 | |
| 231 | ResetSettings(); |
| 232 | return OK; |
| 233 | } |
| 234 | |
| 235 | void PrintingContextAndroid::Cancel() { |
| 236 | abort_printing_ = true; |
| 237 | in_print_job_ = false; |
| 238 | } |
| 239 | |
| 240 | void PrintingContextAndroid::ReleaseContext() { |
| 241 | // Intentional No-op. |
| 242 | } |
| 243 | |
Nico Weber | 8e55956 | 2017-10-03 01:25:26 | [diff] [blame] | 244 | printing::NativeDrawingContext PrintingContextAndroid::context() const { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 245 | // Intentional No-op. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 246 | return nullptr; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 247 | } |
| 248 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 249 | } // namespace printing |