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 d3807778aa7861e1d28c7a9cf1917d12eb782fa4..55ef34a51488190379d15ebdaef07a55f3cced85 100644 |
--- a/chrome/renderer/printing/print_web_view_helper.cc |
+++ b/chrome/renderer/printing/print_web_view_helper.cc |
@@ -774,12 +774,17 @@ void PrepareFrameAndViewForPrint::FinishPrinting() { |
on_ready_.Reset(); |
} |
-PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view) |
+PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view, |
+ bool preview_enabled, |
Vitaly Buka (NO REVIEWS)
2014/09/08 09:43:59
preview_enabled is always false because you build
Marshall
2014/09/09 16:24:51
Building without ENABLE_FULL_PRINTING is problemat
|
+ bool scripted_print_throttling_disabled) |
: content::RenderViewObserver(render_view), |
content::RenderViewObserverTracker<PrintWebViewHelper>(render_view), |
reset_prep_frame_view_(false), |
+ is_preview_enabled_(preview_enabled), |
+ is_scripted_print_throttling_disabled_(scripted_print_throttling_disabled), |
is_print_ready_metafile_sent_(false), |
ignore_css_margins_(false), |
+ user_cancelled_scripted_print_count_(0), |
is_scripted_printing_blocked_(false), |
notify_browser_of_print_failure_(true), |
print_for_preview_(false), |
@@ -798,6 +803,14 @@ bool PrintWebViewHelper::IsScriptInitiatedPrintAllowed( |
#endif // defined(OS_ANDROID) |
if (is_scripted_printing_blocked_) |
return false; |
+ // 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. |
+ if (!is_scripted_print_throttling_disabled_ && |
+ !is_preview_enabled_ && |
+ !user_initiated) |
+ return !IsScriptInitiatedPrintTooFrequent(frame); |
return true; |
} |
@@ -827,8 +840,14 @@ void PrintWebViewHelper::PrintPage(blink::WebLocalFrame* frame, |
if (!IsScriptInitiatedPrintAllowed(frame, user_initiated)) |
return; |
- print_preview_context_.InitWithFrame(frame); |
- RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); |
+ IncrementScriptedPrintCount(); |
+ |
+ if (is_preview_enabled_) { |
+ print_preview_context_.InitWithFrame(frame); |
+ RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); |
+ } else { |
+ Print(frame, blink::WebNode()); |
+ } |
} |
bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) { |
@@ -851,6 +870,7 @@ bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) { |
void PrintWebViewHelper::OnPrintForPrintPreview( |
const base::DictionaryValue& job_settings) { |
+ DCHECK(is_preview_enabled_); |
// If still not finished with earlier print request simply ignore. |
if (prep_frame_view_) |
return; |
@@ -985,6 +1005,7 @@ bool PrintWebViewHelper::IsPrintToPdfRequested( |
} |
void PrintWebViewHelper::OnPrintPreview(const base::DictionaryValue& settings) { |
+ DCHECK(is_preview_enabled_); |
print_preview_context_.OnPrintPreview(); |
UMA_HISTOGRAM_ENUMERATION("PrintPreview.PreviewEvent", |
@@ -1187,6 +1208,7 @@ void PrintWebViewHelper::SetScriptedPrintBlocked(bool blocked) { |
} |
void PrintWebViewHelper::OnInitiatePrintPreview(bool selection_only) { |
+ DCHECK(is_preview_enabled_); |
blink::WebLocalFrame* frame = NULL; |
GetPrintFrame(&frame); |
DCHECK(frame); |
@@ -1220,8 +1242,13 @@ 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 (is_preview_enabled_) { |
+ print_preview_context_.InitWithNode(node); |
+ RequestPrintPreview(PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE); |
+ } else { |
+ blink::WebNode duplicate_node(node); |
+ Print(duplicate_node.document().frame(), duplicate_node); |
+ } |
print_node_in_progress_ = false; |
} |
@@ -1259,6 +1286,7 @@ void PrintWebViewHelper::Print(blink::WebLocalFrame* frame, |
LOG(ERROR) << "RenderPagesForPrint failed"; |
DidFinishPrinting(FAIL_PRINT); |
} |
+ ResetScriptedPrintCount(); |
} |
#endif // !DISABLE_BASIC_PRINTING |
@@ -1279,6 +1307,7 @@ void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { |
break; |
case FAIL_PREVIEW: |
+ DCHECK(is_preview_enabled_); |
int cookie = print_pages_params_ ? |
print_pages_params_->params.document_cookie : 0; |
if (notify_browser_of_print_failure_) { |
@@ -1446,6 +1475,7 @@ bool PrintWebViewHelper::UpdatePrintSettings( |
blink::WebLocalFrame* frame, |
const blink::WebNode& node, |
const base::DictionaryValue& passed_job_settings) { |
+ DCHECK(is_preview_enabled_); |
const base::DictionaryValue* job_settings = &passed_job_settings; |
base::DictionaryValue modified_job_settings; |
if (job_settings->empty()) { |
@@ -1588,6 +1618,54 @@ bool PrintWebViewHelper::CopyMetafileDataToSharedMem( |
} |
#endif // defined(OS_POSIX) |
+bool PrintWebViewHelper::IsScriptInitiatedPrintTooFrequent( |
+ 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 (user_cancelled_scripted_print_count_ > 0) { |
+ base::TimeDelta diff = base::Time::Now() - last_cancelled_script_print_; |
+ int min_wait_seconds = kMinSecondsToIgnoreJavascriptInitiatedPrint; |
+ if (user_cancelled_scripted_print_count_ > 3) { |
+ min_wait_seconds = std::min( |
+ kMinSecondsToIgnoreJavascriptInitiatedPrint << |
+ (user_cancelled_scripted_print_count_ - 3), |
+ kMaxSecondsToIgnoreJavascriptInitiatedPrint); |
+ } |
+ if (diff.InSeconds() < min_wait_seconds) { |
+ too_frequent = true; |
+ } |
+ } |
+ |
+ if (!too_frequent) |
+ return false; |
+ |
+ blink::WebString message( |
+ blink::WebString::fromUTF8("Ignoring too frequent calls to print().")); |
+ frame->addMessageToConsole( |
+ blink::WebConsoleMessage( |
+ blink::WebConsoleMessage::LevelWarning, message)); |
+ return true; |
+} |
+ |
+void PrintWebViewHelper::ResetScriptedPrintCount() { |
+ // Reset cancel counter on successful print. |
+ user_cancelled_scripted_print_count_ = 0; |
+} |
+ |
+void PrintWebViewHelper::IncrementScriptedPrintCount() { |
+ ++user_cancelled_scripted_print_count_; |
+ last_cancelled_script_print_ = base::Time::Now(); |
+} |
+ |
+ |
void PrintWebViewHelper::ShowScriptedPrintPreview() { |
if (is_scripted_preview_delayed_) { |
is_scripted_preview_delayed_ = false; |