blob: 15f9d8524e7c7241cca163e26d2deed9dcd35b56 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.printing;
import android.print.PrintDocumentAdapter;
import android.util.SparseArray;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
/**
* This class is responsible for communicating with its native counterpart through JNI to handle
* the generation of PDF. On the Java side, it works with a {@link PrintingController}
* to talk to the framework.
*/
@JNINamespace("printing")
public class PrintingContext implements PrintingContextInterface {
private static final String TAG = "cr.printing";
/**
* Mapping from a file descriptor (as originally provided from
* {@link PrintDocumentAdapter#onWrite}) to a PrintingContext.
*
* This is static because a static method of the native code (inside PrintingContextAndroid)
* needs to find Java PrintingContext class corresponding to a file descriptor.
**/
private static final SparseArray<PrintingContext> PRINTING_CONTEXT_MAP =
new SparseArray<PrintingContext>();
/** The controller this object interacts with, which in turn communicates with the framework. */
private final PrintingController mController;
/** The pointer to the native PrintingContextAndroid object. */
private final long mNativeObject;
private PrintingContext(long ptr) {
mController = PrintingControllerImpl.getInstance();
mNativeObject = ptr;
}
/**
* Updates PRINTING_CONTEXT_MAP to map from the file descriptor to this object.
* @param fileDescriptor The file descriptor passed down from
* {@link PrintDocumentAdapter#onWrite}.
* @param delete If true, delete the entry (if it exists). If false, add it to the map.
*/
@Override
public void updatePrintingContextMap(int fileDescriptor, boolean delete) {
ThreadUtils.assertOnUiThread();
if (delete) {
PRINTING_CONTEXT_MAP.remove(fileDescriptor);
} else {
PRINTING_CONTEXT_MAP.put(fileDescriptor, this);
}
}
/**
* Notifies the native side that the user just chose a new set of printing settings.
* @param success True if the user has chosen printing settings necessary for the
* generation of PDF, false if there has been a problem.
*/
@Override
public void askUserForSettingsReply(boolean success) {
nativeAskUserForSettingsReply(mNativeObject, success);
}
@CalledByNative
public static PrintingContext create(long nativeObjectPointer) {
ThreadUtils.assertOnUiThread();
return new PrintingContext(nativeObjectPointer);
}
@CalledByNative
public int getFileDescriptor() {
ThreadUtils.assertOnUiThread();
return mController.getFileDescriptor();
}
@CalledByNative
public int getDpi() {
ThreadUtils.assertOnUiThread();
return mController.getDpi();
}
@CalledByNative
public int getWidth() {
ThreadUtils.assertOnUiThread();
return mController.getPageWidth();
}
@CalledByNative
public int getHeight() {
ThreadUtils.assertOnUiThread();
return mController.getPageHeight();
}
@CalledByNative
public void showPrintDialog() {
ThreadUtils.assertOnUiThread();
if (mController != null) { // The native side doesn't check if printing is enabled
mController.startPendingPrint(this);
} else {
Log.d(TAG, "Unable to start printing, feature not available.");
// Printing disabled. Notify the native side to stop waiting.
showSystemDialogDone();
}
}
@CalledByNative
public static void pdfWritingDone(int fd, int pageCount) {
ThreadUtils.assertOnUiThread();
// TODO(cimamoglu): Do something when fd == -1.
if (PRINTING_CONTEXT_MAP.get(fd) != null) {
ThreadUtils.assertOnUiThread();
PrintingContext printingContext = PRINTING_CONTEXT_MAP.get(fd);
printingContext.mController.pdfWritingDone(pageCount);
PRINTING_CONTEXT_MAP.remove(fd);
} else {
Log.d(TAG, "No PrintingContext found for fd %d, can't notify print completion.", fd);
}
}
@CalledByNative
public int[] getPages() {
ThreadUtils.assertOnUiThread();
return mController.getPageNumbers();
}
@CalledByNative
public void askUserForSettings(final int maxPages) {
ThreadUtils.assertOnUiThread();
// If the printing dialog has already finished, tell Chromium that operation is cancelled.
if (mController.hasPrintingFinished()) {
// NOTE: We don't call nativeAskUserForSettingsReply (hence Chromium callback in
// AskUserForSettings callback) twice. See {@link PrintingControllerImpl#onFinish}
// for more explanation.
askUserForSettingsReply(false);
} else {
mController.setPrintingContext(this);
updatePrintingContextMap(mController.getFileDescriptor(), /* delete = */ false);
askUserForSettingsReply(true);
}
}
@Override
public void showSystemDialogDone() {
nativeShowSystemDialogDone(mNativeObject);
}
private native void nativeAskUserForSettingsReply(
long nativePrintingContextAndroid,
boolean success);
private native void nativeShowSystemDialogDone(long nativePrintingContextAndroid);
}