0

Add checks for android printing

Adds a null check for the WebContent used to set up
renderer initiated print jobs and some warnings to be
able to follow failures in the process.

BUG=528909

Review URL: https://codereview.chromium.org/1338333002

Cr-Commit-Position: refs/heads/master@{#349121}
This commit is contained in:
dgn
2015-09-16 07:34:19 -07:00
committed by Commit bot
parent 7a0c427f01
commit e94f112042
6 changed files with 100 additions and 8 deletions
chrome
android
java
src
org
chromium
chrome
browser
javatests
src
org
chromium
chrome
browser
printing/android/java/src/org/chromium/printing

@ -6,6 +6,7 @@ package org.chromium.chrome.browser.printing;
import android.text.TextUtils;
import org.chromium.base.Log;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.printing.Printable;
@ -19,6 +20,7 @@ import java.lang.ref.WeakReference;
*/
public class TabPrinter implements Printable {
private static String sDefaultTitle;
private static final String TAG = "cr.printing";
private final WeakReference<Tab> mTab;
@ -33,7 +35,11 @@ public class TabPrinter implements Printable {
@Override
public boolean print() {
Tab tab = mTab.get();
return tab != null && tab.isInitialized() && tab.print();
if (tab == null || !tab.isInitialized()) {
Log.d(TAG, "Tab not ready, unable to start printing.");
return false;
}
return tab.print();
}
@Override

@ -13,14 +13,19 @@ import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.TestFileUtil;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeActivityTestCaseBase;
import org.chromium.chrome.test.util.browser.TabTitleObserver;
import org.chromium.content.common.ContentSwitches;
import org.chromium.printing.PrintDocumentAdapterWrapper;
import org.chromium.printing.PrintManagerDelegate;
import org.chromium.printing.PrintingControllerImpl;
@ -150,6 +155,31 @@ public class PrintingControllerTest extends ChromeActivityTestCaseBase<ChromeAct
}
/**
* Test for http://crbug.com/528909
*/
@CommandLineFlags.Add(
{ContentSwitches.DISABLE_POPUP_BLOCKING, ChromeSwitches.DISABLE_DOCUMENT_MODE})
@SmallTest
@Feature({"Printing"})
public void testPrintClosedWindow() throws Throwable {
String html = "<html><head><title>printwindowclose</title></head><body><script>"
+ "function printClosedWindow() {"
+ " w = window.open(); w.close();"
+ " setTimeout(()=>{w.print(); document.title='completed'}, 0);"
+ "}</script></body></html>";
startMainActivityWithURL("data:text/html;charset=utf-8," + html);
Tab mTab = getActivity().getActivityTab();
assertEquals("title does not match initial title", "printwindowclose", mTab.getTitle());
TabTitleObserver mOnTitleUpdatedHelper = new TabTitleObserver(mTab, "completed");
runJavaScriptCodeInCurrentTab("printClosedWindow();");
mOnTitleUpdatedHelper.waitForTitleUpdate(2);
assertEquals("JS did not finish running", "completed", mTab.getTitle());
}
private PrintingControllerImpl createControllerOnUiThread() {
try {
final FutureTask<PrintingControllerImpl> task =

@ -219,7 +219,8 @@ void PrintJobWorker::GetSettingsWithUI(
static_cast<PrintingContextDelegate*>(printing_context_delegate_.get());
content::WebContents* web_contents =
printing_context_delegate->GetWebContents();
TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
TabAndroid* tab =
web_contents ? TabAndroid::FromWebContents(web_contents) : nullptr;
// Regardless of whether the following call fails or not, the javascript
// call will return since startPendingPrint will make it return immediately

@ -9,13 +9,22 @@ import android.content.Context;
import android.os.Build;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintJob;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.text.TextUtils;
import org.chromium.base.Log;
import org.chromium.base.annotations.RemovableInRelease;
import java.util.List;
/**
* An implementation of {@link PrintManagerDelegate} using the Android framework print manager.
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public class PrintManagerDelegateImpl implements PrintManagerDelegate {
private static final String TAG = "cr.printing";
private final PrintManager mPrintManager;
public PrintManagerDelegateImpl(Context context) {
@ -25,7 +34,45 @@ public class PrintManagerDelegateImpl implements PrintManagerDelegate {
@Override
public void print(String printJobName, PrintDocumentAdapter documentAdapter,
PrintAttributes attributes) {
dumpJobStatesForDebug();
mPrintManager.print(printJobName, documentAdapter, attributes);
}
@RemovableInRelease
private void dumpJobStatesForDebug() {
List<PrintJob> printJobs = mPrintManager.getPrintJobs();
String[] states = new String[printJobs.size()];
for (int i = 0; i < printJobs.size(); i++) {
String stateString;
switch (printJobs.get(i).getInfo().getState()) {
case PrintJobInfo.STATE_CREATED:
stateString = "STATE_CREATED";
break;
case PrintJobInfo.STATE_QUEUED:
stateString = "STATE_QUEUED";
break;
case PrintJobInfo.STATE_STARTED:
stateString = "STATE_STARTED";
break;
case PrintJobInfo.STATE_BLOCKED:
stateString = "STATE_BLOCKED";
break;
case PrintJobInfo.STATE_FAILED:
stateString = "STATE_FAILED";
break;
case PrintJobInfo.STATE_COMPLETED:
stateString = "STATE_COMPLETED";
break;
case PrintJobInfo.STATE_CANCELED:
stateString = "STATE_CANCELED";
break;
default:
stateString = "STATE_UNKNOWN";
break;
}
states[i] = stateString;
}
Log.v(TAG, "Initiating new print with states in queue: {%s}", TextUtils.join(", ", states));
}
}

@ -7,6 +7,7 @@ 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;
@ -18,7 +19,7 @@ import org.chromium.base.annotations.JNINamespace;
*/
@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.
@ -102,6 +103,7 @@ public class PrintingContext implements PrintingContextInterface {
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();
}
@ -116,6 +118,8 @@ public class PrintingContext implements PrintingContextInterface {
PrintingContext printingContext = PRINTING_CONTEXT_MAP.get(fd);
printingContext.mController.pdfWritingDone(success);
PRINTING_CONTEXT_MAP.remove(fd);
} else {
Log.d(TAG, "No PrintingContext found for fd %d, can't notify print completion.", fd);
}
}

@ -12,8 +12,8 @@ import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintDocumentInfo;
import android.util.Log;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.printing.PrintDocumentAdapterWrapper.PdfGenerator;
@ -31,8 +31,7 @@ import java.util.Iterator;
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public class PrintingControllerImpl implements PrintingController, PdfGenerator {
private static final String LOG_TAG = "PrintingControllerImpl";
private static final String TAG = "cr.printing";
/**
* This is used for both initial state and a completed state (i.e. starting from either
@ -181,7 +180,10 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
@Override
public void setPendingPrint(final Printable printable, PrintManagerDelegate printManager) {
if (mIsBusy) return;
if (mIsBusy) {
Log.d(TAG, "Pending print can't be set. PrintingController is busy.");
return;
}
mPrintable = printable;
mPrintManager = printManager;
}
@ -189,7 +191,9 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
@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 (mIsBusy) Log.d(TAG, "Pending print can't be started. PrintingController is busy.");
else Log.d(TAG, "Pending print can't be started. No PrintManager provided.");
if (printingContext != null) printingContext.showSystemDialogDone();
return;
}