summaryrefslogtreecommitdiffstats
path: root/printing
diff options
context:
space:
mode:
authordgn <dgn@chromium.org>2014-12-15 13:11:23 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-15 21:11:50 +0000
commit4c172eea8b6649f1c1c620d1daa20ce733cee9e1 (patch)
tree9ac7df8f0058d80866716752ec2563d6fb0b3f79 /printing
parent7dac4befc4743666c0fcbb92d02ccd3c1c6a8389 (diff)
downloadchromium_src-4c172eea8b6649f1c1c620d1daa20ce733cee9e1.zip
chromium_src-4c172eea8b6649f1c1c620d1daa20ce733cee9e1.tar.gz
chromium_src-4c172eea8b6649f1c1c620d1daa20ce733cee9e1.tar.bz2
Implement window.print() on Android
Essentially wires up the window.print() and the basic printing path to Android framwork's PrintManager. The changes affect the basic printing path using PrintingMessageFilter::OnScriptedPrint. When calling window.print() on Android, it would now be called twice. The first time is directly after the JS call, OnScriptedPrint is called with a parameter telling it that it's being called from JS. It will then end up calling PrintJobWorker::GetSettings, forwarding that information. PrintJobWorker then takes care of calling PrintingController through JNI, joining the same code path used when printing from chrome's menu in android: Android framework's PrintManager is invoked, and it manages the preview, using the tab to generate the output as the user changes his/her preferences. Why so many changes for just that: the window.print() call is blocked until the end of the process by message pumping. It has to be disabled when printing is finished. It is currently done by setting a callback in the current PrintingContext, that will be called when printing is done. PrintingController stores the reference to it, but here we have two queries at the same time, and only the latest PrintingContext would be stored. I added a field to store separately the one coming from the initial call, so that it can be used when printing is done to stop the message pumping. TL;DR: When window.print() is called, the basic printing path is used to forward the query to PrintManager. The PrintManager then uses almost the same path to actually print the document (as previously implemented to power the 'Print...' entry in the menu). The changes are mostly to ensure that JS returns when printing is completed and not before (or never). BUG=437338 Review URL: https://codereview.chromium.org/740983002 Cr-Commit-Position: refs/heads/master@{#308416}
Diffstat (limited to 'printing')
-rw-r--r--printing/android/java/src/org/chromium/printing/PrintingContext.java18
-rw-r--r--printing/android/java/src/org/chromium/printing/PrintingContextInterface.java6
-rw-r--r--printing/android/java/src/org/chromium/printing/PrintingController.java23
-rw-r--r--printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java40
-rw-r--r--printing/printing_context.h4
-rw-r--r--printing/printing_context_android.cc17
-rw-r--r--printing/printing_context_android.h7
-rw-r--r--printing/printing_context_linux.cc1
-rw-r--r--printing/printing_context_linux.h1
-rw-r--r--printing/printing_context_mac.h1
-rw-r--r--printing/printing_context_mac.mm1
-rw-r--r--printing/printing_context_no_system_dialog.cc1
-rw-r--r--printing/printing_context_no_system_dialog.h1
-rw-r--r--printing/printing_context_system_dialog_win.cc1
-rw-r--r--printing/printing_context_system_dialog_win.h1
-rw-r--r--printing/printing_context_win.cc3
-rw-r--r--printing/printing_context_win.h1
-rw-r--r--printing/printing_context_win_unittest.cc1
18 files changed, 118 insertions, 10 deletions
diff --git a/printing/android/java/src/org/chromium/printing/PrintingContext.java b/printing/android/java/src/org/chromium/printing/PrintingContext.java
index e50f0ce..6dc7b55 100644
--- a/printing/android/java/src/org/chromium/printing/PrintingContext.java
+++ b/printing/android/java/src/org/chromium/printing/PrintingContext.java
@@ -97,6 +97,17 @@ public class PrintingContext implements PrintingContextInterface {
}
@CalledByNative
+ public void showPrintDialog() {
+ ThreadUtils.assertOnUiThread();
+ if (mController != null) { // The native side doesn't check if printing is enabled
+ mController.startPendingPrint(this);
+ } else {
+ // Printing disabled. Notify the native side to stop waiting.
+ showSystemDialogDone();
+ }
+ }
+
+ @CalledByNative
public static void pdfWritingDone(int fd, boolean success) {
ThreadUtils.assertOnUiThread();
// TODO(cimamoglu): Do something when fd == -1.
@@ -129,7 +140,14 @@ public class PrintingContext implements PrintingContextInterface {
}
}
+ @Override
+ public void showSystemDialogDone() {
+ nativeShowSystemDialogDone(mNativeObject);
+ }
+
private native void nativeAskUserForSettingsReply(
long nativePrintingContextAndroid,
boolean success);
+
+ private native void nativeShowSystemDialogDone(long nativePrintingContextAndroid);
}
diff --git a/printing/android/java/src/org/chromium/printing/PrintingContextInterface.java b/printing/android/java/src/org/chromium/printing/PrintingContextInterface.java
index 80369b3..3bc3e82 100644
--- a/printing/android/java/src/org/chromium/printing/PrintingContextInterface.java
+++ b/printing/android/java/src/org/chromium/printing/PrintingContextInterface.java
@@ -21,4 +21,10 @@ public interface PrintingContextInterface {
* @param success True if the settings are successfully prepared to be used by the native side.
*/
void askUserForSettingsReply(boolean success);
+
+ /**
+ * Notifies the native side that the printing process is completed. This method should be
+ * called when the process was initiated by the native side (window.print())
+ */
+ void showSystemDialogDone();
}
diff --git a/printing/android/java/src/org/chromium/printing/PrintingController.java b/printing/android/java/src/org/chromium/printing/PrintingController.java
index 92be968..4753373 100644
--- a/printing/android/java/src/org/chromium/printing/PrintingController.java
+++ b/printing/android/java/src/org/chromium/printing/PrintingController.java
@@ -73,7 +73,7 @@ public interface PrintingController {
* Sets PrintingContext currently associated with the controller.
*
* This needs to be called after PrintingContext object is created. Firstly its native
- * counterpart is created, and then the Java. PrintingController implementation
+ * counterpart is created, and then the Java. PrintingController implementation
* needs this to interact with the native side, since JNI is built on PrintingContext.
**/
void setPrintingContext(final PrintingContextInterface printingContext);
@@ -82,4 +82,25 @@ public interface PrintingController {
* @return Whether a complete PDF generation cycle inside Chromium has been completed.
*/
boolean hasPrintingFinished();
+
+ /**
+ * Sets the data required to initiate a printing process. The process can later be started using
+ * {@link #startPendingPrint(PrintingContextInterface)}.
+ *
+ * @param printable An object capable of starting native side PDF generation, i.e. typically
+ * a Tab.
+ * @param printManager The print manager that manages the print job.
+ */
+ void setPendingPrint(final Printable printable, final PrintManagerDelegate printManager);
+
+ /**
+ * Starts printing, provided that the current object already has sufficient data to start the
+ * process. (using {@link #setPendingPrint(Printable, PrintManagerDelegate)} for example)
+ *
+ * @param jsOriginatedPrintingContext The printingContext holding the callback to be used to
+ * reply when javascript can resume. When printing is done (or could not start),
+ * {@link PrintingContextInterface#showSystemDialogDone()} will be called on this object.
+ */
+ void startPendingPrint(PrintingContextInterface jsOriginatedPrintingContext);
+
}
diff --git a/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java b/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java
index 16e0456..55915e3 100644
--- a/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java
+++ b/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java
@@ -10,6 +10,7 @@ import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintDocumentInfo;
+import android.util.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.printing.PrintDocumentAdapterWrapper.PdfGenerator;
@@ -47,6 +48,12 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
private PrintingContextInterface mPrintingContext;
+ /**
+ * The context of a query initiated by window.print(), stored here to allow syncrhonization
+ * with javascript.
+ */
+ private PrintingContextInterface mContextFromScriptInitiation;
+
/** The file descriptor into which the PDF will be written. Provided by the framework. */
private int mFileDescriptor;
@@ -86,6 +93,8 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
private boolean mIsBusy = false;
+ private PrintManagerDelegate mPrintManager;
+
private PrintingControllerImpl(PrintDocumentAdapterWrapper printDocumentAdapterWrapper,
String errorText) {
mErrorMessage = errorText;
@@ -168,11 +177,30 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
}
@Override
- public void startPrint(final Printable printable, PrintManagerDelegate printManager) {
+ public void setPendingPrint(final Printable printable, PrintManagerDelegate printManager) {
if (mIsBusy) return;
- mIsBusy = true;
mPrintable = printable;
- mPrintDocumentAdapterWrapper.print(printManager, printable.getTitle());
+ mPrintManager = printManager;
+ }
+
+ @Override
+ public void startPendingPrint(PrintingContextInterface printingContext) {
+ if (mIsBusy || mPrintManager == null) {
+ Log.w(LOG_TAG, "Pending print can't be started. Is might be busy or not initialized.");
+ if (printingContext != null) printingContext.showSystemDialogDone();
+ return;
+ }
+ mContextFromScriptInitiation = printingContext;
+ mIsBusy = true;
+ mPrintDocumentAdapterWrapper.print(mPrintManager, mPrintable.getTitle());
+ mPrintManager = null;
+ }
+
+ @Override
+ public void startPrint(final Printable printable, PrintManagerDelegate printManager) {
+ if (mIsBusy) return;
+ setPendingPrint(printable, printManager);
+ startPendingPrint(null);
}
@Override
@@ -321,6 +349,12 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
mPrintingContext.updatePrintingContextMap(mFileDescriptor, true);
mPrintingContext = null;
}
+
+ if (mContextFromScriptInitiation != null) {
+ mContextFromScriptInitiation.showSystemDialogDone();
+ mContextFromScriptInitiation = null;
+ }
+
mPrintingState = PRINTING_STATE_FINISHED;
closeFileDescriptor(mFileDescriptor);
diff --git a/printing/printing_context.h b/printing/printing_context.h
index 0cc4731..40c8d33 100644
--- a/printing/printing_context.h
+++ b/printing/printing_context.h
@@ -55,8 +55,12 @@ class PRINTING_EXPORT PrintingContext {
// context with the select device settings. The result of the call is returned
// in the callback. This is necessary for Linux, which only has an
// asynchronous printing API.
+ // On Android, when |is_scripted| is true, calling it initiates a full
+ // printing flow from the framework's PrintManager.
+ // (see https://codereview.chromium.org/740983002/)
virtual void AskUserForSettings(int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) = 0;
// Selects the user's default printer and format. Updates the context with the
diff --git a/printing/printing_context_android.cc b/printing/printing_context_android.cc
index 64139c8..3be1251 100644
--- a/printing/printing_context_android.cc
+++ b/printing/printing_context_android.cc
@@ -82,6 +82,7 @@ PrintingContextAndroid::~PrintingContextAndroid() {
void PrintingContextAndroid::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
// This method is always run in the UI thread.
callback_ = callback;
@@ -93,9 +94,13 @@ void PrintingContextAndroid::AskUserForSettings(
reinterpret_cast<intptr_t>(this)));
}
- Java_PrintingContext_pageCountEstimationDone(env,
- j_printing_context_.obj(),
- max_pages);
+ if (is_scripted) {
+ Java_PrintingContext_showPrintDialog(env, j_printing_context_.obj());
+ } else {
+ Java_PrintingContext_pageCountEstimationDone(env,
+ j_printing_context_.obj(),
+ max_pages);
+ }
}
void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv* env,
@@ -132,6 +137,12 @@ void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv* env,
callback_.Run(OK);
}
+void PrintingContextAndroid::ShowSystemDialogDone(JNIEnv* env,
+ jobject obj) {
+ // Settings are not updated, callback is called only to unblock javascript.
+ callback_.Run(CANCEL);
+}
+
PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
DCHECK(!in_print_job_);
diff --git a/printing/printing_context_android.h b/printing/printing_context_android.h
index 32f11be..3823b28 100644
--- a/printing/printing_context_android.h
+++ b/printing/printing_context_android.h
@@ -14,8 +14,7 @@
namespace printing {
-// Android subclass of PrintingContext. The implementation for this header file
-// resides in Chrome for Android repository. This class communicates with the
+// Android subclass of PrintingContext. This class communicates with the
// Java side through JNI.
class PRINTING_EXPORT PrintingContextAndroid : public PrintingContext {
public:
@@ -30,10 +29,14 @@ class PRINTING_EXPORT PrintingContextAndroid : public PrintingContext {
// printing operation is canceled.
void AskUserForSettingsReply(JNIEnv* env, jobject obj, jboolean success);
+ // Called from Java, when a printing process initiated by a script finishes.
+ void ShowSystemDialogDone(JNIEnv* env, jobject obj);
+
// PrintingContext implementation.
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
virtual Result UseDefaultSettings() override;
virtual gfx::Size GetPdfPaperSizeDeviceUnits() override;
diff --git a/printing/printing_context_linux.cc b/printing/printing_context_linux.cc
index 8e23577..a1fc1f6 100644
--- a/printing/printing_context_linux.cc
+++ b/printing/printing_context_linux.cc
@@ -67,6 +67,7 @@ void PrintingContextLinux::PrintDocument(const MetafilePlayer& metafile) {
void PrintingContextLinux::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
if (!print_dialog_) {
// Can only get here if the renderer is sending bad messages.
diff --git a/printing/printing_context_linux.h b/printing/printing_context_linux.h
index b0ea1f6..d6968d9 100644
--- a/printing/printing_context_linux.h
+++ b/printing/printing_context_linux.h
@@ -40,6 +40,7 @@ class PRINTING_EXPORT PrintingContextLinux : public PrintingContext {
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
virtual gfx::Size GetPdfPaperSizeDeviceUnits() override;
virtual Result UseDefaultSettings() override;
diff --git a/printing/printing_context_mac.h b/printing/printing_context_mac.h
index 561b25d..51a1a1c 100644
--- a/printing/printing_context_mac.h
+++ b/printing/printing_context_mac.h
@@ -27,6 +27,7 @@ class PRINTING_EXPORT PrintingContextMac : public PrintingContext {
// PrintingContext implementation.
void AskUserForSettings(int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
Result UseDefaultSettings() override;
gfx::Size GetPdfPaperSizeDeviceUnits() override;
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index 23d2d84..be3df6d 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -85,6 +85,7 @@ PrintingContextMac::~PrintingContextMac() {
void PrintingContextMac::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
// Third-party print drivers seem to be an area prone to raising exceptions.
// This will allow exceptions to be raised, but does not handle them. The
diff --git a/printing/printing_context_no_system_dialog.cc b/printing/printing_context_no_system_dialog.cc
index 7ae10dd..b6246d6 100644
--- a/printing/printing_context_no_system_dialog.cc
+++ b/printing/printing_context_no_system_dialog.cc
@@ -31,6 +31,7 @@ PrintingContextNoSystemDialog::~PrintingContextNoSystemDialog() {
void PrintingContextNoSystemDialog::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
// We don't want to bring up a dialog here. Ever. Just signal the callback.
callback.Run(OK);
diff --git a/printing/printing_context_no_system_dialog.h b/printing/printing_context_no_system_dialog.h
index c155e33..6cc8c2a 100644
--- a/printing/printing_context_no_system_dialog.h
+++ b/printing/printing_context_no_system_dialog.h
@@ -24,6 +24,7 @@ class PRINTING_EXPORT PrintingContextNoSystemDialog : public PrintingContext {
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
virtual Result UseDefaultSettings() override;
virtual gfx::Size GetPdfPaperSizeDeviceUnits() override;
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
index 4e1e8f1..19fc4271 100644
--- a/printing/printing_context_system_dialog_win.cc
+++ b/printing/printing_context_system_dialog_win.cc
@@ -21,6 +21,7 @@ PrintingContextSytemDialogWin::~PrintingContextSytemDialogWin() {
void PrintingContextSytemDialogWin::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
DCHECK(!in_print_job_);
dialog_box_dismissed_ = false;
diff --git a/printing/printing_context_system_dialog_win.h b/printing/printing_context_system_dialog_win.h
index 0a797b2..216cdd3 100644
--- a/printing/printing_context_system_dialog_win.h
+++ b/printing/printing_context_system_dialog_win.h
@@ -25,6 +25,7 @@ class PRINTING_EXPORT PrintingContextSytemDialogWin
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
virtual void Cancel() override;
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index c396b1a..678e7f2 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -54,6 +54,7 @@ PrintingContextWin::~PrintingContextWin() {
void PrintingContextWin::AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) {
NOTIMPLEMENTED();
}
@@ -208,7 +209,7 @@ PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
// Update data using DocumentProperties.
if (show_system_dialog) {
PrintingContext::Result result = PrintingContext::FAILED;
- AskUserForSettings(0, false, base::Bind(&AssingResult, &result));
+ AskUserForSettings(0, false, false, base::Bind(&AssingResult, &result));
return result;
} else {
scoped_dev_mode = CreateDevMode(printer.Get(), scoped_dev_mode.get());
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h
index 933162a..7ed8b27 100644
--- a/printing/printing_context_win.h
+++ b/printing/printing_context_win.h
@@ -24,6 +24,7 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext {
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
+ bool is_scripted,
const PrintSettingsCallback& callback) override;
virtual Result UseDefaultSettings() override;
virtual gfx::Size GetPdfPaperSizeDeviceUnits() override;
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc
index 6777434..a758ca6 100644
--- a/printing/printing_context_win_unittest.cc
+++ b/printing/printing_context_win_unittest.cc
@@ -161,6 +161,7 @@ TEST_F(PrintingContextTest, PrintAll) {
context.AskUserForSettings(
123,
false,
+ false,
base::Bind(&PrintingContextTest::PrintSettingsCallback,
base::Unretained(this)));
EXPECT_EQ(PrintingContext::OK, result());