| Index: chrome/browser/printing/pdf_to_emf_converter.cc
|
| diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
|
| index fb0be329e76d0325e4b0c20645adf832fb1d3303..e6277cc57c9dd3c0efc0e5beec2abdf5d73cd78c 100644
|
| --- a/chrome/browser/printing/pdf_to_emf_converter.cc
|
| +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
|
| @@ -12,6 +12,7 @@
|
| #include <utility>
|
| #include <vector>
|
|
|
| +#include "base/callback_helpers.h"
|
| #include "base/files/file.h"
|
| #include "base/files/file_util.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| @@ -20,14 +21,15 @@
|
| #include "base/memory/ptr_util.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "chrome/common/chrome_utility_messages.h"
|
| -#include "chrome/common/chrome_utility_printing_messages.h"
|
| #include "chrome/grit/generated_resources.h"
|
| +#include "components/printing/common/printing.mojom.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/child_process_data.h"
|
| -#include "content/public/browser/utility_process_host.h"
|
| -#include "content/public/browser/utility_process_host_client.h"
|
| +#include "content/public/browser/utility_process_mojo_client.h"
|
| +#include "mojo/public/cpp/bindings/strong_binding.h"
|
| #include "printing/emf_win.h"
|
| #include "printing/pdf_render_settings.h"
|
| +#include "services/service_manager/public/cpp/interface_provider.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
|
|
| namespace printing {
|
| @@ -89,11 +91,11 @@ class LazyEmf : public MetafilePlayer {
|
| };
|
|
|
| // Converts PDF into EMF.
|
| -// Class uses 3 threads: UI, IO and FILE.
|
| +// Class uses 2 threads: UI and FILE.
|
| // Internal workflow is following:
|
| // 1. Create instance on the UI thread. (files_, settings_,)
|
| // 2. Create pdf file on the FILE thread.
|
| -// 3. Start utility process and start conversion on the IO thread.
|
| +// 3. Start utility process and start conversion on the UI thread.
|
| // 4. Utility process returns page count.
|
| // 5. For each page:
|
| // 1. Clients requests page with file handle to a temp file.
|
| @@ -102,7 +104,7 @@ class LazyEmf : public MetafilePlayer {
|
| // All these steps work sequentially, so no data should be accessed
|
| // simultaneously by several threads.
|
| class PdfToEmfUtilityProcessHostClient
|
| - : public content::UtilityProcessHostClient {
|
| + : public base::RefCountedThreadSafe<PdfToEmfUtilityProcessHostClient> {
|
| public:
|
| PdfToEmfUtilityProcessHostClient(
|
| base::WeakPtr<PdfToEmfConverterImpl> converter,
|
| @@ -117,15 +119,6 @@ class PdfToEmfUtilityProcessHostClient
|
|
|
| void Stop();
|
|
|
| - // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters
|
| - // sync message replies.
|
| - bool Send(IPC::Message* msg);
|
| -
|
| - // UtilityProcessHostClient implementation.
|
| - void OnProcessCrashed(int exit_code) override;
|
| - void OnProcessLaunchFailed(int exit_code) override;
|
| - bool OnMessageReceived(const IPC::Message& message) override;
|
| -
|
| private:
|
| class GetPageCallbackData {
|
| public:
|
| @@ -159,13 +152,12 @@ class PdfToEmfUtilityProcessHostClient
|
| DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData);
|
| };
|
|
|
| - ~PdfToEmfUtilityProcessHostClient() override;
|
| + friend class base::RefCountedThreadSafe<PdfToEmfUtilityProcessHostClient>;
|
| + ~PdfToEmfUtilityProcessHostClient();
|
|
|
| // Message handlers.
|
| void OnPageCount(int page_count);
|
| void OnPageDone(bool success, float scale_factor);
|
| - void OnPreCacheFontCharacters(const LOGFONT& log_font,
|
| - const base::string16& characters);
|
|
|
| void OnFailed();
|
| void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf);
|
| @@ -180,8 +172,8 @@ class PdfToEmfUtilityProcessHostClient
|
| // Document loaded callback.
|
| PdfToEmfConverter::StartCallback start_callback_;
|
|
|
| - // Process host for IPC.
|
| - base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
|
| + std::unique_ptr<content::UtilityProcessMojoClient<mojom::PrintingFactory>>
|
| + utility_client_;
|
|
|
| // Queue of callbacks for GetPage() requests. Utility process should reply
|
| // with PageDone in the same order as requests were received.
|
| @@ -189,6 +181,9 @@ class PdfToEmfUtilityProcessHostClient
|
| typedef std::queue<GetPageCallbackData> GetPageCallbacks;
|
| GetPageCallbacks get_page_callbacks_;
|
|
|
| + // Bound and used on the UI thread.
|
| + mojom::PrintingPtr printing_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient);
|
| };
|
|
|
| @@ -297,23 +292,74 @@ bool LazyEmf::LoadEmf(Emf* emf) const {
|
| PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient(
|
| base::WeakPtr<PdfToEmfConverterImpl> converter,
|
| const PdfRenderSettings& settings)
|
| - : converter_(converter), settings_(settings) {
|
| -}
|
| + : converter_(converter), settings_(settings) {}
|
|
|
| PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
|
| }
|
|
|
| +class FontPreCachingImpl : public mojom::FontPreCaching {
|
| + public:
|
| + FontPreCachingImpl() = default;
|
| + ~FontPreCachingImpl() override = default;
|
| +
|
| + static void Create(mojom::FontPreCachingRequest request);
|
| +
|
| + // mojom::FontPreCaching:
|
| + void PreCacheFontCharacters(
|
| + const LOGFONT& log_font,
|
| + const base::string16& characters,
|
| + const PreCacheFontCharactersCallback& callback) override;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(FontPreCachingImpl);
|
| +};
|
| +
|
| +void FontPreCachingImpl::Create(mojom::FontPreCachingRequest request) {
|
| + mojo::MakeStrongBinding(base::MakeUnique<FontPreCachingImpl>(),
|
| + std::move(request));
|
| +}
|
| +
|
| +void FontPreCachingImpl::PreCacheFontCharacters(
|
| + const LOGFONT& font,
|
| + const base::string16& str,
|
| + const PreCacheFontCharactersCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
|
| + // GDI fonts (http://crbug.com/383227), even when using DirectWrite.
|
| + // Eventually this shouldn't be added and should be moved to
|
| + // FontCacheDispatcher too. http://crbug.com/356346.
|
| +
|
| + // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
|
| + // Except that for True Type fonts,
|
| + // GetTextMetrics will not load the font in memory.
|
| + // The only way windows seem to load properly, it is to create a similar
|
| + // device (like the one in which we print), then do an ExtTextOut,
|
| + // as we do in the printing thread, which is sandboxed.
|
| + HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr);
|
| + HFONT font_handle = CreateFontIndirect(&font);
|
| + DCHECK(font_handle != nullptr);
|
| +
|
| + HGDIOBJ old_font = SelectObject(hdc, font_handle);
|
| + DCHECK(old_font != nullptr);
|
| +
|
| + ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr);
|
| +
|
| + SelectObject(hdc, old_font);
|
| + DeleteObject(font_handle);
|
| +
|
| + HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
|
| +
|
| + if (metafile)
|
| + DeleteEnhMetaFile(metafile);
|
| + callback.Run();
|
| +}
|
| +
|
| void PdfToEmfUtilityProcessHostClient::Start(
|
| const scoped_refptr<base::RefCountedMemory>& data,
|
| bool print_text_with_gdi,
|
| const PdfToEmfConverter::StartCallback& start_callback) {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data,
|
| - print_text_with_gdi, start_callback));
|
| - return;
|
| - }
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| // Store callback before any OnFailed() call to make it called on failure.
|
| start_callback_ = start_callback;
|
| @@ -321,11 +367,19 @@ void PdfToEmfUtilityProcessHostClient::Start(
|
| // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
|
| // gdiplus.dll, change how rendering happens, and not be able to correctly
|
| // generate when sent to a metafile DC.
|
| - utility_process_host_ = content::UtilityProcessHost::Create(
|
| - this, base::ThreadTaskRunnerHandle::Get())
|
| - ->AsWeakPtr();
|
| - utility_process_host_->SetName(l10n_util::GetStringUTF16(
|
| - IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME));
|
| + utility_client_ = base::MakeUnique<
|
| + content::UtilityProcessMojoClient<mojom::PrintingFactory>>(
|
| + l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME));
|
| + utility_client_->set_error_callback(
|
| + base::Bind(&PdfToEmfUtilityProcessHostClient::OnFailed, this));
|
| + utility_client_->Start();
|
| + mojom::FontPreCachingPtr font_precaching;
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&FontPreCachingImpl::Create,
|
| + base::Passed(mojo::MakeRequest(&font_precaching))));
|
| + utility_client_->service()->MakePrinting(mojo::MakeRequest(&printing_),
|
| + std::move(font_precaching));
|
|
|
| BrowserThread::PostTaskAndReplyWithResult(
|
| BrowserThread::FILE, FROM_HERE,
|
| @@ -336,45 +390,30 @@ void PdfToEmfUtilityProcessHostClient::Start(
|
|
|
| void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi,
|
| ScopedTempFile pdf) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (!utility_process_host_ || !pdf)
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (!utility_client_ || !pdf)
|
| return OnFailed();
|
| - // Should reply with OnPageCount().
|
| - Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
|
| - IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_,
|
| - print_text_with_gdi));
|
| + printing_->RenderPDFPagesToMetafiles(
|
| + pdf->Duplicate(), settings_, print_text_with_gdi,
|
| + base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageCount, this));
|
| }
|
|
|
| void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| if (start_callback_.is_null())
|
| return OnFailed();
|
| - BrowserThread::PostTask(BrowserThread::UI,
|
| - FROM_HERE,
|
| - base::Bind(&PdfToEmfConverterImpl::RunCallback,
|
| - converter_,
|
| - base::Bind(start_callback_, page_count)));
|
| - start_callback_.Reset();
|
| + base::ResetAndReturn(&start_callback_).Run(page_count);
|
| }
|
|
|
| void PdfToEmfUtilityProcessHostClient::GetPage(
|
| int page_number,
|
| const PdfToEmfConverter::GetPageCallback& get_page_callback) {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(&PdfToEmfUtilityProcessHostClient::GetPage,
|
| - this,
|
| - page_number,
|
| - get_page_callback));
|
| - return;
|
| - }
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| // Store callback before any OnFailed() call to make it called on failure.
|
| get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback));
|
|
|
| - if (!utility_process_host_)
|
| + if (!utility_client_)
|
| return OnFailed();
|
|
|
| BrowserThread::PostTaskAndReplyWithResult(
|
| @@ -389,20 +428,18 @@ void PdfToEmfUtilityProcessHostClient::GetPage(
|
| void PdfToEmfUtilityProcessHostClient::OnTempEmfReady(
|
| GetPageCallbackData* callback_data,
|
| ScopedTempFile emf) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (!utility_process_host_ || !emf)
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (!utility_client_ || !emf)
|
| return OnFailed();
|
| - IPC::PlatformFileForTransit transit =
|
| - IPC::GetPlatformFileForTransit(emf->GetPlatformFile(), false);
|
| callback_data->set_emf(std::move(emf));
|
| - // Should reply with OnPageDone().
|
| - Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(
|
| - callback_data->page_number(), transit));
|
| + printing_->RenderPDFPagesToMetafilesGetPage(
|
| + callback_data->page_number(), emf->Duplicate(),
|
| + base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageDone, this));
|
| }
|
|
|
| void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success,
|
| float scale_factor) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| if (get_page_callbacks_.empty())
|
| return OnFailed();
|
| GetPageCallbackData& data = get_page_callbacks_.front();
|
| @@ -415,97 +452,22 @@ void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success,
|
| emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf));
|
| }
|
|
|
| - BrowserThread::PostTask(BrowserThread::UI,
|
| - FROM_HERE,
|
| - base::Bind(&PdfToEmfConverterImpl::RunCallback,
|
| - converter_,
|
| - base::Bind(data.callback(),
|
| - data.page_number(),
|
| - scale_factor,
|
| - base::Passed(&emf))));
|
| + data.callback().Run(data.page_number(), scale_factor, std::move(emf));
|
| get_page_callbacks_.pop();
|
| }
|
|
|
| -void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters(
|
| - const LOGFONT& font,
|
| - const base::string16& str) {
|
| - // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
|
| - // GDI fonts (http://crbug.com/383227), even when using DirectWrite.
|
| - // Eventually this shouldn't be added and should be moved to
|
| - // FontCacheDispatcher too. http://crbug.com/356346.
|
| -
|
| - // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
|
| - // Except that for True Type fonts,
|
| - // GetTextMetrics will not load the font in memory.
|
| - // The only way windows seem to load properly, it is to create a similar
|
| - // device (like the one in which we print), then do an ExtTextOut,
|
| - // as we do in the printing thread, which is sandboxed.
|
| - HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr);
|
| - HFONT font_handle = CreateFontIndirect(&font);
|
| - DCHECK(font_handle != nullptr);
|
| -
|
| - HGDIOBJ old_font = SelectObject(hdc, font_handle);
|
| - DCHECK(old_font != nullptr);
|
| -
|
| - ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr);
|
| -
|
| - SelectObject(hdc, old_font);
|
| - DeleteObject(font_handle);
|
| -
|
| - HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
|
| -
|
| - if (metafile)
|
| - DeleteEnhMetaFile(metafile);
|
| -}
|
| -
|
| void PdfToEmfUtilityProcessHostClient::Stop() {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this));
|
| - return;
|
| - }
|
| - Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
|
| -}
|
| -
|
| -void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
|
| - OnFailed();
|
| -}
|
| -
|
| -void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) {
|
| - OnFailed();
|
| -}
|
| -
|
| -bool PdfToEmfUtilityProcessHostClient::OnMessageReceived(
|
| - const IPC::Message& message) {
|
| - bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message)
|
| - IPC_MESSAGE_HANDLER(
|
| - ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
|
| - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
|
| - OnPageDone)
|
| - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters,
|
| - OnPreCacheFontCharacters)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - return handled;
|
| -}
|
| -
|
| -bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) {
|
| - if (utility_process_host_)
|
| - return utility_process_host_->Send(msg);
|
| - delete msg;
|
| - return false;
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + printing_.reset();
|
| }
|
|
|
| void PdfToEmfUtilityProcessHostClient::OnFailed() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| if (!start_callback_.is_null())
|
| OnPageCount(0);
|
| while (!get_page_callbacks_.empty())
|
| OnPageDone(false, 0.0f);
|
| - utility_process_host_.reset();
|
| + utility_client_.reset();
|
| }
|
|
|
| PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) {
|
|
|