diff options
Diffstat (limited to 'src/core/print_view_manager_qt.cpp')
-rw-r--r-- | src/core/print_view_manager_qt.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp new file mode 100644 index 000000000..f657b8289 --- /dev/null +++ b/src/core/print_view_manager_qt.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Copyright 2013 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 "print_view_manager_qt.h" + +#include "type_conversion.h" +#include "web_engine_context.h" + +#include <QtGui/QPageLayout> +#include <QtGui/QPageSize> + +#include "base/values.h" +#include "chrome/browser/printing/print_job_manager.h" +#include "chrome/browser/printing/printer_query.h" +#include "components/printing/common/print_messages.h" +#include "content/public/browser/browser_thread.h" +#include "printing/pdf_metafile_skia.h" +#include "printing/print_job_constants.h" + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt); + +namespace { +static const qreal kMicronsToMillimeter = 1000.0f; + +static std::vector<char> +GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { + scoped_ptr<base::SharedMemory> shared_buf( + new base::SharedMemory(handle, true)); + + if (!shared_buf->Map(data_size)) { + return std::vector<char>(); + } + + char* data = static_cast<char*>(shared_buf->memory()); + return std::vector<char>(data, data + data_size); +} + +static scoped_refptr<base::RefCountedBytes> +GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { + scoped_ptr<base::SharedMemory> shared_buf( + new base::SharedMemory(handle, true)); + + if (!shared_buf->Map(data_size)) { + return NULL; + } + + unsigned char* data = static_cast<unsigned char*>(shared_buf->memory()); + std::vector<unsigned char> dataVector(data, data + data_size); + return base::RefCountedBytes::TakeVector(&dataVector); +} + +// Write the PDF file to disk. +static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, + const base::FilePath& path) { + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); + DCHECK_GT(data->size(), 0U); + + printing::PdfMetafileSkia metafile; + metafile.InitFromData(static_cast<const void*>(data->front()), data->size()); + + base::File file(path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + if (file.IsValid()) + metafile.SaveTo(&file); +} + +static base::DictionaryValue *createPrintSettings() +{ + base::DictionaryValue *printSettings = new base::DictionaryValue(); + // TO DO: Check if we can use the request ID from Qt here somehow. + static int internalRequestId = 0; + + printSettings->SetBoolean(printing::kIsFirstRequest, internalRequestId++ == 0); + printSettings->SetInteger(printing::kPreviewRequestID, internalRequestId); + + // The following are standard settings that Chromium expects to be set. + printSettings->SetBoolean(printing::kSettingPrintToPDF, true); + printSettings->SetBoolean(printing::kSettingCloudPrintDialog, false); + printSettings->SetBoolean(printing::kSettingPrintWithPrivet, false); + printSettings->SetBoolean(printing::kSettingPrintWithExtension, false); + + printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); + printSettings->SetBoolean(printing::kSettingPreviewModifiable, false); + printSettings->SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX); + printSettings->SetInteger(printing::kSettingCopies, 1); + printSettings->SetBoolean(printing::kSettingCollate, false); + printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); + printSettings->SetBoolean(printing::kSettingPreviewModifiable, false); + + printSettings->SetBoolean(printing::kSettingShouldPrintSelectionOnly, false); + printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, true); + printSettings->SetBoolean(printing::kSettingHeaderFooterEnabled, false); + printSettings->SetString(printing::kSettingDeviceName, ""); + printSettings->SetInteger(printing::kPreviewUIID, 12345678); + + return printSettings; +} + +static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayout &pageLayout) +{ + base::DictionaryValue *printSettings = createPrintSettings(); + + //Set page size attributes, chromium expects these in micrometers + QSizeF pageSizeInMilimeter = pageLayout.pageSize().size(QPageSize::Millimeter); + scoped_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue); + sizeDict->SetInteger(printing::kSettingMediaSizeWidthMicrons, pageSizeInMilimeter.width() * kMicronsToMillimeter); + sizeDict->SetInteger(printing::kSettingMediaSizeHeightMicrons, pageSizeInMilimeter.height() * kMicronsToMillimeter); + printSettings->Set(printing::kSettingMediaSize, std::move(sizeDict)); + + // Apply page margins + QMargins pageMarginsInPoints = pageLayout.marginsPoints(); + scoped_ptr<base::DictionaryValue> marginsDict(new base::DictionaryValue); + marginsDict->SetInteger(printing::kSettingMarginTop, pageMarginsInPoints.top()); + marginsDict->SetInteger(printing::kSettingMarginBottom, pageMarginsInPoints.bottom()); + marginsDict->SetInteger(printing::kSettingMarginLeft, pageMarginsInPoints.left()); + marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right()); + printSettings->Set(printing::kSettingMarginsCustom, std::move(marginsDict)); + printSettings->SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS); + + printSettings->SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape); + + return printSettings; +} + +} // namespace + +namespace QtWebEngineCore { + +PrintViewManagerQt::~PrintViewManagerQt() +{ +} + +#if defined(ENABLE_BASIC_PRINTING) +bool PrintViewManagerQt::PrintToPDF(const QPageLayout &pageLayout, const QString &filePath) +{ + if (m_printSettings || !filePath.length()) + return false; + + m_pdfOutputPath = toFilePath(filePath); + if (!PrintToPDFInternal(pageLayout)) { + resetPdfState(); + return false; + } + return true; +} + +bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, const PrintToPDFCallback& callback) +{ + if (callback.is_null()) + return false; + + // If there already is a pending print in progress, don't try starting another one. + if (m_printSettings) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, std::vector<char>())); + return false; + } + + m_pdfPrintCallback = callback; + if (!PrintToPDFInternal(pageLayout)) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, std::vector<char>())); + + resetPdfState(); + return false; + } + return true; +} + +bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout) +{ + if (!pageLayout.isValid()) + return false; + m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout)); + + m_printSettings->SetInteger(printing::kSettingColor, printing::COLOR); + return Send(new PrintMsg_InitiatePrintPreview(routing_id(), false)); +} + +#endif // defined(ENABLE_BASIC_PRINTING) + +// PrintedPagesSource implementation. +base::string16 PrintViewManagerQt::RenderSourceName() +{ + return toString16(QLatin1String("")); +} + +PrintViewManagerQt::PrintViewManagerQt(content::WebContents *contents) + : PrintViewManagerBaseQt(contents) +{ + +} + +// content::WebContentsObserver implementation. +bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message) +{ + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerQt, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) + IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview, + OnRequestPrintPreview) + IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting, + OnMetafileReadyForPrinting); + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled || PrintManager::OnMessageReceived(message); +} + +void PrintViewManagerQt::resetPdfState() +{ + m_pdfOutputPath.clear(); + m_pdfPrintCallback.Reset(); + m_printSettings.reset(); +} + +// IPC handlers + +void PrintViewManagerQt::OnRequestPrintPreview( + const PrintHostMsg_RequestPrintPreview_Params& params) +{ + Send(new PrintMsg_PrintPreview(routing_id(), *m_printSettings)); +} + +void PrintViewManagerQt::OnMetafileReadyForPrinting( + const PrintHostMsg_DidPreviewDocument_Params& params) +{ + StopWorker(params.document_cookie); + + // Create local copies so we can reset the state and take a new pdf print job. + base::Callback<void(const std::vector<char>&)> pdf_print_callback = m_pdfPrintCallback; + base::FilePath pdfOutputPath = m_pdfOutputPath; + + resetPdfState(); + + if (!pdf_print_callback.is_null()) { + std::vector<char> data_vector = GetStdVectorFromHandle(params.metafile_data_handle, params.data_size); + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(pdf_print_callback, data_vector)); + } else { + scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.metafile_data_handle, params.data_size); + content::BrowserThread::PostTask(content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&SavePdfFile, data_bytes, pdfOutputPath)); + } +} + +void PrintViewManagerQt::OnDidShowPrintDialog() +{ +} + +// content::WebContentsObserver implementation. +void PrintViewManagerQt::DidStartLoading() +{ +} + +// content::WebContentsObserver implementation. +// Cancels the print job. +void PrintViewManagerQt::NavigationStopped() +{ + if (!m_pdfPrintCallback.is_null()) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(m_pdfPrintCallback, std::vector<char>())); + } + resetPdfState(); +} + +void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) +{ + PrintViewManagerBaseQt::RenderProcessGone(status); + if (!m_pdfPrintCallback.is_null()) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(m_pdfPrintCallback, std::vector<char>())); + } + resetPdfState(); +} + + +} // namespace QtWebEngineCore |