Home | History | Annotate | Download | only in printing
      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/printing/print_preview_message_handler.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/ref_counted.h"
     11 #include "base/memory/ref_counted_memory.h"
     12 #include "base/memory/shared_memory.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/printing/print_job_manager.h"
     15 #include "chrome/browser/printing/print_preview_dialog_controller.h"
     16 #include "chrome/browser/printing/print_view_manager.h"
     17 #include "chrome/browser/printing/printer_query.h"
     18 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
     19 #include "chrome/common/print_messages.h"
     20 #include "content/public/browser/browser_thread.h"
     21 #include "content/public/browser/render_view_host.h"
     22 #include "content/public/browser/web_contents.h"
     23 #include "content/public/browser/web_ui.h"
     24 #include "printing/page_size_margins.h"
     25 #include "printing/print_job_constants.h"
     26 
     27 using content::BrowserThread;
     28 using content::WebContents;
     29 
     30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintPreviewMessageHandler);
     31 
     32 namespace {
     33 
     34 void StopWorker(int document_cookie) {
     35   if (document_cookie <= 0)
     36     return;
     37   scoped_refptr<printing::PrintQueriesQueue> queue =
     38       g_browser_process->print_job_manager()->queue();
     39   scoped_refptr<printing::PrinterQuery> printer_query =
     40       queue->PopPrinterQuery(document_cookie);
     41   if (printer_query.get()) {
     42     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     43                             base::Bind(&printing::PrinterQuery::StopWorker,
     44                                        printer_query));
     45   }
     46 }
     47 
     48 base::RefCountedBytes* GetDataFromHandle(base::SharedMemoryHandle handle,
     49                                          uint32 data_size) {
     50   scoped_ptr<base::SharedMemory> shared_buf(
     51       new base::SharedMemory(handle, true));
     52   if (!shared_buf->Map(data_size)) {
     53     NOTREACHED();
     54     return NULL;
     55   }
     56 
     57   unsigned char* data_begin = static_cast<unsigned char*>(shared_buf->memory());
     58   std::vector<unsigned char> data(data_begin, data_begin + data_size);
     59   return base::RefCountedBytes::TakeVector(&data);
     60 }
     61 
     62 }  // namespace
     63 
     64 namespace printing {
     65 
     66 PrintPreviewMessageHandler::PrintPreviewMessageHandler(
     67     WebContents* web_contents)
     68     : content::WebContentsObserver(web_contents) {
     69   DCHECK(web_contents);
     70 }
     71 
     72 PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
     73 }
     74 
     75 WebContents* PrintPreviewMessageHandler::GetPrintPreviewDialog() {
     76   PrintPreviewDialogController* dialog_controller =
     77       PrintPreviewDialogController::GetInstance();
     78   if (!dialog_controller)
     79     return NULL;
     80   return dialog_controller->GetPrintPreviewForContents(web_contents());
     81 }
     82 
     83 PrintPreviewUI* PrintPreviewMessageHandler::GetPrintPreviewUI() {
     84   WebContents* dialog = GetPrintPreviewDialog();
     85   if (!dialog || !dialog->GetWebUI())
     86     return NULL;
     87   return static_cast<PrintPreviewUI*>(dialog->GetWebUI()->GetController());
     88 }
     89 
     90 void PrintPreviewMessageHandler::OnRequestPrintPreview(
     91     const PrintHostMsg_RequestPrintPreview_Params& params) {
     92   if (params.webnode_only) {
     93     printing::PrintViewManager::FromWebContents(web_contents())->
     94         PrintPreviewForWebNode();
     95   }
     96   PrintPreviewDialogController::PrintPreview(web_contents());
     97   PrintPreviewUI::SetInitialParams(GetPrintPreviewDialog(), params);
     98 }
     99 
    100 void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(
    101     const PrintHostMsg_DidGetPreviewPageCount_Params& params) {
    102   if (params.page_count <= 0) {
    103     NOTREACHED();
    104     return;
    105   }
    106 
    107   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    108   if (!print_preview_ui)
    109     return;
    110 
    111   if (!params.is_modifiable || params.clear_preview_data)
    112     print_preview_ui->ClearAllPreviewData();
    113 
    114   print_preview_ui->OnDidGetPreviewPageCount(params);
    115 }
    116 
    117 void PrintPreviewMessageHandler::OnDidPreviewPage(
    118     const PrintHostMsg_DidPreviewPage_Params& params) {
    119   int page_number = params.page_number;
    120   if (page_number < FIRST_PAGE_INDEX || !params.data_size)
    121     return;
    122 
    123   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    124   if (!print_preview_ui)
    125     return;
    126 
    127   base::RefCountedBytes* data_bytes =
    128       GetDataFromHandle(params.metafile_data_handle, params.data_size);
    129   DCHECK(data_bytes);
    130 
    131   print_preview_ui->SetPrintPreviewDataForIndex(page_number, data_bytes);
    132   print_preview_ui->OnDidPreviewPage(page_number, params.preview_request_id);
    133 }
    134 
    135 void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
    136     const PrintHostMsg_DidPreviewDocument_Params& params) {
    137   // Always try to stop the worker.
    138   StopWorker(params.document_cookie);
    139 
    140   if (params.expected_pages_count <= 0) {
    141     NOTREACHED();
    142     return;
    143   }
    144 
    145   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    146   if (!print_preview_ui)
    147     return;
    148 
    149   // TODO(joth): This seems like a good match for using RefCountedStaticMemory
    150   // to avoid the memory copy, but the SetPrintPreviewData call chain below
    151   // needs updating to accept the RefCountedMemory* base class.
    152   base::RefCountedBytes* data_bytes =
    153       GetDataFromHandle(params.metafile_data_handle, params.data_size);
    154   if (!data_bytes || !data_bytes->size())
    155     return;
    156 
    157   print_preview_ui->SetPrintPreviewDataForIndex(COMPLETE_PREVIEW_DOCUMENT_INDEX,
    158                                                 data_bytes);
    159   print_preview_ui->OnPreviewDataIsAvailable(
    160       params.expected_pages_count, params.preview_request_id);
    161 }
    162 
    163 void PrintPreviewMessageHandler::OnPrintPreviewFailed(int document_cookie) {
    164   StopWorker(document_cookie);
    165 
    166   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    167   if (!print_preview_ui)
    168     return;
    169   print_preview_ui->OnPrintPreviewFailed();
    170 }
    171 
    172 void PrintPreviewMessageHandler::OnDidGetDefaultPageLayout(
    173     const PageSizeMargins& page_layout_in_points,
    174     const gfx::Rect& printable_area_in_points,
    175     bool has_custom_page_size_style) {
    176   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    177   if (!print_preview_ui)
    178     return;
    179   print_preview_ui->OnDidGetDefaultPageLayout(page_layout_in_points,
    180                                               printable_area_in_points,
    181                                               has_custom_page_size_style);
    182 }
    183 
    184 void PrintPreviewMessageHandler::OnPrintPreviewCancelled(int document_cookie) {
    185   // Always need to stop the worker.
    186   StopWorker(document_cookie);
    187 }
    188 
    189 void PrintPreviewMessageHandler::OnInvalidPrinterSettings(int document_cookie) {
    190   StopWorker(document_cookie);
    191   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    192   if (!print_preview_ui)
    193     return;
    194   print_preview_ui->OnInvalidPrinterSettings();
    195 }
    196 
    197 void PrintPreviewMessageHandler::OnSetOptionsFromDocument(
    198     const PrintHostMsg_SetOptionsFromDocument_Params& params) {
    199   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
    200   if (!print_preview_ui)
    201     return;
    202   print_preview_ui->OnSetOptionsFromDocument(params);
    203 }
    204 
    205 bool PrintPreviewMessageHandler::OnMessageReceived(
    206     const IPC::Message& message) {
    207   bool handled = true;
    208   IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
    209     IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
    210                         OnRequestPrintPreview)
    211     IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
    212                         OnDidGetPreviewPageCount)
    213     IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage,
    214                         OnDidPreviewPage)
    215     IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
    216                         OnMetafileReadyForPrinting)
    217     IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
    218                         OnPrintPreviewFailed)
    219     IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
    220                         OnDidGetDefaultPageLayout)
    221     IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewCancelled,
    222                         OnPrintPreviewCancelled)
    223     IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewInvalidPrinterSettings,
    224                         OnInvalidPrinterSettings)
    225     IPC_MESSAGE_HANDLER(PrintHostMsg_SetOptionsFromDocument,
    226                         OnSetOptionsFromDocument)
    227     IPC_MESSAGE_UNHANDLED(handled = false)
    228   IPC_END_MESSAGE_MAP()
    229   return handled;
    230 }
    231 
    232 }  // namespace printing
    233