Home | History | Annotate | Download | only in print_preview
      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, &current_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