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 #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, &current_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