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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" 6 7 #include <map> 8 9 #include "base/id_map.h" 10 #include "base/lazy_instance.h" 11 #include "base/memory/ref_counted_memory.h" 12 #include "base/metrics/histogram.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_split.h" 15 #include "base/strings/string_util.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/synchronization/lock.h" 18 #include "base/values.h" 19 #include "chrome/browser/browser_process.h" 20 #include "chrome/browser/printing/background_printing_manager.h" 21 #include "chrome/browser/printing/print_preview_data_service.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" 24 #include "chrome/browser/ui/webui/theme_source.h" 25 #include "chrome/common/print_messages.h" 26 #include "chrome/common/url_constants.h" 27 #include "content/public/browser/url_data_source.h" 28 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_ui_data_source.h" 30 #include "grit/browser_resources.h" 31 #include "grit/chromium_strings.h" 32 #include "grit/generated_resources.h" 33 #include "grit/google_chrome_strings.h" 34 #include "printing/page_size_margins.h" 35 #include "printing/print_job_constants.h" 36 #include "ui/base/l10n/l10n_util.h" 37 #include "ui/gfx/rect.h" 38 #include "ui/web_dialogs/web_dialog_delegate.h" 39 #include "ui/web_dialogs/web_dialog_ui.h" 40 41 using content::WebContents; 42 using printing::PageSizeMargins; 43 44 namespace { 45 46 #if defined(OS_MACOSX) 47 // U+0028 U+21E7 U+2318 U+0050 U+0029 in UTF8 48 const char kAdvancedPrintShortcut[] = "\x28\xE2\x8c\xA5\xE2\x8C\x98\x50\x29"; 49 #elif defined(OS_WIN) || defined(OS_CHROMEOS) 50 const char kAdvancedPrintShortcut[] = "(Ctrl+Shift+P)"; 51 #else 52 const char kAdvancedPrintShortcut[] = "(Shift+Ctrl+P)"; 53 #endif 54 55 // Thread-safe wrapper around a std::map to keep track of mappings from 56 // PrintPreviewUI IDs to most recent print preview request IDs. 57 class PrintPreviewRequestIdMapWithLock { 58 public: 59 PrintPreviewRequestIdMapWithLock() {} 60 ~PrintPreviewRequestIdMapWithLock() {} 61 62 // Gets the value for |preview_id|. 63 // Returns true and sets |out_value| on success. 64 bool Get(int32 preview_id, int* out_value) { 65 base::AutoLock lock(lock_); 66 PrintPreviewRequestIdMap::const_iterator it = map_.find(preview_id); 67 if (it == map_.end()) 68 return false; 69 *out_value = it->second; 70 return true; 71 } 72 73 // Sets the |value| for |preview_id|. 74 void Set(int32 preview_id, int value) { 75 base::AutoLock lock(lock_); 76 map_[preview_id] = value; 77 } 78 79 // Erases the entry for |preview_id|. 80 void Erase(int32 preview_id) { 81 base::AutoLock lock(lock_); 82 map_.erase(preview_id); 83 } 84 85 private: 86 // Mapping from PrintPreviewUI ID to print preview request ID. 87 typedef std::map<int, int> PrintPreviewRequestIdMap; 88 89 PrintPreviewRequestIdMap map_; 90 base::Lock lock_; 91 92 DISALLOW_COPY_AND_ASSIGN(PrintPreviewRequestIdMapWithLock); 93 }; 94 95 // Written to on the UI thread, read from any thread. 96 base::LazyInstance<PrintPreviewRequestIdMapWithLock> 97 g_print_preview_request_id_map = LAZY_INSTANCE_INITIALIZER; 98 99 // PrintPreviewUI IDMap used to avoid exposing raw pointer addresses to WebUI. 100 // Only accessed on the UI thread. 101 base::LazyInstance<IDMap<PrintPreviewUI> > 102 g_print_preview_ui_id_map = LAZY_INSTANCE_INITIALIZER; 103 104 // PrintPreviewUI serves data for chrome://print requests. 105 // 106 // The format for requesting PDF data is as follows: 107 // chrome://print/<PrintPreviewUIID>/<PageIndex>/print.pdf 108 // 109 // Parameters (< > required): 110 // <PrintPreviewUIID> = PrintPreview UI ID 111 // <PageIndex> = Page index is zero-based or 112 // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent 113 // a print ready PDF. 114 // 115 // Example: 116 // chrome://print/123/10/print.pdf 117 // 118 // Requests to chrome://print with paths not ending in /print.pdf are used 119 // to return the markup or other resources for the print preview page itself. 120 bool HandleRequestCallback( 121 const std::string& path, 122 const content::WebUIDataSource::GotDataCallback& callback) { 123 // ChromeWebUIDataSource handles most requests except for the print preview 124 // data. 125 if (!EndsWith(path, "/print.pdf", true)) 126 return false; 127 128 // Print Preview data. 129 scoped_refptr<base::RefCountedBytes> data; 130 std::vector<std::string> url_substr; 131 base::SplitString(path, '/', &url_substr); 132 int preview_ui_id = -1; 133 int page_index = 0; 134 if (url_substr.size() == 3 && 135 base::StringToInt(url_substr[0], &preview_ui_id), 136 base::StringToInt(url_substr[1], &page_index) && 137 preview_ui_id >= 0) { 138 PrintPreviewDataService::GetInstance()->GetDataEntry( 139 preview_ui_id, page_index, &data); 140 } 141 if (data.get()) { 142 callback.Run(data.get()); 143 return true; 144 } 145 // Invalid request. 146 scoped_refptr<base::RefCountedBytes> empty_bytes(new base::RefCountedBytes); 147 callback.Run(empty_bytes.get()); 148 return true; 149 } 150 151 content::WebUIDataSource* CreatePrintPreviewUISource() { 152 content::WebUIDataSource* source = 153 content::WebUIDataSource::Create(chrome::kChromeUIPrintHost); 154 #if defined(OS_CHROMEOS) 155 source->AddLocalizedString("title", 156 IDS_PRINT_PREVIEW_GOOGLE_CLOUD_PRINT_TITLE); 157 #else 158 source->AddLocalizedString("title", IDS_PRINT_PREVIEW_TITLE); 159 #endif 160 source->AddLocalizedString("loading", IDS_PRINT_PREVIEW_LOADING); 161 source->AddLocalizedString("noPlugin", IDS_PRINT_PREVIEW_NO_PLUGIN); 162 source->AddLocalizedString("launchNativeDialog", 163 IDS_PRINT_PREVIEW_NATIVE_DIALOG); 164 source->AddLocalizedString("previewFailed", IDS_PRINT_PREVIEW_FAILED); 165 source->AddLocalizedString("invalidPrinterSettings", 166 IDS_PRINT_PREVIEW_INVALID_PRINTER_SETTINGS); 167 source->AddLocalizedString("printButton", IDS_PRINT_PREVIEW_PRINT_BUTTON); 168 source->AddLocalizedString("saveButton", IDS_PRINT_PREVIEW_SAVE_BUTTON); 169 source->AddLocalizedString("cancelButton", IDS_PRINT_PREVIEW_CANCEL_BUTTON); 170 source->AddLocalizedString("printing", IDS_PRINT_PREVIEW_PRINTING); 171 source->AddLocalizedString("printingToPDFInProgress", 172 IDS_PRINT_PREVIEW_PRINTING_TO_PDF_IN_PROGRESS); 173 #if defined(OS_MACOSX) 174 source->AddLocalizedString("openingPDFInPreview", 175 IDS_PRINT_PREVIEW_OPENING_PDF_IN_PREVIEW); 176 #endif 177 source->AddLocalizedString("destinationLabel", 178 IDS_PRINT_PREVIEW_DESTINATION_LABEL); 179 source->AddLocalizedString("copiesLabel", IDS_PRINT_PREVIEW_COPIES_LABEL); 180 source->AddLocalizedString("examplePageRangeText", 181 IDS_PRINT_PREVIEW_EXAMPLE_PAGE_RANGE_TEXT); 182 source->AddLocalizedString("layoutLabel", IDS_PRINT_PREVIEW_LAYOUT_LABEL); 183 source->AddLocalizedString("optionAllPages", 184 IDS_PRINT_PREVIEW_OPTION_ALL_PAGES); 185 source->AddLocalizedString("optionBw", IDS_PRINT_PREVIEW_OPTION_BW); 186 source->AddLocalizedString("optionCollate", IDS_PRINT_PREVIEW_OPTION_COLLATE); 187 source->AddLocalizedString("optionColor", IDS_PRINT_PREVIEW_OPTION_COLOR); 188 source->AddLocalizedString("optionLandscape", 189 IDS_PRINT_PREVIEW_OPTION_LANDSCAPE); 190 source->AddLocalizedString("optionPortrait", 191 IDS_PRINT_PREVIEW_OPTION_PORTRAIT); 192 source->AddLocalizedString("optionTwoSided", 193 IDS_PRINT_PREVIEW_OPTION_TWO_SIDED); 194 source->AddLocalizedString("pagesLabel", IDS_PRINT_PREVIEW_PAGES_LABEL); 195 source->AddLocalizedString("pageRangeTextBox", 196 IDS_PRINT_PREVIEW_PAGE_RANGE_TEXT); 197 source->AddLocalizedString("pageRangeRadio", 198 IDS_PRINT_PREVIEW_PAGE_RANGE_RADIO); 199 source->AddLocalizedString("printToPDF", IDS_PRINT_PREVIEW_PRINT_TO_PDF); 200 source->AddLocalizedString("printPreviewSummaryFormatShort", 201 IDS_PRINT_PREVIEW_SUMMARY_FORMAT_SHORT); 202 source->AddLocalizedString("printPreviewSummaryFormatLong", 203 IDS_PRINT_PREVIEW_SUMMARY_FORMAT_LONG); 204 source->AddLocalizedString("printPreviewSheetsLabelSingular", 205 IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR); 206 source->AddLocalizedString("printPreviewSheetsLabelPlural", 207 IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL); 208 source->AddLocalizedString("printPreviewPageLabelSingular", 209 IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR); 210 source->AddLocalizedString("printPreviewPageLabelPlural", 211 IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL); 212 const base::string16 shortcut_text(UTF8ToUTF16(kAdvancedPrintShortcut)); 213 #if defined(OS_CHROMEOS) 214 source->AddString( 215 "systemDialogOption", 216 l10n_util::GetStringFUTF16( 217 IDS_PRINT_PREVIEW_CLOUD_DIALOG_OPTION, 218 l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT), 219 shortcut_text)); 220 #else 221 source->AddString( 222 "systemDialogOption", 223 l10n_util::GetStringFUTF16( 224 IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION, 225 shortcut_text)); 226 #endif 227 source->AddString( 228 "cloudPrintDialogOption", 229 l10n_util::GetStringFUTF16( 230 IDS_PRINT_PREVIEW_CLOUD_DIALOG_OPTION_NO_SHORTCUT, 231 l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT))); 232 #if defined(OS_MACOSX) 233 source->AddLocalizedString("openPdfInPreviewOption", 234 IDS_PRINT_PREVIEW_OPEN_PDF_IN_PREVIEW_APP); 235 #endif 236 source->AddString( 237 "printWithCloudPrintWait", 238 l10n_util::GetStringFUTF16( 239 IDS_PRINT_PREVIEW_PRINT_WITH_CLOUD_PRINT_WAIT, 240 l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT))); 241 source->AddString( 242 "noDestsPromoLearnMoreUrl", 243 chrome::kCloudPrintNoDestinationsLearnMoreURL); 244 source->AddLocalizedString("pageRangeInstruction", 245 IDS_PRINT_PREVIEW_PAGE_RANGE_INSTRUCTION); 246 source->AddLocalizedString("copiesInstruction", 247 IDS_PRINT_PREVIEW_COPIES_INSTRUCTION); 248 source->AddLocalizedString("incrementTitle", 249 IDS_PRINT_PREVIEW_INCREMENT_TITLE); 250 source->AddLocalizedString("decrementTitle", 251 IDS_PRINT_PREVIEW_DECREMENT_TITLE); 252 source->AddLocalizedString("printPagesLabel", 253 IDS_PRINT_PREVIEW_PRINT_PAGES_LABEL); 254 source->AddLocalizedString("optionsLabel", IDS_PRINT_PREVIEW_OPTIONS_LABEL); 255 source->AddLocalizedString("optionHeaderFooter", 256 IDS_PRINT_PREVIEW_OPTION_HEADER_FOOTER); 257 source->AddLocalizedString("optionFitToPage", 258 IDS_PRINT_PREVIEW_OPTION_FIT_TO_PAGE); 259 source->AddLocalizedString( 260 "optionBackgroundColorsAndImages", 261 IDS_PRINT_PREVIEW_OPTION_BACKGROUND_COLORS_AND_IMAGES); 262 source->AddLocalizedString("optionSelectionOnly", 263 IDS_PRINT_PREVIEW_OPTION_SELECTION_ONLY); 264 source->AddLocalizedString("marginsLabel", IDS_PRINT_PREVIEW_MARGINS_LABEL); 265 source->AddLocalizedString("defaultMargins", 266 IDS_PRINT_PREVIEW_DEFAULT_MARGINS); 267 source->AddLocalizedString("noMargins", IDS_PRINT_PREVIEW_NO_MARGINS); 268 source->AddLocalizedString("customMargins", IDS_PRINT_PREVIEW_CUSTOM_MARGINS); 269 source->AddLocalizedString("minimumMargins", 270 IDS_PRINT_PREVIEW_MINIMUM_MARGINS); 271 source->AddLocalizedString("top", IDS_PRINT_PREVIEW_TOP_MARGIN_LABEL); 272 source->AddLocalizedString("bottom", IDS_PRINT_PREVIEW_BOTTOM_MARGIN_LABEL); 273 source->AddLocalizedString("left", IDS_PRINT_PREVIEW_LEFT_MARGIN_LABEL); 274 source->AddLocalizedString("right", IDS_PRINT_PREVIEW_RIGHT_MARGIN_LABEL); 275 source->AddLocalizedString("destinationSearchTitle", 276 IDS_PRINT_PREVIEW_DESTINATION_SEARCH_TITLE); 277 source->AddLocalizedString("userInfo", IDS_PRINT_PREVIEW_USER_INFO); 278 source->AddLocalizedString("cloudPrintPromotion", 279 IDS_PRINT_PREVIEW_CLOUD_PRINT_PROMOTION); 280 source->AddLocalizedString("searchBoxPlaceholder", 281 IDS_PRINT_PREVIEW_SEARCH_BOX_PLACEHOLDER); 282 source->AddLocalizedString("noDestinationsMessage", 283 IDS_PRINT_PREVIEW_NO_DESTINATIONS_MESSAGE); 284 source->AddLocalizedString("showAllButtonText", 285 IDS_PRINT_PREVIEW_SHOW_ALL_BUTTON_TEXT); 286 source->AddLocalizedString("destinationCount", 287 IDS_PRINT_PREVIEW_DESTINATION_COUNT); 288 source->AddLocalizedString("recentDestinationsTitle", 289 IDS_PRINT_PREVIEW_RECENT_DESTINATIONS_TITLE); 290 source->AddLocalizedString("localDestinationsTitle", 291 IDS_PRINT_PREVIEW_LOCAL_DESTINATIONS_TITLE); 292 source->AddLocalizedString("cloudDestinationsTitle", 293 IDS_PRINT_PREVIEW_CLOUD_DESTINATIONS_TITLE); 294 source->AddLocalizedString("manage", IDS_PRINT_PREVIEW_MANAGE); 295 source->AddLocalizedString("setupCloudPrinters", 296 IDS_PRINT_PREVIEW_SETUP_CLOUD_PRINTERS); 297 source->AddLocalizedString("changeDestination", 298 IDS_PRINT_PREVIEW_CHANGE_DESTINATION); 299 source->AddLocalizedString("offlineForYear", 300 IDS_PRINT_PREVIEW_OFFLINE_FOR_YEAR); 301 source->AddLocalizedString("offlineForMonth", 302 IDS_PRINT_PREVIEW_OFFLINE_FOR_MONTH); 303 source->AddLocalizedString("offlineForWeek", 304 IDS_PRINT_PREVIEW_OFFLINE_FOR_WEEK); 305 source->AddLocalizedString("offline", IDS_PRINT_PREVIEW_OFFLINE); 306 source->AddLocalizedString("fedexTos", IDS_PRINT_PREVIEW_FEDEX_TOS); 307 source->AddLocalizedString("tosCheckboxLabel", 308 IDS_PRINT_PREVIEW_TOS_CHECKBOX_LABEL); 309 source->AddLocalizedString("noDestsPromoTitle", 310 IDS_PRINT_PREVIEW_NO_DESTS_PROMO_TITLE); 311 source->AddLocalizedString("noDestsPromoBody", 312 IDS_PRINT_PREVIEW_NO_DESTS_PROMO_BODY); 313 source->AddLocalizedString("noDestsPromoGcpDesc", 314 IDS_PRINT_PREVIEW_NO_DESTS_GCP_DESC); 315 source->AddLocalizedString("learnMore", 316 IDS_LEARN_MORE); 317 source->AddLocalizedString( 318 "noDestsPromoAddPrinterButtonLabel", 319 IDS_PRINT_PREVIEW_NO_DESTS_PROMO_ADD_PRINTER_BUTTON_LABEL); 320 source->AddLocalizedString( 321 "noDestsPromoNotNowButtonLabel", 322 IDS_PRINT_PREVIEW_NO_DESTS_PROMO_NOT_NOW_BUTTON_LABEL); 323 source->AddLocalizedString("couldNotPrint", 324 IDS_PRINT_PREVIEW_COULD_NOT_PRINT); 325 source->AddLocalizedString("registerPromoButtonText", 326 IDS_PRINT_PREVIEW_REGISTER_PROMO_BUTTON_TEXT); 327 328 source->SetJsonPath("strings.js"); 329 source->AddResourcePath("print_preview.js", IDR_PRINT_PREVIEW_JS); 330 source->AddResourcePath("images/printer.png", 331 IDR_PRINT_PREVIEW_IMAGES_PRINTER); 332 source->AddResourcePath("images/printer_shared.png", 333 IDR_PRINT_PREVIEW_IMAGES_PRINTER_SHARED); 334 source->AddResourcePath("images/third_party.png", 335 IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY); 336 source->AddResourcePath("images/third_party_fedex.png", 337 IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY_FEDEX); 338 source->AddResourcePath("images/google_doc.png", 339 IDR_PRINT_PREVIEW_IMAGES_GOOGLE_DOC); 340 source->AddResourcePath("images/pdf.png", IDR_PRINT_PREVIEW_IMAGES_PDF); 341 source->AddResourcePath("images/mobile.png", IDR_PRINT_PREVIEW_IMAGES_MOBILE); 342 source->AddResourcePath("images/mobile_shared.png", 343 IDR_PRINT_PREVIEW_IMAGES_MOBILE_SHARED); 344 source->SetDefaultResource(IDR_PRINT_PREVIEW_HTML); 345 source->SetRequestFilter(base::Bind(&HandleRequestCallback)); 346 source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';"); 347 return source; 348 } 349 350 PrintPreviewUI::TestingDelegate* g_testing_delegate = NULL; 351 352 } // namespace 353 354 PrintPreviewUI::PrintPreviewUI(content::WebUI* web_ui) 355 : ConstrainedWebDialogUI(web_ui), 356 initial_preview_start_time_(base::TimeTicks::Now()), 357 id_(g_print_preview_ui_id_map.Get().Add(this)), 358 handler_(NULL), 359 source_is_modifiable_(true), 360 source_has_selection_(false), 361 dialog_closed_(false) { 362 // Set up the chrome://print/ data source. 363 Profile* profile = Profile::FromWebUI(web_ui); 364 content::WebUIDataSource::Add(profile, CreatePrintPreviewUISource()); 365 366 // Set up the chrome://theme/ source. 367 content::URLDataSource::Add(profile, new ThemeSource(profile)); 368 369 // WebUI owns |handler_|. 370 handler_ = new PrintPreviewHandler(); 371 web_ui->AddMessageHandler(handler_); 372 373 g_print_preview_request_id_map.Get().Set(id_, -1); 374 } 375 376 PrintPreviewUI::~PrintPreviewUI() { 377 print_preview_data_service()->RemoveEntry(id_); 378 g_print_preview_request_id_map.Get().Erase(id_); 379 g_print_preview_ui_id_map.Get().Remove(id_); 380 } 381 382 void PrintPreviewUI::GetPrintPreviewDataForIndex( 383 int index, 384 scoped_refptr<base::RefCountedBytes>* data) { 385 print_preview_data_service()->GetDataEntry(id_, index, data); 386 } 387 388 void PrintPreviewUI::SetPrintPreviewDataForIndex( 389 int index, 390 const base::RefCountedBytes* data) { 391 print_preview_data_service()->SetDataEntry(id_, index, data); 392 } 393 394 void PrintPreviewUI::ClearAllPreviewData() { 395 print_preview_data_service()->RemoveEntry(id_); 396 } 397 398 int PrintPreviewUI::GetAvailableDraftPageCount() { 399 return print_preview_data_service()->GetAvailableDraftPageCount(id_); 400 } 401 402 void PrintPreviewUI::SetInitiatorTitle( 403 const base::string16& job_title) { 404 initiator_title_ = job_title; 405 } 406 407 // static 408 void PrintPreviewUI::SetInitialParams( 409 content::WebContents* print_preview_dialog, 410 const PrintHostMsg_RequestPrintPreview_Params& params) { 411 if (!print_preview_dialog || !print_preview_dialog->GetWebUI()) 412 return; 413 PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>( 414 print_preview_dialog->GetWebUI()->GetController()); 415 print_preview_ui->source_is_modifiable_ = params.is_modifiable; 416 print_preview_ui->source_has_selection_ = params.has_selection; 417 print_preview_ui->print_selection_only_ = params.selection_only; 418 } 419 420 // static 421 void PrintPreviewUI::GetCurrentPrintPreviewStatus(int32 preview_ui_id, 422 int request_id, 423 bool* cancel) { 424 int current_id = -1; 425 if (!g_print_preview_request_id_map.Get().Get(preview_ui_id, ¤t_id)) { 426 *cancel = true; 427 return; 428 } 429 *cancel = (request_id != current_id); 430 } 431 432 int32 PrintPreviewUI::GetIDForPrintPreviewUI() const { 433 return id_; 434 } 435 436 void PrintPreviewUI::OnPrintPreviewDialogClosed() { 437 WebContents* preview_dialog = web_ui()->GetWebContents(); 438 printing::BackgroundPrintingManager* background_printing_manager = 439 g_browser_process->background_printing_manager(); 440 if (background_printing_manager->HasPrintPreviewDialog(preview_dialog)) 441 return; 442 OnClosePrintPreviewDialog(); 443 } 444 445 void PrintPreviewUI::OnInitiatorClosed() { 446 WebContents* preview_dialog = web_ui()->GetWebContents(); 447 printing::BackgroundPrintingManager* background_printing_manager = 448 g_browser_process->background_printing_manager(); 449 if (background_printing_manager->HasPrintPreviewDialog(preview_dialog)) 450 web_ui()->CallJavascriptFunction("cancelPendingPrintRequest"); 451 else 452 OnClosePrintPreviewDialog(); 453 } 454 455 void PrintPreviewUI::OnPrintPreviewRequest(int request_id) { 456 if (!initial_preview_start_time_.is_null()) { 457 UMA_HISTOGRAM_TIMES("PrintPreview.InitializationTime", 458 base::TimeTicks::Now() - initial_preview_start_time_); 459 } 460 g_print_preview_request_id_map.Get().Set(id_, request_id); 461 } 462 463 void PrintPreviewUI::OnShowSystemDialog() { 464 web_ui()->CallJavascriptFunction("onSystemDialogLinkClicked"); 465 } 466 467 void PrintPreviewUI::OnDidGetPreviewPageCount( 468 const PrintHostMsg_DidGetPreviewPageCount_Params& params) { 469 DCHECK_GT(params.page_count, 0); 470 if (g_testing_delegate) 471 g_testing_delegate->DidGetPreviewPageCount(params.page_count); 472 base::FundamentalValue count(params.page_count); 473 base::FundamentalValue request_id(params.preview_request_id); 474 web_ui()->CallJavascriptFunction("onDidGetPreviewPageCount", 475 count, 476 request_id); 477 } 478 479 void PrintPreviewUI::OnDidGetDefaultPageLayout( 480 const PageSizeMargins& page_layout, const gfx::Rect& printable_area, 481 bool has_custom_page_size_style) { 482 if (page_layout.margin_top < 0 || page_layout.margin_left < 0 || 483 page_layout.margin_bottom < 0 || page_layout.margin_right < 0 || 484 page_layout.content_width < 0 || page_layout.content_height < 0 || 485 printable_area.width() <= 0 || printable_area.height() <= 0) { 486 NOTREACHED(); 487 return; 488 } 489 490 base::DictionaryValue layout; 491 layout.SetDouble(printing::kSettingMarginTop, page_layout.margin_top); 492 layout.SetDouble(printing::kSettingMarginLeft, page_layout.margin_left); 493 layout.SetDouble(printing::kSettingMarginBottom, page_layout.margin_bottom); 494 layout.SetDouble(printing::kSettingMarginRight, page_layout.margin_right); 495 layout.SetDouble(printing::kSettingContentWidth, page_layout.content_width); 496 layout.SetDouble(printing::kSettingContentHeight, page_layout.content_height); 497 layout.SetInteger(printing::kSettingPrintableAreaX, printable_area.x()); 498 layout.SetInteger(printing::kSettingPrintableAreaY, printable_area.y()); 499 layout.SetInteger(printing::kSettingPrintableAreaWidth, 500 printable_area.width()); 501 layout.SetInteger(printing::kSettingPrintableAreaHeight, 502 printable_area.height()); 503 504 base::FundamentalValue has_page_size_style(has_custom_page_size_style); 505 web_ui()->CallJavascriptFunction("onDidGetDefaultPageLayout", layout, 506 has_page_size_style); 507 } 508 509 void PrintPreviewUI::OnDidPreviewPage(int page_number, 510 int preview_request_id) { 511 DCHECK_GE(page_number, 0); 512 base::FundamentalValue number(page_number); 513 base::FundamentalValue ui_identifier(id_); 514 base::FundamentalValue request_id(preview_request_id); 515 if (g_testing_delegate) 516 g_testing_delegate->DidRenderPreviewPage(*web_ui()->GetWebContents()); 517 web_ui()->CallJavascriptFunction( 518 "onDidPreviewPage", number, ui_identifier, request_id); 519 if (g_testing_delegate && g_testing_delegate->IsAutoCancelEnabled()) 520 web_ui()->CallJavascriptFunction("autoCancelForTesting"); 521 } 522 523 void PrintPreviewUI::OnPreviewDataIsAvailable(int expected_pages_count, 524 int preview_request_id) { 525 VLOG(1) << "Print preview request finished with " 526 << expected_pages_count << " pages"; 527 528 if (!initial_preview_start_time_.is_null()) { 529 UMA_HISTOGRAM_TIMES("PrintPreview.InitialDisplayTime", 530 base::TimeTicks::Now() - initial_preview_start_time_); 531 UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.Initial", 532 expected_pages_count); 533 UMA_HISTOGRAM_COUNTS( 534 "PrintPreview.RegeneratePreviewRequest.BeforeFirstData", 535 handler_->regenerate_preview_request_count()); 536 initial_preview_start_time_ = base::TimeTicks(); 537 } 538 base::FundamentalValue ui_identifier(id_); 539 base::FundamentalValue ui_preview_request_id(preview_request_id); 540 web_ui()->CallJavascriptFunction("updatePrintPreview", ui_identifier, 541 ui_preview_request_id); 542 } 543 544 void PrintPreviewUI::OnPrintPreviewDialogDestroyed() { 545 handler_->OnPrintPreviewDialogDestroyed(); 546 } 547 548 void PrintPreviewUI::OnFileSelectionCancelled() { 549 web_ui()->CallJavascriptFunction("fileSelectionCancelled"); 550 } 551 552 void PrintPreviewUI::OnCancelPendingPreviewRequest() { 553 g_print_preview_request_id_map.Get().Set(id_, -1); 554 } 555 556 void PrintPreviewUI::OnPrintPreviewFailed() { 557 handler_->OnPrintPreviewFailed(); 558 web_ui()->CallJavascriptFunction("printPreviewFailed"); 559 } 560 561 void PrintPreviewUI::OnInvalidPrinterSettings() { 562 web_ui()->CallJavascriptFunction("invalidPrinterSettings"); 563 } 564 565 PrintPreviewDataService* PrintPreviewUI::print_preview_data_service() { 566 return PrintPreviewDataService::GetInstance(); 567 } 568 569 void PrintPreviewUI::OnHidePreviewDialog() { 570 WebContents* preview_dialog = web_ui()->GetWebContents(); 571 printing::BackgroundPrintingManager* background_printing_manager = 572 g_browser_process->background_printing_manager(); 573 if (background_printing_manager->HasPrintPreviewDialog(preview_dialog)) 574 return; 575 576 ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate(); 577 if (!delegate) 578 return; 579 delegate->ReleaseWebContentsOnDialogClose(); 580 background_printing_manager->OwnPrintPreviewDialog(preview_dialog); 581 OnClosePrintPreviewDialog(); 582 } 583 584 void PrintPreviewUI::OnClosePrintPreviewDialog() { 585 if (dialog_closed_) 586 return; 587 dialog_closed_ = true; 588 ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate(); 589 if (!delegate) 590 return; 591 delegate->GetWebDialogDelegate()->OnDialogClosed(std::string()); 592 delegate->OnDialogCloseFromWebUI(); 593 } 594 595 void PrintPreviewUI::OnReloadPrintersList() { 596 web_ui()->CallJavascriptFunction("reloadPrintersList"); 597 } 598 599 void PrintPreviewUI::OnPrintPreviewScalingDisabled() { 600 web_ui()->CallJavascriptFunction("printScalingDisabledForSourcePDF"); 601 } 602 603 // static 604 void PrintPreviewUI::SetDelegateForTesting(TestingDelegate* delegate) { 605 g_testing_delegate = delegate; 606 } 607