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