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) { |