Index: chrome/renderer/printing/print_web_view_helper.cc |
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc |
index 6077438cd49ddcc9b81495bda829bfc049f538f2..4f8be2e6dd30fb636465dd7e82b973bdde8bdaf8 100644 |
--- a/chrome/renderer/printing/print_web_view_helper.cc |
+++ b/chrome/renderer/printing/print_web_view_helper.cc |
@@ -68,6 +68,12 @@ const char kPageLoadScriptFormat[] = |
const char kPageSetupScriptFormat[] = "setup(%s);"; |
+#if defined(ENABLE_FULL_PRINTING) |
+bool g_is_preview_enabled_ = true; |
+#else |
+bool g_is_preview_enabled_ = false; |
+#endif |
+ |
void ExecuteScript(blink::WebFrame* frame, |
const char* script_format, |
const base::Value& parameters) { |
@@ -791,14 +797,23 @@ PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view) |
PrintWebViewHelper::~PrintWebViewHelper() {} |
+// static |
+void PrintWebViewHelper::DisablePreview() { |
+ g_is_preview_enabled_ = false; |
+} |
+ |
bool PrintWebViewHelper::IsScriptInitiatedPrintAllowed( |
blink::WebFrame* frame, bool user_initiated) { |
#if defined(OS_ANDROID) |
return false; |
#endif // defined(OS_ANDROID) |
- if (is_scripted_printing_blocked_) |
- return false; |
- return true; |
+ // If preview is enabled, then the print dialog is tab modal, and the user |
+ // can always close the tab on a mis-behaving page (the system print dialog |
+ // is app modal). If the print was initiated through user action, don't |
+ // throttle. Or, if the command line flag to skip throttling has been set. |
+ return !is_scripted_printing_blocked_ && |
+ (user_initiated || g_is_preview_enabled_ || |
+ scripting_throttler_.IsAllowed(frame)); |
} |
void PrintWebViewHelper::DidStartLoading() { |
@@ -827,8 +842,13 @@ void PrintWebViewHelper::PrintPage(blink::WebLocalFrame* frame, |
if (!IsScriptInitiatedPrintAllowed(frame, user_initiated)) |
return; |
- print_preview_context_.InitWithFrame(frame); |
- RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); |
+ |
+ if (!g_is_preview_enabled_) { |
+ Print(frame, blink::WebNode()); |
+ } else { |
+ print_preview_context_.InitWithFrame(frame); |
+ RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); |
+ } |
} |
bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) { |
@@ -1220,13 +1240,17 @@ void PrintWebViewHelper::PrintNode(const blink::WebNode& node) { |
// Make a copy of the node, in case RenderView::OnContextMenuClosed resets |
// its |context_menu_node_|. |
- print_preview_context_.InitWithNode(node); |
- RequestPrintPreview(PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE); |
+ if (!g_is_preview_enabled_) { |
+ blink::WebNode duplicate_node(node); |
+ Print(duplicate_node.document().frame(), duplicate_node); |
+ } else { |
+ print_preview_context_.InitWithNode(node); |
+ RequestPrintPreview(PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE); |
+ } |
print_node_in_progress_ = false; |
} |
-#if !defined(DISABLE_BASIC_PRINTING) |
void PrintWebViewHelper::Print(blink::WebLocalFrame* frame, |
const blink::WebNode& node) { |
// If still not finished with earlier print request simply ignore. |
@@ -1259,8 +1283,8 @@ void PrintWebViewHelper::Print(blink::WebLocalFrame* frame, |
LOG(ERROR) << "RenderPagesForPrint failed"; |
DidFinishPrinting(FAIL_PRINT); |
} |
+ scripting_throttler_.Reset(); |
} |
-#endif // !DISABLE_BASIC_PRINTING |
void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { |
switch (result) { |
@@ -1970,4 +1994,49 @@ void PrintWebViewHelper::SetPrintPagesParams( |
settings.params.document_cookie)); |
} |
+PrintWebViewHelper::ScriptingThrottler::ScriptingThrottler() : count_(0) { |
+} |
+ |
+bool PrintWebViewHelper::ScriptingThrottler::IsAllowed(blink::WebFrame* frame) { |
+ const int kMinSecondsToIgnoreJavascriptInitiatedPrint = 2; |
+ const int kMaxSecondsToIgnoreJavascriptInitiatedPrint = 32; |
+ bool too_frequent = false; |
+ |
+ // Check if there is script repeatedly trying to print and ignore it if too |
+ // frequent. The first 3 times, we use a constant wait time, but if this |
+ // gets excessive, we switch to exponential wait time. So for a page that |
+ // calls print() in a loop the user will need to cancel the print dialog |
+ // after: [2, 2, 2, 4, 8, 16, 32, 32, ...] seconds. |
+ // This gives the user time to navigate from the page. |
+ if (count_ > 0) { |
+ base::TimeDelta diff = base::Time::Now() - last_print_; |
+ int min_wait_seconds = kMinSecondsToIgnoreJavascriptInitiatedPrint; |
+ if (count_ > 3) { |
+ min_wait_seconds = |
+ std::min(kMinSecondsToIgnoreJavascriptInitiatedPrint << (count_ - 3), |
+ kMaxSecondsToIgnoreJavascriptInitiatedPrint); |
+ } |
+ if (diff.InSeconds() < min_wait_seconds) { |
+ too_frequent = true; |
+ } |
+ } |
+ |
+ if (!too_frequent) { |
+ ++count_; |
+ last_print_ = base::Time::Now(); |
+ return true; |
+ } |
+ |
+ blink::WebString message( |
+ blink::WebString::fromUTF8("Ignoring too frequent calls to print().")); |
+ frame->addMessageToConsole(blink::WebConsoleMessage( |
+ blink::WebConsoleMessage::LevelWarning, message)); |
+ return false; |
+} |
+ |
+void PrintWebViewHelper::ScriptingThrottler::Reset() { |
+ // Reset counter on successful print. |
+ count_ = 0; |
+} |
+ |
} // namespace printing |