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