diff options
author | Michal Klocek <michal.klocek@qt.io> | 2018-07-05 16:12:23 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2018-08-09 09:39:27 +0000 |
commit | 34a7c2cde9ea3fb2d4c297d60a4e16c9d99cdf9b (patch) | |
tree | fed925e2dd9eedc32d4010fa555b3e3194452fdc /src | |
parent | d0f00b47cb91f1f6af920602f8bf8b263a8d7f88 (diff) |
Add printRequest()
Adds printRequested() signal for web content. This signal
is emitted on javascript window.print().
This change updates also qt printview manager implementation,
fixes a corner case and warnings about ipc unconsumed attachments.
Task-number: QTBUG-69237
Task-number: QTBUG-53745
Change-Id: I0c47b732e27e929ac6db237fb562b7d5f9b959c2
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/printing/print_view_manager_base_qt.cpp | 113 | ||||
-rw-r--r-- | src/core/printing/print_view_manager_base_qt.h | 29 | ||||
-rw-r--r-- | src/core/printing/print_view_manager_qt.cpp | 132 | ||||
-rw-r--r-- | src/core/printing/print_view_manager_qt.h | 27 | ||||
-rw-r--r-- | src/core/renderer/print_web_view_helper_delegate_qt.cpp | 4 | ||||
-rw-r--r-- | src/core/web_contents_adapter_client.h | 1 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 8 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p.h | 1 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p_p.h | 1 | ||||
-rw-r--r-- | src/webengine/doc/src/webengineview_lgpl.qdoc | 10 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 18 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage_p.h | 1 |
13 files changed, 244 insertions, 102 deletions
diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index facc4ff84..6c67adbc7 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -72,15 +72,13 @@ namespace QtWebEngineCore { PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) - , cookie_(0) , m_isInsideInnerMessageLoop(false) -#if !defined(OS_MACOSX) - , m_isExpectingFirstPage(false) -#endif , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) + , m_printingRFH(nullptr) { // FIXME: Check if this needs to be executed async: + // TODO: Add isEnabled to profile PrintViewManagerBaseQt::UpdatePrintingEnabled(); } @@ -90,8 +88,15 @@ PrintViewManagerBaseQt::~PrintViewManagerBaseQt() DisconnectFromCurrentPrintJob(); } +void PrintViewManagerBaseQt::SetPrintingRFH(content::RenderFrameHost *rfh) +{ + DCHECK(!m_printingRFH); + m_printingRFH = rfh; +} + void PrintViewManagerBaseQt::UpdatePrintingEnabled() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); bool enabled = false; #if QT_CONFIG(webengine_printing_and_pdf) enabled = true; @@ -112,24 +117,19 @@ base::string16 PrintViewManagerBaseQt::RenderSourceName() return toString16(QLatin1String("")); } -bool PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedBytes> &print_data, +void PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document, + const scoped_refptr<base::RefCountedMemory> &print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets) { std::unique_ptr<printing::PdfMetafileSkia> metafile = std::make_unique<printing::PdfMetafileSkia>(); - if (!metafile->InitFromData(print_data->front(), print_data->size())) { - NOTREACHED() << "Invalid metafile"; - web_contents()->Stop(); - return false; - } + CHECK(metafile->InitFromData(print_data->front(), print_data->size())); // Update the rendered document. It will send notifications to the listener. document->SetDocument(std::move(metafile), page_size, content_area); ShouldQuitFromInnerMessageLoop(); - return true; } printing::PrintedDocument *PrintViewManagerBaseQt::GetDocument(int cookie) @@ -147,7 +147,8 @@ printing::PrintedDocument *PrintViewManagerBaseQt::GetDocument(int cookie) } // IPC handlers -void PrintViewManagerBaseQt::OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params ¶ms) +void PrintViewManagerBaseQt::OnDidPrintDocument(content::RenderFrameHost* /*render_frame_host*/, + const PrintHostMsg_DidPrintDocument_Params ¶ms) { printing::PrintedDocument *document = GetDocument(params.document_cookie); if (!document) @@ -167,10 +168,10 @@ void PrintViewManagerBaseQt::OnDidPrintDocument(const PrintHostMsg_DidPrintDocum web_contents()->Stop(); return; } - scoped_refptr<base::RefCountedBytes> bytes = - base::MakeRefCounted<base::RefCountedBytes>( - reinterpret_cast<const unsigned char*>(shared_buf->memory()), content.data_size); - PrintDocument(document, bytes, params.page_size, params.content_area, params.physical_offsets); + auto data = base::MakeRefCounted<base::RefCountedSharedMemory>( + std::move(shared_buf), content.data_size); + PrintDocument(document, data, params.page_size, params.content_area, + params.physical_offsets); } void PrintViewManagerBaseQt::OnShowInvalidPrinterSettingsError() @@ -182,12 +183,16 @@ void PrintViewManagerBaseQt::DidStartLoading() UpdatePrintingEnabled(); } +// Note: In PrintViewManagerQt we always initiate printing with PrintMsg_InitiatePrintPreview +// so m_printingRFH is never set and used at the moment. void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) { // Terminates or cancels the print job if one was pending. - if (render_frame_host != web_contents()->GetMainFrame()) + if (render_frame_host != m_printingRFH) return; + m_printingRFH = nullptr; + PrintManager::PrintingRenderFrameDeleted(); ReleasePrinterQuery(); @@ -203,12 +208,20 @@ void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render } } -bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) +bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) + IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerBaseQt, message, render_frame_host) IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument) - IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, OnShowInvalidPrinterSettingsError); + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + if (handled) + return true; + handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, + OnShowInvalidPrinterSettingsError); IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled || PrintManager::OnMessageReceived(message, render_frame_host); @@ -225,7 +238,7 @@ void PrintViewManagerBaseQt::Observe(int type, void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details) { switch (event_details.type()) { - case printing::JobEventDetails::FAILED: + case printing::JobEventDetails::FAILED: { TerminatePrintJob(true); content::NotificationService::current()->Notify( @@ -233,21 +246,26 @@ void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetai content::Source<content::WebContents>(web_contents()), content::NotificationService::NoDetails()); break; + } case printing::JobEventDetails::USER_INIT_DONE: case printing::JobEventDetails::DEFAULT_INIT_DONE: - case printing::JobEventDetails::USER_INIT_CANCELED: + case printing::JobEventDetails::USER_INIT_CANCELED: { NOTREACHED(); break; - case printing::JobEventDetails::ALL_PAGES_REQUESTED: + } + case printing::JobEventDetails::ALL_PAGES_REQUESTED: { + ShouldQuitFromInnerMessageLoop(); break; + } case printing::JobEventDetails::NEW_DOC: #if defined(OS_WIN) case printing::JobEventDetails::PAGE_DONE: #endif - case printing::JobEventDetails::DOC_DONE: + case printing::JobEventDetails::DOC_DONE: { // Don't care about the actual printing process. break; - case printing::JobEventDetails::JOB_DONE: + } + case printing::JobEventDetails::JOB_DONE: { // Printing is done, we don't need it anymore. // print_job_->is_job_pending() may still be true, depending on the order // of object registration. @@ -259,6 +277,7 @@ void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetai content::Source<content::WebContents>(web_contents()), content::NotificationService::NoDetails()); break; + } default: NOTREACHED(); break; @@ -273,6 +292,12 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() if (!m_printJob.get() || !m_printJob->is_job_pending()) return false; + // Is the document already complete? + if (m_printJob->document() && m_printJob->document()->IsComplete()) { + m_didPrintingSucceed = true; + return true; + } + // We can't print if there is no renderer. if (!web_contents() || !web_contents()->GetRenderViewHost() || @@ -280,12 +305,6 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() return false; } - // Is the document already complete? - if (m_printJob->document() && m_printJob->document()->IsComplete()) { - m_didPrintingSucceed = true; - return true; - } - // WebContents is either dying or a second consecutive request to print // happened before the first had time to finish. We need to render all the // pages in an hurry if a print_job_ is still pending. No need to wait for it @@ -319,7 +338,7 @@ void PrintViewManagerBaseQt::ShouldQuitFromInnerMessageLoop() m_isInsideInnerMessageLoop) { // We are in a message loop created by RenderAllMissingPagesNow. Quit from // it. - base::MessageLoop::current()->QuitWhenIdleClosure(); + base::RunLoop::QuitCurrentWhenIdleDeprecated(); m_isInsideInnerMessageLoop = false; } } @@ -344,7 +363,7 @@ bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrintJobWorkerOwner* jo if (!job) return false; - m_printJob = new printing::PrintJob(); + m_printJob = base::MakeRefCounted<printing::PrintJob>(); m_printJob->Initialize(job, RenderSourceName(), number_pages_); m_registrar.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<printing::PrintJob>(m_printJob.get())); @@ -369,9 +388,6 @@ void PrintViewManagerBaseQt::DisconnectFromCurrentPrintJob() // DO NOT wait for the job to finish. ReleasePrintJob(); } -#if !defined(OS_MACOSX) - m_isExpectingFirstPage = true; -#endif } void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) @@ -397,13 +413,18 @@ void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) void PrintViewManagerBaseQt::ReleasePrintJob() { - content::RenderFrameHost *rfh = web_contents() ? web_contents()->GetMainFrame() : nullptr; + content::RenderFrameHost* rfh = m_printingRFH; + m_printingRFH = nullptr; if (!m_printJob.get()) return; - if (rfh) - rfh->Send(new PrintMsg_PrintingDone(rfh->GetRoutingID(), m_didPrintingSucceed)); + if (rfh) { + auto msg = std::make_unique<PrintMsg_PrintingDone>(rfh->GetRoutingID(), + m_didPrintingSucceed); + rfh->Send(msg.release()); + } + m_registrar.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<printing::PrintJob>(m_printJob.get())); @@ -411,7 +432,6 @@ void PrintViewManagerBaseQt::ReleasePrintJob() m_printJob = nullptr; } - bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // This value may actually be too low: // @@ -426,19 +446,18 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // memory-bound. static const int kPrinterSettingsTimeout = 60000; base::OneShotTimer quit_timer; - base::RunLoop runLoop; + base::RunLoop run_loop; quit_timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), - runLoop.QuitWhenIdleClosure()); + run_loop.QuitWhenIdleClosure()); m_isInsideInnerMessageLoop = true; // Need to enable recursive task. { - m_quitClosure = runLoop.QuitClosure(); - base::MessageLoop* loop = base::MessageLoop::current(); - base::MessageLoop::ScopedNestableTaskAllower allowNested(loop); - runLoop.Run(); + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + run_loop.Run(); } bool success = true; diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h index 0d86fcf90..eb4302fe8 100644 --- a/src/core/printing/print_view_manager_base_qt.h +++ b/src/core/printing/print_view_manager_base_qt.h @@ -44,7 +44,7 @@ #ifndef PRINT_VIEW_MANAGER_BASE_QT_H #define PRINT_VIEW_MANAGER_BASE_QT_H -#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" #include "base/strings/string16.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" @@ -87,6 +87,8 @@ public: protected: explicit PrintViewManagerBaseQt(content::WebContents*); + void SetPrintingRFH(content::RenderFrameHost* rfh); + // content::WebContentsObserver implementation. // Cancels the print job. void NavigationStopped() override; @@ -97,16 +99,13 @@ protected: content::RenderFrameHost* render_frame_host) override; // IPC Message handlers. - void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params); + void OnDidPrintDocument(content::RenderFrameHost* render_frame_host, + const PrintHostMsg_DidPrintDocument_Params& params); void OnShowInvalidPrinterSettingsError(); // Processes a NOTIFY_PRINT_JOB_EVENT notification. void OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details); - int number_pages_; // Number of pages to print in the print job. - int cookie_; - std::unique_ptr<base::DictionaryValue> m_printSettings; - // content::NotificationObserver implementation. void Observe(int, const content::NotificationSource&, @@ -130,8 +129,8 @@ protected: // Starts printing a document with data given in |print_data|. |print_data| // must successfully initialize a metafile. |document| is the printed // document associated with the print job. Returns true if successful. - bool PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedBytes> &print_data, + void PrintDocument(printing::PrintedDocument *document, + const scoped_refptr<base::RefCountedMemory> &print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets); @@ -155,21 +154,17 @@ protected: private: // Helper method for UpdatePrintingEnabled(). void SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh); + // content::WebContentsObserver implementation. + void DidStartLoading() override; +private: content::NotificationRegistrar m_registrar; scoped_refptr<printing::PrintJob> m_printJob; - // Closure for quitting nested message loop. - base::Closure m_quitClosure; - bool m_isInsideInnerMessageLoop; -#if !defined(OS_MACOSX) - bool m_isExpectingFirstPage; -#endif bool m_didPrintingSucceed; scoped_refptr<printing::PrintQueriesQueue> m_printerQueriesQueue; - // content::WebContentsObserver implementation. - void DidStartLoading() override; - + // The current RFH that is printing with a system printing dialog. + content::RenderFrameHost* m_printingRFH; DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBaseQt); }; diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index bb176d687..fffc91631 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -45,6 +45,7 @@ #include "type_conversion.h" #include "web_engine_context.h" +#include "web_contents_view_qt.h" #include <QtGui/qpagelayout.h> #include <QtGui/qpagesize.h> @@ -66,6 +67,7 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt); namespace { + static const qreal kMicronsToMillimeter = 1000.0f; static std::vector<char> @@ -85,11 +87,10 @@ GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) static scoped_refptr<base::RefCountedBytes> GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { - std::unique_ptr<base::SharedMemory> shared_buf( - new base::SharedMemory(handle, true)); + std::unique_ptr<base::SharedMemory> shared_buf(new base::SharedMemory(handle, true)); if (!shared_buf->Map(data_size)) { - return NULL; + return nullptr; } unsigned char* data = static_cast<unsigned char*>(shared_buf->memory()); @@ -99,9 +100,8 @@ GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) // Write the PDF file to disk. static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, - const base::FilePath& path, - const QtWebEngineCore::PrintViewManagerQt::PrintToPDFFileCallback - &saveCallback) + const base::FilePath &path, + const QtWebEngineCore::PrintViewManagerQt::PrintToPDFFileCallback &saveCallback) { base::AssertBlockingAllowed(); DCHECK_GT(data->size(), 0U); @@ -197,6 +197,19 @@ static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayo namespace QtWebEngineCore { +struct PrintViewManagerQt::FrameDispatchHelper { + PrintViewManagerQt* m_manager; + content::RenderFrameHost* m_renderFrameHost; + + bool Send(IPC::Message* msg) { + return m_renderFrameHost->Send(msg); + } + + void OnSetupScriptedPrintPreview(IPC::Message* reply_msg) { + m_manager->OnSetupScriptedPrintPreview(m_renderFrameHost, reply_msg); + } +}; + PrintViewManagerQt::~PrintViewManagerQt() { } @@ -211,8 +224,7 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou return; if (m_printSettings || !filePath.length()) { - content::BrowserThread::PostTask(content::BrowserThread::UI, - FROM_HERE, + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false)); return; } @@ -220,8 +232,7 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou m_pdfOutputPath = toFilePath(filePath); m_pdfSaveCallback = callback; if (!PrintToPDFInternal(pageLayout, printInColor)) { - content::BrowserThread::PostTask(content::BrowserThread::UI, - FROM_HERE, + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false)); resetPdfState(); } @@ -237,9 +248,8 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, // 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>())); + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(callback, std::vector<char>())); return; } @@ -261,12 +271,27 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, return false; m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout, useCustomMargins)); - m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds - , web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds); + m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, + web_contents()->GetRenderViewHost()-> + GetWebkitPreferences().should_print_backgrounds); m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE); - return web_contents()->GetMainFrame()->Send( - new PrintMsg_InitiatePrintPreview(web_contents()->GetMainFrame()->GetRoutingID(), false)); + + if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed()) + return false; + + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + auto message = std::make_unique<PrintMsg_InitiatePrintPreview>( + rfh->GetRoutingID(), false); + + DCHECK(!m_printPreviewRfh); + + if (!rfh->Send(message.release())) { + return false; + } + + m_printPreviewRfh = rfh; + return true; } #endif // QT_CONFIG(webengine_printing_and_pdf) @@ -274,26 +299,42 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, // PrintedPagesSource implementation. base::string16 PrintViewManagerQt::RenderSourceName() { - return toString16(QLatin1String("")); + return base::string16(); } PrintViewManagerQt::PrintViewManagerQt(content::WebContents *contents) : PrintViewManagerBaseQt(contents) + , m_printPreviewRfh(nullptr) { } // content::WebContentsObserver implementation. -bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) +bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { + FrameDispatchHelper helper = {this, render_frame_host}; 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_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerQt, message, render_frame_host); + IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) + IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview, OnRequestPrintPreview) + IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting, OnMetafileReadyForPrinting); + IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage) + IPC_MESSAGE_FORWARD_DELAY_REPLY( + PrintHostMsg_SetupScriptedPrintPreview, &helper, + FrameDispatchHelper::OnSetupScriptedPrintPreview) + IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview, + OnShowScriptedPrintPreview) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() - return handled || PrintManager::OnMessageReceived(message, render_frame_host); + return handled || PrintViewManagerBaseQt::OnMessageReceived(message, render_frame_host); +} + +void PrintViewManagerQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) +{ + if (render_frame_host == m_printPreviewRfh) + PrintPreviewDone(); + PrintViewManagerBaseQt::RenderFrameDeleted(render_frame_host); } void PrintViewManagerQt::resetPdfState() @@ -309,9 +350,9 @@ void PrintViewManagerQt::resetPdfState() void PrintViewManagerQt::OnRequestPrintPreview( const PrintHostMsg_RequestPrintPreview_Params &/*params*/) { - auto *rfh = web_contents()->GetMainFrame(); - rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), *m_printSettings)); - rfh->Send(new PrintMsg_ClosePrintPreviewDialog(rfh->GetRoutingID())); + m_printPreviewRfh->Send(new PrintMsg_PrintPreview(m_printPreviewRfh->GetRoutingID(), + *m_printSettings)); + PrintPreviewDone(); } void PrintViewManagerQt::OnMetafileReadyForPrinting( @@ -359,6 +400,7 @@ void PrintViewManagerQt::NavigationStopped() base::Bind(m_pdfPrintCallback, std::vector<char>())); } resetPdfState(); + PrintViewManagerBaseQt::NavigationStopped(); } void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) @@ -372,5 +414,39 @@ void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) resetPdfState(); } +void PrintViewManagerQt::OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params ¶ms) +{ + // just consume the message, this is just for sending 'page-preview-ready' for webui +} + +void PrintViewManagerQt::OnSetupScriptedPrintPreview(content::RenderFrameHost* rfh, + IPC::Message* reply_msg) +{ + // ignore the scripted print + rfh->Send(reply_msg); + + content::WebContentsView *view = static_cast<content::WebContentsImpl*>(web_contents())->GetView(); + WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client(); + + if (!client) + return; + + // close preview + rfh->Send(new PrintMsg_ClosePrintPreviewDialog(rfh->GetRoutingID())); + + client->printRequested(); +} + +void PrintViewManagerQt::OnShowScriptedPrintPreview(content::RenderFrameHost* rfh, + bool source_is_modifiable) +{ + // ignore for now +} + +void PrintViewManagerQt::PrintPreviewDone() { + m_printPreviewRfh->Send(new PrintMsg_ClosePrintPreviewDialog( + m_printPreviewRfh->GetRoutingID())); + m_printPreviewRfh = nullptr; +} } // namespace QtWebEngineCore diff --git a/src/core/printing/print_view_manager_qt.h b/src/core/printing/print_view_manager_qt.h index c181d9063..c71ec4a61 100644 --- a/src/core/printing/print_view_manager_qt.h +++ b/src/core/printing/print_view_manager_qt.h @@ -51,6 +51,7 @@ #include "base/strings/string16.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" +#include "components/printing/common/print_messages.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_user_data.h" @@ -77,7 +78,7 @@ QT_END_NAMESPACE namespace QtWebEngineCore { class PrintViewManagerQt - : PrintViewManagerBaseQt + : public PrintViewManagerBaseQt , public content::WebContentsUserData<PrintViewManagerQt> { public: @@ -111,28 +112,38 @@ protected: // content::WebContentsObserver implementation. bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; // IPC handlers void OnDidShowPrintDialog(); void OnRequestPrintPreview(const PrintHostMsg_RequestPrintPreview_Params&); void OnMetafileReadyForPrinting(const PrintHostMsg_DidPreviewDocument_Params& params); + void OnSetupScriptedPrintPreview(content::RenderFrameHost* rfh, + IPC::Message* reply_msg); + void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params); + void OnShowScriptedPrintPreview(content::RenderFrameHost* rfh, + bool source_is_modifiable); + #if QT_CONFIG(webengine_printing_and_pdf) bool PrintToPDFInternal(const QPageLayout &, bool printInColor, bool useCustomMargins = true); #endif - base::FilePath m_pdfOutputPath; - PrintToPDFCallback m_pdfPrintCallback; - PrintToPDFFileCallback m_pdfSaveCallback; - private: - friend class content::WebContentsUserData<PrintViewManagerQt>; - void resetPdfState(); - // content::WebContentsObserver implementation. void DidStartLoading() override; + void PrintPreviewDone(); + +private: + content::RenderFrameHost *m_printPreviewRfh; + base::FilePath m_pdfOutputPath; + PrintToPDFCallback m_pdfPrintCallback; + PrintToPDFFileCallback m_pdfSaveCallback; + std::unique_ptr<base::DictionaryValue> m_printSettings; + friend class content::WebContentsUserData<PrintViewManagerQt>; DISALLOW_COPY_AND_ASSIGN(PrintViewManagerQt); + struct FrameDispatchHelper; }; } // namespace QtWebEngineCore diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp index 79d86b00f..e693cf096 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -53,7 +53,7 @@ PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() bool PrintWebViewHelperDelegateQt::CancelPrerender(content::RenderFrame *) { - return true; + return false; } blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame* frame) @@ -63,7 +63,7 @@ blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFra bool PrintWebViewHelperDelegateQt::IsPrintPreviewEnabled() { - return false; + return true; } bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame* frame) diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 851a6122f..6fd29ec61 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -472,6 +472,7 @@ public: virtual const QObject *holdingQObject() const = 0; virtual void setToolTip(const QString& toolTipText) = 0; virtual ClientType clientType() = 0; + virtual void printRequested() = 0; virtual ProfileAdapter *profileAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index aaa8d58c5..f24ba1d7d 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -640,6 +640,14 @@ WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter() return adapter.data(); } +void QQuickWebEngineViewPrivate::printRequested() +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [q]() { + Q_EMIT q->printRequested(); + }); +} + WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { return m_settings->d_ptr.data(); diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index d400fc75e..f60fdcddf 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -549,6 +549,7 @@ Q_SIGNALS: Q_REVISION(7) void inspectedViewChanged(); Q_REVISION(7) void devToolsViewChanged(); Q_REVISION(7) void registerProtocolHandlerRequested(const QWebEngineRegisterProtocolHandlerRequest &request); + Q_REVISION(8) void printRequested(); #if QT_CONFIG(webengine_testsupport) void testSupportChanged(); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 7e5d1e64f..b030b2a29 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -155,6 +155,7 @@ public: QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; + void printRequested() override; void updateAction(QQuickWebEngineView::WebAction) const; void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc index 741dee2f7..cc826a0d9 100644 --- a/src/webengine/doc/src/webengineview_lgpl.qdoc +++ b/src/webengine/doc/src/webengineview_lgpl.qdoc @@ -1462,3 +1462,13 @@ \sa WebEngineAction */ + +/*! + \qmlsignal WebEngineView::printRequest + \since QtWebEngine 1.8 + + This signal is emitted when the JavaScript \c{window.print()} method is called. + Typically, the signal handler can simply call printToPdf(). + + \sa printToPdf +*/ diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 16a9c138d..5b42b871a 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -739,6 +739,16 @@ QWebEnginePage::QWebEnginePage(QObject* parent) } /*! + \fn void QWebEnginePage::printRequested() + \since 5.12 + + This signal is emitted when the JavaScript \c{window.print()} method is called. + Typically, the signal handler can simply call printToPdf(). + + \sa printToPdf() +*/ + +/*! \enum QWebEnginePage::RenderProcessTerminationStatus \since 5.6 @@ -1751,6 +1761,14 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) view->setToolTip(wrappedTip); } +void QWebEnginePagePrivate::printRequested() +{ + Q_Q(QWebEnginePage); + QTimer::singleShot(0, q, [q](){ + Q_EMIT q->printRequested(); + }); +} + #if QT_CONFIG(menu) QMenu *QWebEnginePage::createStandardContextMenu() { diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 3e5e083df..b8bf61700 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -343,6 +343,7 @@ Q_SIGNALS: void recentlyAudibleChanged(bool recentlyAudible); void pdfPrintingFinished(const QString &filePath, bool success); + void printRequested(); protected: virtual QWebEnginePage *createWindow(WebWindowType type); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index e2329e8f8..66a92dec9 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -146,6 +146,7 @@ public: bool supportsDragging() const override; bool isEnabled() const override; void setToolTip(const QString &toolTipText) override; + void printRequested() override; const QObject *holdingQObject() const override; ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; } |