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