blob: f3c316a3e638a8b04d83fa251298627d246373b8 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/printing/print_preview_message_handler.h"
#include <vector>
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/print_preview_tab_controller.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/print_preview_ui.h"
#include "chrome/common/print_messages.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/public/browser/browser_thread.h"
#include "printing/page_size_margins.h"
#include "printing/print_job_constants.h"
using content::BrowserThread;
namespace {
void StopWorker(int document_cookie) {
if (document_cookie <= 0)
return;
printing::PrintJobManager* print_job_manager =
g_browser_process->print_job_manager();
scoped_refptr<printing::PrinterQuery> printer_query;
print_job_manager->PopPrinterQuery(document_cookie, &printer_query);
if (printer_query.get()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&printing::PrinterQuery::StopWorker, printer_query.get()));
}
}
RefCountedBytes* GetDataFromHandle(base::SharedMemoryHandle handle,
uint32 data_size) {
scoped_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(handle, true));
if (!shared_buf->Map(data_size)) {
NOTREACHED();
return NULL;
}
char* preview_data = static_cast<char*>(shared_buf->memory());
std::vector<unsigned char> data(data_size);
memcpy(&data[0], preview_data, data_size);
return RefCountedBytes::TakeVector(&data);
}
} // namespace
namespace printing {
PrintPreviewMessageHandler::PrintPreviewMessageHandler(
TabContents* tab_contents)
: content::WebContentsObserver(tab_contents) {
DCHECK(tab_contents);
}
PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
}
TabContentsWrapper* PrintPreviewMessageHandler::GetPrintPreviewTab() {
PrintPreviewTabController* tab_controller =
PrintPreviewTabController::GetInstance();
if (!tab_controller)
return NULL;
return tab_controller->GetPrintPreviewForTab(tab_contents_wrapper());
}
TabContentsWrapper* PrintPreviewMessageHandler::tab_contents_wrapper() {
return TabContentsWrapper::GetCurrentWrapperForContents(tab_contents());
}
PrintPreviewUI* PrintPreviewMessageHandler::OnFailure(int document_cookie) {
// Always need to stop the worker.
StopWorker(document_cookie);
// Inform the print preview tab of the failure.
TabContentsWrapper* print_preview_tab = GetPrintPreviewTab();
// User might have closed it already.
if (!print_preview_tab || !print_preview_tab->tab_contents()->GetWebUI())
return NULL;
return static_cast<PrintPreviewUI*>(
print_preview_tab->tab_contents()->GetWebUI());
}
void PrintPreviewMessageHandler::OnRequestPrintPreview(
bool source_is_modifiable) {
PrintPreviewTabController::PrintPreview(tab_contents_wrapper());
PrintPreviewUI::SetSourceIsModifiable(GetPrintPreviewTab(),
source_is_modifiable);
}
void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(
const PrintHostMsg_DidGetPreviewPageCount_Params& params) {
if (params.page_count <= 0) {
NOTREACHED();
return;
}
TabContentsWrapper* print_preview_tab = GetPrintPreviewTab();
if (!print_preview_tab || !print_preview_tab->tab_contents()->GetWebUI())
return;
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
print_preview_tab->tab_contents()->GetWebUI());
if (!params.is_modifiable || params.clear_preview_data)
print_preview_ui->ClearAllPreviewData();
print_preview_ui->OnDidGetPreviewPageCount(params);
}
void PrintPreviewMessageHandler::OnDidPreviewPage(
const PrintHostMsg_DidPreviewPage_Params& params) {
TabContentsWrapper* print_preview_tab = GetPrintPreviewTab();
if (!print_preview_tab || !print_preview_tab->tab_contents()->GetWebUI())
return;
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
print_preview_tab->tab_contents()->GetWebUI());
int page_number = params.page_number;
if (page_number >= FIRST_PAGE_INDEX && params.data_size) {
RefCountedBytes* data_bytes =
GetDataFromHandle(params.metafile_data_handle, params.data_size);
DCHECK(data_bytes);
print_preview_ui->SetPrintPreviewDataForIndex(page_number, data_bytes);
print_preview_ui->OnDidPreviewPage(page_number, params.preview_request_id);
}
}
void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
const PrintHostMsg_DidPreviewDocument_Params& params) {
// Always try to stop the worker.
StopWorker(params.document_cookie);
if (params.expected_pages_count <= 0) {
NOTREACHED();
return;
}
// Get the print preview tab.
TabContentsWrapper* print_preview_tab = GetPrintPreviewTab();
// User might have closed it already.
if (!print_preview_tab || !print_preview_tab->tab_contents()->GetWebUI())
return;
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
print_preview_tab->tab_contents()->GetWebUI());
if (params.reuse_existing_data) {
// Need to match normal rendering where we are expected to send this.
PrintHostMsg_DidGetPreviewPageCount_Params temp_params;
temp_params.page_count = params.expected_pages_count;
temp_params.document_cookie = params.document_cookie;
temp_params.is_modifiable = params.modifiable;
temp_params.preview_request_id = params.preview_request_id;
print_preview_ui->OnDidGetPreviewPageCount(temp_params);
print_preview_ui->OnReusePreviewData(params.preview_request_id);
return;
}
// TODO(joth): This seems like a good match for using RefCountedStaticMemory
// to avoid the memory copy, but the SetPrintPreviewData call chain below
// needs updating to accept the RefCountedMemory* base class.
RefCountedBytes* data_bytes =
GetDataFromHandle(params.metafile_data_handle, params.data_size);
if (!data_bytes)
return;
print_preview_ui->SetPrintPreviewDataForIndex(COMPLETE_PREVIEW_DOCUMENT_INDEX,
data_bytes);
print_preview_ui->OnPreviewDataIsAvailable(
params.expected_pages_count, params.preview_request_id);
}
void PrintPreviewMessageHandler::OnPrintPreviewFailed(int document_cookie) {
PrintPreviewUI* print_preview_ui = OnFailure(document_cookie);
if (!print_preview_ui)
return;
print_preview_ui->OnPrintPreviewFailed();
}
void PrintPreviewMessageHandler::OnDidGetDefaultPageLayout(
const PageSizeMargins& page_layout_in_points) {
TabContentsWrapper* print_preview_tab = GetPrintPreviewTab();
if (!print_preview_tab || !print_preview_tab->tab_contents()->GetWebUI())
return;
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
print_preview_tab->tab_contents()->GetWebUI());
print_preview_ui->OnDidGetDefaultPageLayout(page_layout_in_points);
}
void PrintPreviewMessageHandler::OnPrintPreviewCancelled(int document_cookie) {
// Always need to stop the worker.
StopWorker(document_cookie);
}
void PrintPreviewMessageHandler::OnInvalidPrinterSettings(int document_cookie) {
PrintPreviewUI* print_preview_ui = OnFailure(document_cookie);
if (!print_preview_ui)
return;
print_preview_ui->OnInvalidPrinterSettings();
}
bool PrintPreviewMessageHandler::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
OnRequestPrintPreview)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
OnDidGetPreviewPageCount)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage,
OnDidPreviewPage)
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
OnPrintPreviewFailed)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
OnDidGetDefaultPageLayout)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewCancelled,
OnPrintPreviewCancelled)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewInvalidPrinterSettings,
OnInvalidPrinterSettings)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PrintPreviewMessageHandler::NavigateToPendingEntry(
const GURL& url,
NavigationController::ReloadType reload_type) {
TabContentsWrapper* tab = tab_contents_wrapper();
TabContentsWrapper* preview_tab = GetPrintPreviewTab();
if (tab == preview_tab) {
// Cloud print sign-in reloads the page.
DCHECK(PrintPreviewTabController::IsPrintPreviewURL(url));
DCHECK_EQ(NavigationController::RELOAD, reload_type);
return;
}
// If |tab| is navigating and it has a print preview tab, notify |tab| to
// consider print preview done so it unfreezes the renderer in the case of
// window.print().
if (preview_tab)
tab->print_view_manager()->PrintPreviewDone();
}
} // namespace printing