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
5package org.chromium.android_webview;
6
7import android.content.Context;
8import android.os.Bundle;
9import android.os.CancellationSignal;
10import android.os.ParcelFileDescriptor;
11import android.print.PageRange;
12import android.print.PrintAttributes;
13import android.print.PrintDocumentAdapter;
14import android.print.PrintDocumentInfo;
15
16import android.util.Log;
17
18import android.webkit.ValueCallback;
19
20
21/**
22 * Adapter for printing Webview. This class implements the abstract
23 * system class PrintDocumentAdapter and hides all printing details from
24 * the developer.
25 */
26public class AwPrintDocumentAdapter extends PrintDocumentAdapter {
27
28    private static final String TAG = "AwPrintDocumentAdapter";
29
30    private AwPdfExporter mPdfExporter;
31    private PrintAttributes mAttributes;
32
33    /**
34     * Constructor.
35     *
36     * @param pdfExporter The PDF exporter to export the webview contents to a PDF file.
37     */
38    public AwPrintDocumentAdapter(AwPdfExporter pdfExporter) {
39        mPdfExporter = pdfExporter;
40    }
41
42    @Override
43    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
44            CancellationSignal cancellationSignal, LayoutResultCallback callback,
45            Bundle metadata) {
46        mAttributes = newAttributes;
47        // TODO(sgurun) pass a meaningful string once b/10705082 is resolved
48        PrintDocumentInfo documentInfo = new PrintDocumentInfo
49                .Builder("webview")
50                .build();
51        // TODO(sgurun) once componentization is done, do layout changes and
52        // generate PDF here, set the page range information to documentinfo
53        // and call onLayoutFinished with true/false depending on whether
54        // layout actually changed.
55        callback.onLayoutFinished(documentInfo, true);
56    }
57
58    @Override
59    public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
60            CancellationSignal cancellationSignal, WriteResultCallback callback) {
61        // TODO(sgurun) sometimes we receive spurious onWrite. ignore it.
62        if (mAttributes.getMediaSize() == null) {
63            throw new  IllegalArgumentException("attributes must specify a media size");
64        }
65        if (mAttributes.getResolution() == null) {
66            throw new IllegalArgumentException("attributes must specify print resolution");
67        }
68        if (mAttributes.getMinMargins() == null) {
69            throw new IllegalArgumentException("attributes must specify margins");
70        }
71        // TODO(sgurun) get rid of AwPdfExportAttributes after upstreaming
72        // and move this logic to AwPdfExporter
73        AwPdfExportAttributes pdfAttributes = new AwPdfExportAttributes();
74        pdfAttributes.pageWidth = mAttributes.getMediaSize().getWidthMils();
75        pdfAttributes.pageHeight = mAttributes.getMediaSize().getHeightMils();
76        pdfAttributes.dpi = getPrintDpi(mAttributes);
77        pdfAttributes.leftMargin = mAttributes.getMinMargins().getLeftMils();
78        pdfAttributes.rightMargin = mAttributes.getMinMargins().getRightMils();
79        pdfAttributes.topMargin = mAttributes.getMinMargins().getTopMils();
80        pdfAttributes.bottomMargin = mAttributes.getMinMargins().getBottomMils();
81        exportPdf(destination, pdfAttributes, cancellationSignal, callback);
82    }
83
84    private static int getPrintDpi(PrintAttributes attributes) {
85        // TODO(sgurun) android print attributes support horizontal and
86        // vertical DPI. Chrome has only one DPI. Revisit this.
87        int horizontalDpi = attributes.getResolution().getHorizontalDpi();
88        int verticalDpi = attributes.getResolution().getVerticalDpi();
89        if (horizontalDpi != verticalDpi) {
90            Log.w(TAG, "Horizontal and vertical DPIs differ. Using horizontal DPI " +
91                    " hDpi=" + horizontalDpi + " vDPI=" + verticalDpi);
92        }
93        return horizontalDpi;
94    }
95
96    private void exportPdf(final ParcelFileDescriptor destination,
97            final AwPdfExportAttributes attributes,
98            final CancellationSignal signal,
99            final WriteResultCallback callback) {
100        mPdfExporter.exportToPdf(destination, attributes, new ValueCallback<Boolean>() {
101                    @Override
102                    public void onReceiveValue(Boolean value) {
103                        if (value) {
104                            callback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES});
105                        } else {
106                            // TODO(sgurun) localized error message
107                            callback.onWriteFailed(null);
108                        }
109                    }
110                }, signal);
111    }
112}
113
114