OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/printing/pdf_to_emf_converter.h" | 5 #include "chrome/browser/printing/pdf_to_emf_converter.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <windows.h> | 8 #include <windows.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 #include <queue> | 11 #include <queue> |
12 #include <utility> | 12 #include <utility> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/files/file.h" | 15 #include "base/files/file.h" |
16 #include "base/files/file_util.h" | 16 #include "base/files/file_util.h" |
17 #include "base/files/scoped_temp_dir.h" | 17 #include "base/files/scoped_temp_dir.h" |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/macros.h" | 19 #include "base/macros.h" |
20 #include "base/memory/ptr_util.h" | 20 #include "base/memory/ptr_util.h" |
21 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
22 #include "chrome/common/chrome_utility_messages.h" | 22 #include "chrome/common/chrome_utility_messages.h" |
23 #include "chrome/common/chrome_utility_printing_messages.h" | |
24 #include "chrome/grit/generated_resources.h" | 23 #include "chrome/grit/generated_resources.h" |
24 #include "components/printing/common/printing.mojom.h" | |
25 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/child_process_data.h" | 26 #include "content/public/browser/child_process_data.h" |
27 #include "content/public/browser/utility_process_host.h" | 27 #include "content/public/browser/utility_process_mojo_client.h" |
28 #include "content/public/browser/utility_process_host_client.h" | 28 #include "mojo/public/cpp/bindings/strong_binding.h" |
29 #include "printing/emf_win.h" | 29 #include "printing/emf_win.h" |
30 #include "printing/pdf_render_settings.h" | 30 #include "printing/pdf_render_settings.h" |
31 #include "services/service_manager/public/cpp/interface_provider.h" | |
31 #include "ui/base/l10n/l10n_util.h" | 32 #include "ui/base/l10n/l10n_util.h" |
32 | 33 |
33 namespace printing { | 34 namespace printing { |
34 | 35 |
35 namespace { | 36 namespace { |
36 | 37 |
37 using content::BrowserThread; | 38 using content::BrowserThread; |
38 | 39 |
39 class PdfToEmfConverterImpl; | 40 class PdfToEmfConverterImpl; |
40 | 41 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 void Close() const; | 83 void Close() const; |
83 bool LoadEmf(Emf* emf) const; | 84 bool LoadEmf(Emf* emf) const; |
84 | 85 |
85 mutable scoped_refptr<RefCountedTempDir> temp_dir_; | 86 mutable scoped_refptr<RefCountedTempDir> temp_dir_; |
86 mutable ScopedTempFile file_; // Mutable because of consts in base class. | 87 mutable ScopedTempFile file_; // Mutable because of consts in base class. |
87 | 88 |
88 DISALLOW_COPY_AND_ASSIGN(LazyEmf); | 89 DISALLOW_COPY_AND_ASSIGN(LazyEmf); |
89 }; | 90 }; |
90 | 91 |
91 // Converts PDF into EMF. | 92 // Converts PDF into EMF. |
92 // Class uses 3 threads: UI, IO and FILE. | 93 // Class uses 2 threads: UI and FILE. |
93 // Internal workflow is following: | 94 // Internal workflow is following: |
94 // 1. Create instance on the UI thread. (files_, settings_,) | 95 // 1. Create instance on the UI thread. (files_, settings_,) |
95 // 2. Create pdf file on the FILE thread. | 96 // 2. Create pdf file on the FILE thread. |
96 // 3. Start utility process and start conversion on the IO thread. | 97 // 3. Start utility process and start conversion on the UI thread. |
97 // 4. Utility process returns page count. | 98 // 4. Utility process returns page count. |
98 // 5. For each page: | 99 // 5. For each page: |
99 // 1. Clients requests page with file handle to a temp file. | 100 // 1. Clients requests page with file handle to a temp file. |
100 // 2. Utility converts the page, save it to the file and reply. | 101 // 2. Utility converts the page, save it to the file and reply. |
101 // | 102 // |
102 // All these steps work sequentially, so no data should be accessed | 103 // All these steps work sequentially, so no data should be accessed |
103 // simultaneously by several threads. | 104 // simultaneously by several threads. |
104 class PdfToEmfUtilityProcessHostClient | 105 class PdfToEmfUtilityProcessHostClient |
105 : public content::UtilityProcessHostClient { | 106 : public base::RefCountedThreadSafe<PdfToEmfUtilityProcessHostClient> { |
106 public: | 107 public: |
107 PdfToEmfUtilityProcessHostClient( | 108 PdfToEmfUtilityProcessHostClient( |
108 base::WeakPtr<PdfToEmfConverterImpl> converter, | 109 base::WeakPtr<PdfToEmfConverterImpl> converter, |
109 const PdfRenderSettings& settings); | 110 const PdfRenderSettings& settings); |
110 | 111 |
111 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 112 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
112 bool print_text_with_gdi, | 113 bool print_text_with_gdi, |
113 const PdfToEmfConverter::StartCallback& start_callback); | 114 const PdfToEmfConverter::StartCallback& start_callback); |
114 | 115 |
115 void GetPage(int page_number, | 116 void GetPage(int page_number, |
116 const PdfToEmfConverter::GetPageCallback& get_page_callback); | 117 const PdfToEmfConverter::GetPageCallback& get_page_callback); |
117 | 118 |
118 void Stop(); | 119 void Stop(); |
119 | 120 |
120 // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters | |
121 // sync message replies. | |
122 bool Send(IPC::Message* msg); | |
123 | |
124 // UtilityProcessHostClient implementation. | |
125 void OnProcessCrashed(int exit_code) override; | |
126 void OnProcessLaunchFailed(int exit_code) override; | |
127 bool OnMessageReceived(const IPC::Message& message) override; | |
128 | |
129 private: | 121 private: |
130 class GetPageCallbackData { | 122 class GetPageCallbackData { |
131 public: | 123 public: |
132 GetPageCallbackData(int page_number, | 124 GetPageCallbackData(int page_number, |
133 PdfToEmfConverter::GetPageCallback callback) | 125 PdfToEmfConverter::GetPageCallback callback) |
134 : page_number_(page_number), callback_(callback) {} | 126 : page_number_(page_number), callback_(callback) {} |
135 | 127 |
136 GetPageCallbackData(GetPageCallbackData&& other) { | 128 GetPageCallbackData(GetPageCallbackData&& other) { |
137 *this = std::move(other); | 129 *this = std::move(other); |
138 } | 130 } |
(...skipping 13 matching lines...) Expand all Loading... | |
152 void set_emf(ScopedTempFile emf) { emf_ = std::move(emf); } | 144 void set_emf(ScopedTempFile emf) { emf_ = std::move(emf); } |
153 | 145 |
154 private: | 146 private: |
155 int page_number_; | 147 int page_number_; |
156 PdfToEmfConverter::GetPageCallback callback_; | 148 PdfToEmfConverter::GetPageCallback callback_; |
157 ScopedTempFile emf_; | 149 ScopedTempFile emf_; |
158 | 150 |
159 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); | 151 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); |
160 }; | 152 }; |
161 | 153 |
154 friend class base::RefCountedThreadSafe<PdfToEmfUtilityProcessHostClient>; | |
162 ~PdfToEmfUtilityProcessHostClient() override; | 155 ~PdfToEmfUtilityProcessHostClient() override; |
163 | 156 |
164 // Message handlers. | 157 // Message handlers. |
165 void OnPageCount(int page_count); | 158 void OnPageCount(int page_count); |
166 void OnPageDone(bool success, float scale_factor); | 159 void OnPageDone(bool success, float scale_factor); |
167 void OnPreCacheFontCharacters(const LOGFONT& log_font, | |
168 const base::string16& characters); | |
169 | 160 |
170 void OnFailed(); | 161 void OnFailed(); |
171 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); | 162 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); |
172 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); | 163 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); |
173 | 164 |
174 scoped_refptr<RefCountedTempDir> temp_dir_; | 165 scoped_refptr<RefCountedTempDir> temp_dir_; |
175 | 166 |
176 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. | 167 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. |
177 base::WeakPtr<PdfToEmfConverterImpl> converter_; | 168 base::WeakPtr<PdfToEmfConverterImpl> converter_; |
178 PdfRenderSettings settings_; | 169 PdfRenderSettings settings_; |
179 | 170 |
180 // Document loaded callback. | 171 // Document loaded callback. |
181 PdfToEmfConverter::StartCallback start_callback_; | 172 PdfToEmfConverter::StartCallback start_callback_; |
182 | 173 |
183 // Process host for IPC. | 174 std::unique_ptr<content::UtilityProcessMojoClient<mojom::PrintingFactory>> |
184 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; | 175 utility_client_; |
185 | 176 |
186 // Queue of callbacks for GetPage() requests. Utility process should reply | 177 // Queue of callbacks for GetPage() requests. Utility process should reply |
187 // with PageDone in the same order as requests were received. | 178 // with PageDone in the same order as requests were received. |
188 // Use containers that keeps element pointers valid after push() and pop(). | 179 // Use containers that keeps element pointers valid after push() and pop(). |
189 typedef std::queue<GetPageCallbackData> GetPageCallbacks; | 180 typedef std::queue<GetPageCallbackData> GetPageCallbacks; |
190 GetPageCallbacks get_page_callbacks_; | 181 GetPageCallbacks get_page_callbacks_; |
191 | 182 |
183 // Bound and used on the UI thread. | |
184 mojom::PrintingPtr printing_; | |
185 | |
192 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); | 186 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); |
193 }; | 187 }; |
194 | 188 |
195 class PdfToEmfConverterImpl : public PdfToEmfConverter { | 189 class PdfToEmfConverterImpl : public PdfToEmfConverter { |
196 public: | 190 public: |
197 PdfToEmfConverterImpl(); | 191 PdfToEmfConverterImpl(); |
198 | 192 |
199 ~PdfToEmfConverterImpl() override; | 193 ~PdfToEmfConverterImpl() override; |
200 | 194 |
201 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 195 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 return false; | 284 return false; |
291 std::vector<char> data(size); | 285 std::vector<char> data(size); |
292 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) | 286 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) |
293 return false; | 287 return false; |
294 return emf->InitFromData(data.data(), data.size()); | 288 return emf->InitFromData(data.data(), data.size()); |
295 } | 289 } |
296 | 290 |
297 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( | 291 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( |
298 base::WeakPtr<PdfToEmfConverterImpl> converter, | 292 base::WeakPtr<PdfToEmfConverterImpl> converter, |
299 const PdfRenderSettings& settings) | 293 const PdfRenderSettings& settings) |
300 : converter_(converter), settings_(settings) { | 294 : converter_(converter), settings_(settings) {} |
295 | |
296 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | |
301 } | 297 } |
302 | 298 |
303 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | 299 class FontPreCachingImpl : public mojom::FontPreCaching { |
Sam McNally
2017/01/12 04:49:53
This class seems bit scattered.
tibell
2017/01/13 02:51:10
Done.
| |
300 public: | |
301 static void Create(mojom::FontPreCachingRequest request); | |
302 | |
303 // mojom::FontPreCaching: | |
304 void PreCacheFontCharacters( | |
305 const LOGFONT& log_font, | |
306 const base::string16& characters, | |
307 const PreCacheFontCharactersCallback& callback) override; | |
308 | |
309 private: | |
310 // Interface that receives font precaching requests. | |
311 mojo::StrongBinding<mojom::FontPreCaching> binding_; | |
312 | |
313 DISALLOW_COPY_AND_ASSIGN(FontPreCachingImpl); | |
314 }; | |
315 | |
316 FontPreCachingImpl::Create(mojom::FontPreCachingRequest request) { | |
317 mojo::MakeStrongBinding(base::MakeUnique<FontPreCachingImpl>(), | |
318 std::move(request)); | |
304 } | 319 } |
305 | 320 |
306 void PdfToEmfUtilityProcessHostClient::Start( | 321 void PdfToEmfUtilityProcessHostClient::Start( |
307 const scoped_refptr<base::RefCountedMemory>& data, | 322 const scoped_refptr<base::RefCountedMemory>& data, |
308 bool print_text_with_gdi, | 323 bool print_text_with_gdi, |
309 const PdfToEmfConverter::StartCallback& start_callback) { | 324 const PdfToEmfConverter::StartCallback& start_callback) { |
310 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 325 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
311 BrowserThread::PostTask( | |
312 BrowserThread::IO, FROM_HERE, | |
313 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data, | |
314 print_text_with_gdi, start_callback)); | |
315 return; | |
316 } | |
317 | 326 |
318 // Store callback before any OnFailed() call to make it called on failure. | 327 // Store callback before any OnFailed() call to make it called on failure. |
319 start_callback_ = start_callback; | 328 start_callback_ = start_callback; |
320 | 329 |
321 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load | 330 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load |
322 // gdiplus.dll, change how rendering happens, and not be able to correctly | 331 // gdiplus.dll, change how rendering happens, and not be able to correctly |
323 // generate when sent to a metafile DC. | 332 // generate when sent to a metafile DC. |
324 utility_process_host_ = content::UtilityProcessHost::Create( | 333 utility_client_ = base::MakeUnique< |
325 this, base::ThreadTaskRunnerHandle::Get()) | 334 content::UtilityProcessMojoClient<mojom::PrintingFactory>>( |
326 ->AsWeakPtr(); | 335 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); |
327 utility_process_host_->SetName(l10n_util::GetStringUTF16( | 336 utility_client_->set_error_callback( |
328 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); | 337 base::Bind(&PdfToEmfUtilityProcessHostClient::OnFailed, this)); |
338 utility_client_->Start(); | |
339 mojom::FontPreCachingPtr font_precaching; | |
340 BrowserThread::PostTask( | |
341 BrowserThread::IO, FROM_HERE, | |
342 base::Bind(&FontPreCachingImpl::Create, | |
343 base::Passed(mojo::MakeRequest(&font_precaching)))); | |
344 utility_client_->service()->MakePrinting(mojo::MakeRequest(&printing_), | |
345 std::move(font_precaching)); | |
329 | 346 |
330 BrowserThread::PostTaskAndReplyWithResult( | 347 BrowserThread::PostTaskAndReplyWithResult( |
331 BrowserThread::FILE, FROM_HERE, | 348 BrowserThread::FILE, FROM_HERE, |
332 base::Bind(&CreateTempPdfFile, data, &temp_dir_), | 349 base::Bind(&CreateTempPdfFile, data, &temp_dir_), |
333 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, | 350 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, |
334 print_text_with_gdi)); | 351 print_text_with_gdi)); |
335 } | 352 } |
336 | 353 |
337 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, | 354 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, |
338 ScopedTempFile pdf) { | 355 ScopedTempFile pdf) { |
339 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 356 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
340 if (!utility_process_host_ || !pdf) | 357 if (!utility_client_ || !pdf) |
341 return OnFailed(); | 358 return OnFailed(); |
342 // Should reply with OnPageCount(). | 359 printing_->RenderPDFPagesToMetafiles( |
343 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( | 360 pdf->Duplicate(), settings_, print_text_with_gdi, |
344 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, | 361 base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageCount, this)); |
345 print_text_with_gdi)); | |
346 } | 362 } |
347 | 363 |
348 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { | 364 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { |
349 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 365 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
350 if (start_callback_.is_null()) | 366 if (start_callback_.is_null()) |
351 return OnFailed(); | 367 return OnFailed(); |
352 BrowserThread::PostTask(BrowserThread::UI, | 368 base::ResetAndReturn(&start_callback_).Run(page_count); |
353 FROM_HERE, | |
354 base::Bind(&PdfToEmfConverterImpl::RunCallback, | |
355 converter_, | |
356 base::Bind(start_callback_, page_count))); | |
357 start_callback_.Reset(); | |
358 } | 369 } |
359 | 370 |
360 void PdfToEmfUtilityProcessHostClient::GetPage( | 371 void PdfToEmfUtilityProcessHostClient::GetPage( |
361 int page_number, | 372 int page_number, |
362 const PdfToEmfConverter::GetPageCallback& get_page_callback) { | 373 const PdfToEmfConverter::GetPageCallback& get_page_callback) { |
363 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 374 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
364 BrowserThread::PostTask( | |
365 BrowserThread::IO, | |
366 FROM_HERE, | |
367 base::Bind(&PdfToEmfUtilityProcessHostClient::GetPage, | |
368 this, | |
369 page_number, | |
370 get_page_callback)); | |
371 return; | |
372 } | |
373 | 375 |
374 // Store callback before any OnFailed() call to make it called on failure. | 376 // Store callback before any OnFailed() call to make it called on failure. |
375 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); | 377 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); |
376 | 378 |
377 if (!utility_process_host_) | 379 if (!utility_client_) |
378 return OnFailed(); | 380 return OnFailed(); |
379 | 381 |
380 BrowserThread::PostTaskAndReplyWithResult( | 382 BrowserThread::PostTaskAndReplyWithResult( |
381 BrowserThread::FILE, | 383 BrowserThread::FILE, |
382 FROM_HERE, | 384 FROM_HERE, |
383 base::Bind(&CreateTempFile, &temp_dir_), | 385 base::Bind(&CreateTempFile, &temp_dir_), |
384 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady, | 386 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady, |
385 this, | 387 this, |
386 &get_page_callbacks_.back())); | 388 &get_page_callbacks_.back())); |
387 } | 389 } |
388 | 390 |
389 void PdfToEmfUtilityProcessHostClient::OnTempEmfReady( | 391 void PdfToEmfUtilityProcessHostClient::OnTempEmfReady( |
390 GetPageCallbackData* callback_data, | 392 GetPageCallbackData* callback_data, |
391 ScopedTempFile emf) { | 393 ScopedTempFile emf) { |
392 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 394 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
393 if (!utility_process_host_ || !emf) | 395 if (!utility_client_ || !emf) |
394 return OnFailed(); | 396 return OnFailed(); |
395 IPC::PlatformFileForTransit transit = | |
396 IPC::GetPlatformFileForTransit(emf->GetPlatformFile(), false); | |
397 callback_data->set_emf(std::move(emf)); | 397 callback_data->set_emf(std::move(emf)); |
398 // Should reply with OnPageDone(). | 398 printing_->RenderPDFPagesToMetafilesGetPage( |
399 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage( | 399 callback_data->page_number(), emf->Duplicate(), |
400 callback_data->page_number(), transit)); | 400 base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageDone, this)); |
401 } | 401 } |
402 | 402 |
403 void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, | 403 void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, |
404 float scale_factor) { | 404 float scale_factor) { |
405 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 405 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
406 if (get_page_callbacks_.empty()) | 406 if (get_page_callbacks_.empty()) |
407 return OnFailed(); | 407 return OnFailed(); |
408 GetPageCallbackData& data = get_page_callbacks_.front(); | 408 GetPageCallbackData& data = get_page_callbacks_.front(); |
409 std::unique_ptr<MetafilePlayer> emf; | 409 std::unique_ptr<MetafilePlayer> emf; |
410 | 410 |
411 if (success) { | 411 if (success) { |
412 ScopedTempFile temp_emf = data.TakeEmf(); | 412 ScopedTempFile temp_emf = data.TakeEmf(); |
413 if (!temp_emf) // Unexpected message from utility process. | 413 if (!temp_emf) // Unexpected message from utility process. |
414 return OnFailed(); | 414 return OnFailed(); |
415 emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf)); | 415 emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf)); |
416 } | 416 } |
417 | 417 |
418 BrowserThread::PostTask(BrowserThread::UI, | 418 data.callback().Run(data.page_number(), scale_factor, std::move(emf)); |
419 FROM_HERE, | |
420 base::Bind(&PdfToEmfConverterImpl::RunCallback, | |
421 converter_, | |
422 base::Bind(data.callback(), | |
423 data.page_number(), | |
424 scale_factor, | |
425 base::Passed(&emf)))); | |
426 get_page_callbacks_.pop(); | 419 get_page_callbacks_.pop(); |
427 } | 420 } |
428 | 421 |
429 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( | 422 void FontPreCachingImpl::PreCacheFontCharacters( |
430 const LOGFONT& font, | 423 const LOGFONT& font, |
431 const base::string16& str) { | 424 const base::string16& str, |
425 const PreCacheFontCharactersCallback& callback) { | |
426 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
427 | |
432 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache | 428 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
433 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. | 429 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. |
434 // Eventually this shouldn't be added and should be moved to | 430 // Eventually this shouldn't be added and should be moved to |
435 // FontCacheDispatcher too. http://crbug.com/356346. | 431 // FontCacheDispatcher too. http://crbug.com/356346. |
436 | 432 |
437 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. | 433 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. |
438 // Except that for True Type fonts, | 434 // Except that for True Type fonts, |
439 // GetTextMetrics will not load the font in memory. | 435 // GetTextMetrics will not load the font in memory. |
440 // The only way windows seem to load properly, it is to create a similar | 436 // The only way windows seem to load properly, it is to create a similar |
441 // device (like the one in which we print), then do an ExtTextOut, | 437 // device (like the one in which we print), then do an ExtTextOut, |
442 // as we do in the printing thread, which is sandboxed. | 438 // as we do in the printing thread, which is sandboxed. |
443 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); | 439 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); |
444 HFONT font_handle = CreateFontIndirect(&font); | 440 HFONT font_handle = CreateFontIndirect(&font); |
445 DCHECK(font_handle != nullptr); | 441 DCHECK(font_handle != nullptr); |
446 | 442 |
447 HGDIOBJ old_font = SelectObject(hdc, font_handle); | 443 HGDIOBJ old_font = SelectObject(hdc, font_handle); |
448 DCHECK(old_font != nullptr); | 444 DCHECK(old_font != nullptr); |
449 | 445 |
450 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); | 446 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); |
451 | 447 |
452 SelectObject(hdc, old_font); | 448 SelectObject(hdc, old_font); |
453 DeleteObject(font_handle); | 449 DeleteObject(font_handle); |
454 | 450 |
455 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); | 451 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); |
456 | 452 |
457 if (metafile) | 453 if (metafile) |
458 DeleteEnhMetaFile(metafile); | 454 DeleteEnhMetaFile(metafile); |
455 callback.Run(); | |
459 } | 456 } |
460 | 457 |
461 void PdfToEmfUtilityProcessHostClient::Stop() { | 458 void PdfToEmfUtilityProcessHostClient::Stop() { |
462 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 459 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
463 BrowserThread::PostTask( | 460 printing_.reset(); |
464 BrowserThread::IO, | |
465 FROM_HERE, | |
466 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); | |
467 return; | |
468 } | |
469 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); | |
470 } | |
471 | |
472 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) { | |
473 OnFailed(); | |
474 } | |
475 | |
476 void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) { | |
477 OnFailed(); | |
478 } | |
479 | |
480 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( | |
481 const IPC::Message& message) { | |
482 bool handled = true; | |
483 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) | |
484 IPC_MESSAGE_HANDLER( | |
485 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) | |
486 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, | |
487 OnPageDone) | |
488 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters, | |
489 OnPreCacheFontCharacters) | |
490 IPC_MESSAGE_UNHANDLED(handled = false) | |
491 IPC_END_MESSAGE_MAP() | |
492 return handled; | |
493 } | |
494 | |
495 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) { | |
496 if (utility_process_host_) | |
497 return utility_process_host_->Send(msg); | |
498 delete msg; | |
499 return false; | |
500 } | 461 } |
501 | 462 |
502 void PdfToEmfUtilityProcessHostClient::OnFailed() { | 463 void PdfToEmfUtilityProcessHostClient::OnFailed() { |
503 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 464 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
504 if (!start_callback_.is_null()) | 465 if (!start_callback_.is_null()) |
505 OnPageCount(0); | 466 OnPageCount(0); |
506 while (!get_page_callbacks_.empty()) | 467 while (!get_page_callbacks_.empty()) |
507 OnPageDone(false, 0.0f); | 468 OnPageDone(false, 0.0f); |
508 utility_process_host_.reset(); | 469 utility_client_.reset(); |
509 } | 470 } |
510 | 471 |
511 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) { | 472 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) { |
512 } | 473 } |
513 | 474 |
514 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { | 475 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { |
515 if (utility_client_.get()) | 476 if (utility_client_.get()) |
516 utility_client_->Stop(); | 477 utility_client_->Stop(); |
517 } | 478 } |
518 | 479 |
(...skipping 22 matching lines...) Expand all Loading... | |
541 | 502 |
542 PdfToEmfConverter::~PdfToEmfConverter() { | 503 PdfToEmfConverter::~PdfToEmfConverter() { |
543 } | 504 } |
544 | 505 |
545 // static | 506 // static |
546 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { | 507 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { |
547 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); | 508 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); |
548 } | 509 } |
549 | 510 |
550 } // namespace printing | 511 } // namespace printing |
OLD | NEW |