• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package org.chromium.android_webview;
6 
7 import android.os.CancellationSignal;
8 import android.os.ParcelFileDescriptor;
9 import android.print.PrintAttributes;
10 import android.util.Log;
11 import android.view.ViewGroup;
12 import android.webkit.ValueCallback;
13 
14 import org.chromium.base.CalledByNative;
15 import org.chromium.base.JNINamespace;
16 
17 /**
18  * Export the android webview as a PDF.
19  * @TODO(sgurun) explain the ownership of this class and its native counterpart
20  */
21 @JNINamespace("android_webview")
22 public class AwPdfExporter {
23 
24     private static final String TAG = "AwPdfExporter";
25     private long mNativeAwPdfExporter;
26     // TODO(sgurun) result callback should return an int/object indicating errors.
27     // potential errors: invalid print parameters, already pending, IO error
28     private ValueCallback<Boolean> mResultCallback;
29     private PrintAttributes mAttributes;
30     private ParcelFileDescriptor mFd;
31     // Maintain a reference to the top level object (i.e. WebView) since in a common
32     // use case (offscreen webview) application may expect the framework's print manager
33     // to own the Webview (via PrintDocumentAdapter).
34     // NOTE: it looks unused, but please do not remove this reference.
35     private ViewGroup mContainerView;
36 
AwPdfExporter(ViewGroup containerView)37     AwPdfExporter(ViewGroup containerView) {
38         setContainerView(containerView);
39     }
40 
setContainerView(ViewGroup containerView)41     public void setContainerView(ViewGroup containerView) {
42         mContainerView = containerView;
43     }
44 
exportToPdf(final ParcelFileDescriptor fd, PrintAttributes attributes, ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)45     public void exportToPdf(final ParcelFileDescriptor fd, PrintAttributes attributes,
46             ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
47 
48         if (fd == null) {
49             throw new IllegalArgumentException("fd cannot be null");
50         }
51         if (resultCallback == null) {
52             throw new IllegalArgumentException("resultCallback cannot be null");
53         }
54         if (mResultCallback != null) {
55             throw new IllegalStateException("printing is already pending");
56         }
57         if (attributes.getMediaSize() == null) {
58             throw new  IllegalArgumentException("attributes must specify a media size");
59         }
60         if (attributes.getResolution() == null) {
61             throw new IllegalArgumentException("attributes must specify print resolution");
62         }
63         if (attributes.getMinMargins() == null) {
64             throw new IllegalArgumentException("attributes must specify margins");
65         }
66         if (mNativeAwPdfExporter == 0) {
67             resultCallback.onReceiveValue(false);
68             return;
69         }
70         mResultCallback = resultCallback;
71         mAttributes = attributes;
72         mFd = fd;
73         nativeExportToPdf(mNativeAwPdfExporter, mFd.getFd(), cancellationSignal);
74     }
75 
76     @CalledByNative
setNativeAwPdfExporter(long nativePdfExporter)77     private void setNativeAwPdfExporter(long nativePdfExporter) {
78         mNativeAwPdfExporter = nativePdfExporter;
79         // Handle the cornercase that Webview.Destroy is called before the native side
80         // has a chance to complete the pdf exporting.
81         if (nativePdfExporter == 0 && mResultCallback != null) {
82             mResultCallback.onReceiveValue(false);
83             mResultCallback = null;
84         }
85     }
86 
getPrintDpi(PrintAttributes attributes)87     private static int getPrintDpi(PrintAttributes attributes) {
88         // TODO(sgurun) android print attributes support horizontal and
89         // vertical DPI. Chrome has only one DPI. Revisit this.
90         int horizontalDpi = attributes.getResolution().getHorizontalDpi();
91         int verticalDpi = attributes.getResolution().getVerticalDpi();
92         if (horizontalDpi != verticalDpi) {
93             Log.w(TAG, "Horizontal and vertical DPIs differ. Using horizontal DPI " +
94                     " hDpi=" + horizontalDpi + " vDPI=" + verticalDpi);
95         }
96         return horizontalDpi;
97     }
98 
99     @CalledByNative
didExportPdf(boolean success)100     private void didExportPdf(boolean success) {
101         mResultCallback.onReceiveValue(success);
102         mResultCallback = null;
103         mAttributes = null;
104         // The caller should close the file.
105         mFd = null;
106     }
107 
108     @CalledByNative
getPageWidth()109     private int getPageWidth() {
110         return mAttributes.getMediaSize().getWidthMils();
111     }
112 
113     @CalledByNative
getPageHeight()114     private int getPageHeight() {
115         return mAttributes.getMediaSize().getHeightMils();
116     }
117 
118     @CalledByNative
getDpi()119     private int getDpi() {
120         return getPrintDpi(mAttributes);
121     }
122 
123     @CalledByNative
getLeftMargin()124     private int getLeftMargin() {
125         return mAttributes.getMinMargins().getLeftMils();
126     }
127 
128     @CalledByNative
getRightMargin()129     private int getRightMargin() {
130         return mAttributes.getMinMargins().getRightMils();
131     }
132 
133     @CalledByNative
getTopMargin()134     private int getTopMargin() {
135         return mAttributes.getMinMargins().getTopMils();
136     }
137 
138     @CalledByNative
getBottomMargin()139     private int getBottomMargin() {
140         return mAttributes.getMinMargins().getBottomMils();
141     }
142 
nativeExportToPdf(long nativeAwPdfExporter, int fd, CancellationSignal cancellationSignal)143     private native void nativeExportToPdf(long nativeAwPdfExporter, int fd,
144             CancellationSignal cancellationSignal);
145 }
146