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