OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/printing/print_web_view_helper.h" | 5 #include "chrome/renderer/printing/print_web_view_helper.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 PREVIEW_EVENT_MAX, | 61 PREVIEW_EVENT_MAX, |
62 }; | 62 }; |
63 | 63 |
64 const double kMinDpi = 1.0; | 64 const double kMinDpi = 1.0; |
65 | 65 |
66 const char kPageLoadScriptFormat[] = | 66 const char kPageLoadScriptFormat[] = |
67 "document.open(); document.write(%s); document.close();"; | 67 "document.open(); document.write(%s); document.close();"; |
68 | 68 |
69 const char kPageSetupScriptFormat[] = "setup(%s);"; | 69 const char kPageSetupScriptFormat[] = "setup(%s);"; |
70 | 70 |
| 71 #if defined(ENABLE_FULL_PRINTING) |
| 72 bool g_is_preview_enabled_ = true; |
| 73 #else |
| 74 bool g_is_preview_enabled_ = false; |
| 75 #endif |
| 76 |
71 void ExecuteScript(blink::WebFrame* frame, | 77 void ExecuteScript(blink::WebFrame* frame, |
72 const char* script_format, | 78 const char* script_format, |
73 const base::Value& parameters) { | 79 const base::Value& parameters) { |
74 std::string json; | 80 std::string json; |
75 base::JSONWriter::Write(¶meters, &json); | 81 base::JSONWriter::Write(¶meters, &json); |
76 std::string script = base::StringPrintf(script_format, json.c_str()); | 82 std::string script = base::StringPrintf(script_format, json.c_str()); |
77 frame->executeScript(blink::WebString(base::UTF8ToUTF16(script))); | 83 frame->executeScript(blink::WebString(base::UTF8ToUTF16(script))); |
78 } | 84 } |
79 | 85 |
80 int GetDPI(const PrintMsg_Print_Params* print_params) { | 86 int GetDPI(const PrintMsg_Print_Params* print_params) { |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 notify_browser_of_print_failure_(true), | 790 notify_browser_of_print_failure_(true), |
785 print_for_preview_(false), | 791 print_for_preview_(false), |
786 print_node_in_progress_(false), | 792 print_node_in_progress_(false), |
787 is_loading_(false), | 793 is_loading_(false), |
788 is_scripted_preview_delayed_(false), | 794 is_scripted_preview_delayed_(false), |
789 weak_ptr_factory_(this) { | 795 weak_ptr_factory_(this) { |
790 } | 796 } |
791 | 797 |
792 PrintWebViewHelper::~PrintWebViewHelper() {} | 798 PrintWebViewHelper::~PrintWebViewHelper() {} |
793 | 799 |
| 800 // static |
| 801 void PrintWebViewHelper::DisablePreview() { |
| 802 g_is_preview_enabled_ = false; |
| 803 } |
| 804 |
794 bool PrintWebViewHelper::IsScriptInitiatedPrintAllowed( | 805 bool PrintWebViewHelper::IsScriptInitiatedPrintAllowed( |
795 blink::WebFrame* frame, bool user_initiated) { | 806 blink::WebFrame* frame, bool user_initiated) { |
796 #if defined(OS_ANDROID) | 807 #if defined(OS_ANDROID) |
797 return false; | 808 return false; |
798 #endif // defined(OS_ANDROID) | 809 #endif // defined(OS_ANDROID) |
799 if (is_scripted_printing_blocked_) | 810 // If preview is enabled, then the print dialog is tab modal, and the user |
800 return false; | 811 // can always close the tab on a mis-behaving page (the system print dialog |
801 return true; | 812 // is app modal). If the print was initiated through user action, don't |
| 813 // throttle. Or, if the command line flag to skip throttling has been set. |
| 814 return !is_scripted_printing_blocked_ && |
| 815 (user_initiated || g_is_preview_enabled_ || |
| 816 scripting_throttler_.IsAllowed(frame)); |
802 } | 817 } |
803 | 818 |
804 void PrintWebViewHelper::DidStartLoading() { | 819 void PrintWebViewHelper::DidStartLoading() { |
805 is_loading_ = true; | 820 is_loading_ = true; |
806 } | 821 } |
807 | 822 |
808 void PrintWebViewHelper::DidStopLoading() { | 823 void PrintWebViewHelper::DidStopLoading() { |
809 is_loading_ = false; | 824 is_loading_ = false; |
810 if (!on_stop_loading_closure_.is_null()) { | 825 if (!on_stop_loading_closure_.is_null()) { |
811 on_stop_loading_closure_.Run(); | 826 on_stop_loading_closure_.Run(); |
812 on_stop_loading_closure_.Reset(); | 827 on_stop_loading_closure_.Reset(); |
813 } | 828 } |
814 } | 829 } |
815 | 830 |
816 // Prints |frame| which called window.print(). | 831 // Prints |frame| which called window.print(). |
817 void PrintWebViewHelper::PrintPage(blink::WebLocalFrame* frame, | 832 void PrintWebViewHelper::PrintPage(blink::WebLocalFrame* frame, |
818 bool user_initiated) { | 833 bool user_initiated) { |
819 DCHECK(frame); | 834 DCHECK(frame); |
820 | 835 |
821 // Allow Prerendering to cancel this print request if necessary. | 836 // Allow Prerendering to cancel this print request if necessary. |
822 if (prerender::PrerenderHelper::IsPrerendering( | 837 if (prerender::PrerenderHelper::IsPrerendering( |
823 render_view()->GetMainRenderFrame())) { | 838 render_view()->GetMainRenderFrame())) { |
824 Send(new ChromeViewHostMsg_CancelPrerenderForPrinting(routing_id())); | 839 Send(new ChromeViewHostMsg_CancelPrerenderForPrinting(routing_id())); |
825 return; | 840 return; |
826 } | 841 } |
827 | 842 |
828 if (!IsScriptInitiatedPrintAllowed(frame, user_initiated)) | 843 if (!IsScriptInitiatedPrintAllowed(frame, user_initiated)) |
829 return; | 844 return; |
830 print_preview_context_.InitWithFrame(frame); | 845 |
831 RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); | 846 if (!g_is_preview_enabled_) { |
| 847 Print(frame, blink::WebNode()); |
| 848 } else { |
| 849 print_preview_context_.InitWithFrame(frame); |
| 850 RequestPrintPreview(PRINT_PREVIEW_SCRIPTED); |
| 851 } |
832 } | 852 } |
833 | 853 |
834 bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) { | 854 bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) { |
835 bool handled = true; | 855 bool handled = true; |
836 IPC_BEGIN_MESSAGE_MAP(PrintWebViewHelper, message) | 856 IPC_BEGIN_MESSAGE_MAP(PrintWebViewHelper, message) |
837 #if !defined(DISABLE_BASIC_PRINTING) | 857 #if !defined(DISABLE_BASIC_PRINTING) |
838 IPC_MESSAGE_HANDLER(PrintMsg_PrintPages, OnPrintPages) | 858 IPC_MESSAGE_HANDLER(PrintMsg_PrintPages, OnPrintPages) |
839 IPC_MESSAGE_HANDLER(PrintMsg_PrintForSystemDialog, OnPrintForSystemDialog) | 859 IPC_MESSAGE_HANDLER(PrintMsg_PrintForSystemDialog, OnPrintForSystemDialog) |
840 #endif // !DISABLE_BASIC_PRINTING | 860 #endif // !DISABLE_BASIC_PRINTING |
841 IPC_MESSAGE_HANDLER(PrintMsg_InitiatePrintPreview, OnInitiatePrintPreview) | 861 IPC_MESSAGE_HANDLER(PrintMsg_InitiatePrintPreview, OnInitiatePrintPreview) |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 // This can happen as a result of processing sync messages when printing | 1233 // This can happen as a result of processing sync messages when printing |
1214 // from ppapi plugins. It's a rare case, so its OK to just fail here. | 1234 // from ppapi plugins. It's a rare case, so its OK to just fail here. |
1215 // See http://crbug.com/159165. | 1235 // See http://crbug.com/159165. |
1216 return; | 1236 return; |
1217 } | 1237 } |
1218 | 1238 |
1219 print_node_in_progress_ = true; | 1239 print_node_in_progress_ = true; |
1220 | 1240 |
1221 // Make a copy of the node, in case RenderView::OnContextMenuClosed resets | 1241 // Make a copy of the node, in case RenderView::OnContextMenuClosed resets |
1222 // its |context_menu_node_|. | 1242 // its |context_menu_node_|. |
1223 print_preview_context_.InitWithNode(node); | 1243 if (!g_is_preview_enabled_) { |
1224 RequestPrintPreview(PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE); | 1244 blink::WebNode duplicate_node(node); |
| 1245 Print(duplicate_node.document().frame(), duplicate_node); |
| 1246 } else { |
| 1247 print_preview_context_.InitWithNode(node); |
| 1248 RequestPrintPreview(PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE); |
| 1249 } |
1225 | 1250 |
1226 print_node_in_progress_ = false; | 1251 print_node_in_progress_ = false; |
1227 } | 1252 } |
1228 | 1253 |
1229 #if !defined(DISABLE_BASIC_PRINTING) | |
1230 void PrintWebViewHelper::Print(blink::WebLocalFrame* frame, | 1254 void PrintWebViewHelper::Print(blink::WebLocalFrame* frame, |
1231 const blink::WebNode& node) { | 1255 const blink::WebNode& node) { |
1232 // If still not finished with earlier print request simply ignore. | 1256 // If still not finished with earlier print request simply ignore. |
1233 if (prep_frame_view_) | 1257 if (prep_frame_view_) |
1234 return; | 1258 return; |
1235 | 1259 |
1236 FrameReference frame_ref(frame); | 1260 FrameReference frame_ref(frame); |
1237 | 1261 |
1238 int expected_page_count = 0; | 1262 int expected_page_count = 0; |
1239 if (!CalculateNumberOfPages(frame, node, &expected_page_count)) { | 1263 if (!CalculateNumberOfPages(frame, node, &expected_page_count)) { |
(...skipping 12 matching lines...) Expand all Loading... |
1252 expected_page_count)) { | 1276 expected_page_count)) { |
1253 DidFinishPrinting(OK); // Release resources and fail silently. | 1277 DidFinishPrinting(OK); // Release resources and fail silently. |
1254 return; | 1278 return; |
1255 } | 1279 } |
1256 | 1280 |
1257 // Render Pages for printing. | 1281 // Render Pages for printing. |
1258 if (!RenderPagesForPrint(frame_ref.GetFrame(), node)) { | 1282 if (!RenderPagesForPrint(frame_ref.GetFrame(), node)) { |
1259 LOG(ERROR) << "RenderPagesForPrint failed"; | 1283 LOG(ERROR) << "RenderPagesForPrint failed"; |
1260 DidFinishPrinting(FAIL_PRINT); | 1284 DidFinishPrinting(FAIL_PRINT); |
1261 } | 1285 } |
| 1286 scripting_throttler_.Reset(); |
1262 } | 1287 } |
1263 #endif // !DISABLE_BASIC_PRINTING | |
1264 | 1288 |
1265 void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { | 1289 void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { |
1266 switch (result) { | 1290 switch (result) { |
1267 case OK: | 1291 case OK: |
1268 break; | 1292 break; |
1269 | 1293 |
1270 case FAIL_PRINT_INIT: | 1294 case FAIL_PRINT_INIT: |
1271 DCHECK(!notify_browser_of_print_failure_); | 1295 DCHECK(!notify_browser_of_print_failure_); |
1272 break; | 1296 break; |
1273 | 1297 |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1963 error_ = PREVIEW_ERROR_NONE; | 1987 error_ = PREVIEW_ERROR_NONE; |
1964 } | 1988 } |
1965 | 1989 |
1966 void PrintWebViewHelper::SetPrintPagesParams( | 1990 void PrintWebViewHelper::SetPrintPagesParams( |
1967 const PrintMsg_PrintPages_Params& settings) { | 1991 const PrintMsg_PrintPages_Params& settings) { |
1968 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); | 1992 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); |
1969 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), | 1993 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), |
1970 settings.params.document_cookie)); | 1994 settings.params.document_cookie)); |
1971 } | 1995 } |
1972 | 1996 |
| 1997 PrintWebViewHelper::ScriptingThrottler::ScriptingThrottler() : count_(0) { |
| 1998 } |
| 1999 |
| 2000 bool PrintWebViewHelper::ScriptingThrottler::IsAllowed(blink::WebFrame* frame) { |
| 2001 const int kMinSecondsToIgnoreJavascriptInitiatedPrint = 2; |
| 2002 const int kMaxSecondsToIgnoreJavascriptInitiatedPrint = 32; |
| 2003 bool too_frequent = false; |
| 2004 |
| 2005 // Check if there is script repeatedly trying to print and ignore it if too |
| 2006 // frequent. The first 3 times, we use a constant wait time, but if this |
| 2007 // gets excessive, we switch to exponential wait time. So for a page that |
| 2008 // calls print() in a loop the user will need to cancel the print dialog |
| 2009 // after: [2, 2, 2, 4, 8, 16, 32, 32, ...] seconds. |
| 2010 // This gives the user time to navigate from the page. |
| 2011 if (count_ > 0) { |
| 2012 base::TimeDelta diff = base::Time::Now() - last_print_; |
| 2013 int min_wait_seconds = kMinSecondsToIgnoreJavascriptInitiatedPrint; |
| 2014 if (count_ > 3) { |
| 2015 min_wait_seconds = |
| 2016 std::min(kMinSecondsToIgnoreJavascriptInitiatedPrint << (count_ - 3), |
| 2017 kMaxSecondsToIgnoreJavascriptInitiatedPrint); |
| 2018 } |
| 2019 if (diff.InSeconds() < min_wait_seconds) { |
| 2020 too_frequent = true; |
| 2021 } |
| 2022 } |
| 2023 |
| 2024 if (!too_frequent) { |
| 2025 ++count_; |
| 2026 last_print_ = base::Time::Now(); |
| 2027 return true; |
| 2028 } |
| 2029 |
| 2030 blink::WebString message( |
| 2031 blink::WebString::fromUTF8("Ignoring too frequent calls to print().")); |
| 2032 frame->addMessageToConsole(blink::WebConsoleMessage( |
| 2033 blink::WebConsoleMessage::LevelWarning, message)); |
| 2034 return false; |
| 2035 } |
| 2036 |
| 2037 void PrintWebViewHelper::ScriptingThrottler::Reset() { |
| 2038 // Reset counter on successful print. |
| 2039 count_ = 0; |
| 2040 } |
| 2041 |
1973 } // namespace printing | 2042 } // namespace printing |
OLD | NEW |