 Chromium Code Reviews
 Chromium Code Reviews Issue 2477283002:
  Convert printing IPCs to Mojo
    
  
    Issue 2477283002:
  Convert printing IPCs to Mojo 
  | 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/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>, | 
| 107 public mojom::FontPreCaching { | |
| 106 public: | 108 public: | 
| 107 PdfToEmfUtilityProcessHostClient( | 109 PdfToEmfUtilityProcessHostClient( | 
| 108 base::WeakPtr<PdfToEmfConverterImpl> converter, | 110 base::WeakPtr<PdfToEmfConverterImpl> converter, | 
| 109 const PdfRenderSettings& settings); | 111 const PdfRenderSettings& settings); | 
| 110 | 112 | 
| 111 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 113 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 
| 112 bool print_text_with_gdi, | 114 bool print_text_with_gdi, | 
| 113 const PdfToEmfConverter::StartCallback& start_callback); | 115 const PdfToEmfConverter::StartCallback& start_callback); | 
| 114 | 116 | 
| 115 void GetPage(int page_number, | 117 void GetPage(int page_number, | 
| 116 const PdfToEmfConverter::GetPageCallback& get_page_callback); | 118 const PdfToEmfConverter::GetPageCallback& get_page_callback); | 
| 117 | 119 | 
| 118 void Stop(); | 120 void Stop(); | 
| 119 | 121 | 
| 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: | 122 private: | 
| 130 class GetPageCallbackData { | 123 class GetPageCallbackData { | 
| 131 public: | 124 public: | 
| 132 GetPageCallbackData(int page_number, | 125 GetPageCallbackData(int page_number, | 
| 133 PdfToEmfConverter::GetPageCallback callback) | 126 PdfToEmfConverter::GetPageCallback callback) | 
| 134 : page_number_(page_number), callback_(callback) {} | 127 : page_number_(page_number), callback_(callback) {} | 
| 135 | 128 | 
| 136 GetPageCallbackData(GetPageCallbackData&& other) { | 129 GetPageCallbackData(GetPageCallbackData&& other) { | 
| 137 *this = std::move(other); | 130 *this = std::move(other); | 
| 138 } | 131 } | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 152 void set_emf(ScopedTempFile emf) { emf_ = std::move(emf); } | 145 void set_emf(ScopedTempFile emf) { emf_ = std::move(emf); } | 
| 153 | 146 | 
| 154 private: | 147 private: | 
| 155 int page_number_; | 148 int page_number_; | 
| 156 PdfToEmfConverter::GetPageCallback callback_; | 149 PdfToEmfConverter::GetPageCallback callback_; | 
| 157 ScopedTempFile emf_; | 150 ScopedTempFile emf_; | 
| 158 | 151 | 
| 159 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); | 152 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); | 
| 160 }; | 153 }; | 
| 161 | 154 | 
| 155 friend class base::RefCountedThreadSafe<PdfToEmfUtilityProcessHostClient>; | |
| 162 ~PdfToEmfUtilityProcessHostClient() override; | 156 ~PdfToEmfUtilityProcessHostClient() override; | 
| 163 | 157 | 
| 164 // Message handlers. | 158 // Message handlers. | 
| 165 void OnPageCount(int page_count); | 159 void OnPageCount(int page_count); | 
| 166 void OnPageDone(bool success, float scale_factor); | 160 void OnPageDone(bool success, float scale_factor); | 
| 167 void OnPreCacheFontCharacters(const LOGFONT& log_font, | 161 | 
| 168 const base::string16& characters); | 162 // mojom::FontPreCaching: | 
| 163 void PreCacheFontCharacters( | |
| 164 const LOGFONT& log_font, | |
| 165 const base::string16& characters, | |
| 166 const PreCacheFontCharactersCallback& callback) override; | |
| 169 | 167 | 
| 170 void OnFailed(); | 168 void OnFailed(); | 
| 171 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); | 169 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); | 
| 172 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); | 170 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); | 
| 173 | 171 | 
| 174 scoped_refptr<RefCountedTempDir> temp_dir_; | 172 scoped_refptr<RefCountedTempDir> temp_dir_; | 
| 175 | 173 | 
| 176 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. | 174 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. | 
| 177 base::WeakPtr<PdfToEmfConverterImpl> converter_; | 175 base::WeakPtr<PdfToEmfConverterImpl> converter_; | 
| 178 PdfRenderSettings settings_; | 176 PdfRenderSettings settings_; | 
| 179 | 177 | 
| 180 // Document loaded callback. | 178 // Document loaded callback. | 
| 181 PdfToEmfConverter::StartCallback start_callback_; | 179 PdfToEmfConverter::StartCallback start_callback_; | 
| 182 | 180 | 
| 183 // Process host for IPC. | 181 std::unique_ptr<content::UtilityProcessMojoClient<mojom::PrintingFactory>> | 
| 184 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; | 182 utility_client_; | 
| 185 | 183 | 
| 186 // Queue of callbacks for GetPage() requests. Utility process should reply | 184 // Queue of callbacks for GetPage() requests. Utility process should reply | 
| 187 // with PageDone in the same order as requests were received. | 185 // with PageDone in the same order as requests were received. | 
| 188 // Use containers that keeps element pointers valid after push() and pop(). | 186 // Use containers that keeps element pointers valid after push() and pop(). | 
| 189 typedef std::queue<GetPageCallbackData> GetPageCallbacks; | 187 typedef std::queue<GetPageCallbackData> GetPageCallbacks; | 
| 190 GetPageCallbacks get_page_callbacks_; | 188 GetPageCallbacks get_page_callbacks_; | 
| 191 | 189 | 
| 190 // Bound and used on the UI thread. | |
| 191 mojom::PrintingPtr printing_; | |
| 192 | |
| 193 // Interface that receives font precaching requests. | |
| 194 mojo::Binding<mojom::FontPreCaching> binding_; | |
| 195 | |
| 192 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); | 196 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); | 
| 193 }; | 197 }; | 
| 194 | 198 | 
| 195 class PdfToEmfConverterImpl : public PdfToEmfConverter { | 199 class PdfToEmfConverterImpl : public PdfToEmfConverter { | 
| 196 public: | 200 public: | 
| 197 PdfToEmfConverterImpl(); | 201 PdfToEmfConverterImpl(); | 
| 198 | 202 | 
| 199 ~PdfToEmfConverterImpl() override; | 203 ~PdfToEmfConverterImpl() override; | 
| 200 | 204 | 
| 201 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 205 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 return false; | 294 return false; | 
| 291 std::vector<char> data(size); | 295 std::vector<char> data(size); | 
| 292 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) | 296 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) | 
| 293 return false; | 297 return false; | 
| 294 return emf->InitFromData(data.data(), data.size()); | 298 return emf->InitFromData(data.data(), data.size()); | 
| 295 } | 299 } | 
| 296 | 300 | 
| 297 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( | 301 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( | 
| 298 base::WeakPtr<PdfToEmfConverterImpl> converter, | 302 base::WeakPtr<PdfToEmfConverterImpl> converter, | 
| 299 const PdfRenderSettings& settings) | 303 const PdfRenderSettings& settings) | 
| 300 : converter_(converter), settings_(settings) { | 304 : converter_(converter), settings_(settings), binding_(this) {} | 
| 301 } | |
| 302 | 305 | 
| 303 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | 306 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | 
| 304 } | 307 } | 
| 305 | 308 | 
| 306 void PdfToEmfUtilityProcessHostClient::Start( | 309 void PdfToEmfUtilityProcessHostClient::Start( | 
| 307 const scoped_refptr<base::RefCountedMemory>& data, | 310 const scoped_refptr<base::RefCountedMemory>& data, | 
| 308 bool print_text_with_gdi, | 311 bool print_text_with_gdi, | 
| 309 const PdfToEmfConverter::StartCallback& start_callback) { | 312 const PdfToEmfConverter::StartCallback& start_callback) { | 
| 310 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 313 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 | 314 | 
| 318 // Store callback before any OnFailed() call to make it called on failure. | 315 // Store callback before any OnFailed() call to make it called on failure. | 
| 319 start_callback_ = start_callback; | 316 start_callback_ = start_callback; | 
| 320 | 317 | 
| 321 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load | 318 // 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 | 319 // gdiplus.dll, change how rendering happens, and not be able to correctly | 
| 323 // generate when sent to a metafile DC. | 320 // generate when sent to a metafile DC. | 
| 324 utility_process_host_ = content::UtilityProcessHost::Create( | 321 utility_client_.reset( | 
| 
Sam McNally
2017/01/05 06:23:15
Prefer base::MakeUnique over std::unique_ptr::rese
 
tibell
2017/01/12 03:30:14
Done.
 | |
| 325 this, base::ThreadTaskRunnerHandle::Get()) | 322 new content::UtilityProcessMojoClient<mojom::PrintingFactory>( | 
| 326 ->AsWeakPtr(); | 323 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME))); | 
| 327 utility_process_host_->SetName(l10n_util::GetStringUTF16( | 324 utility_client_->set_error_callback( | 
| 328 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); | 325 base::Bind(&PdfToEmfUtilityProcessHostClient::OnFailed, this)); | 
| 326 utility_client_->Start(); | |
| 327 utility_client_->service()->MakePrinting( | |
| 328 mojo::MakeRequest(&printing_), binding_.CreateInterfacePtrAndBind()); | |
| 329 | 329 | 
| 330 BrowserThread::PostTaskAndReplyWithResult( | 330 BrowserThread::PostTaskAndReplyWithResult( | 
| 331 BrowserThread::FILE, FROM_HERE, | 331 BrowserThread::FILE, FROM_HERE, | 
| 332 base::Bind(&CreateTempPdfFile, data, &temp_dir_), | 332 base::Bind(&CreateTempPdfFile, data, &temp_dir_), | 
| 333 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, | 333 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, | 
| 334 print_text_with_gdi)); | 334 print_text_with_gdi)); | 
| 335 } | 335 } | 
| 336 | 336 | 
| 337 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, | 337 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, | 
| 338 ScopedTempFile pdf) { | 338 ScopedTempFile pdf) { | 
| 339 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 339 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 340 if (!utility_process_host_ || !pdf) | 340 if (!utility_client_ || !pdf) | 
| 341 return OnFailed(); | 341 return OnFailed(); | 
| 342 // Should reply with OnPageCount(). | 342 printing_->RenderPDFPagesToMetafiles( | 
| 343 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( | 343 pdf->Duplicate(), settings_, print_text_with_gdi, | 
| 344 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, | 344 base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageCount, this)); | 
| 345 print_text_with_gdi)); | |
| 346 } | 345 } | 
| 347 | 346 | 
| 348 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { | 347 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { | 
| 349 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 348 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 350 if (start_callback_.is_null()) | 349 if (start_callback_.is_null()) | 
| 351 return OnFailed(); | 350 return OnFailed(); | 
| 352 BrowserThread::PostTask(BrowserThread::UI, | 351 start_callback_.Run(page_count); | 
| 
Sam McNally
2017/01/05 06:23:15
base::ResetAndReturn(&start_callback_).Run(page_co
 
tibell
2017/01/12 03:30:14
Done.
 | |
| 353 FROM_HERE, | |
| 354 base::Bind(&PdfToEmfConverterImpl::RunCallback, | |
| 355 converter_, | |
| 356 base::Bind(start_callback_, page_count))); | |
| 357 start_callback_.Reset(); | 352 start_callback_.Reset(); | 
| 358 } | 353 } | 
| 359 | 354 | 
| 360 void PdfToEmfUtilityProcessHostClient::GetPage( | 355 void PdfToEmfUtilityProcessHostClient::GetPage( | 
| 361 int page_number, | 356 int page_number, | 
| 362 const PdfToEmfConverter::GetPageCallback& get_page_callback) { | 357 const PdfToEmfConverter::GetPageCallback& get_page_callback) { | 
| 363 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 358 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 | 359 | 
| 374 // Store callback before any OnFailed() call to make it called on failure. | 360 // Store callback before any OnFailed() call to make it called on failure. | 
| 375 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); | 361 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); | 
| 376 | 362 | 
| 377 if (!utility_process_host_) | 363 if (!utility_client_) | 
| 378 return OnFailed(); | 364 return OnFailed(); | 
| 379 | 365 | 
| 380 BrowserThread::PostTaskAndReplyWithResult( | 366 BrowserThread::PostTaskAndReplyWithResult( | 
| 381 BrowserThread::FILE, | 367 BrowserThread::FILE, | 
| 382 FROM_HERE, | 368 FROM_HERE, | 
| 383 base::Bind(&CreateTempFile, &temp_dir_), | 369 base::Bind(&CreateTempFile, &temp_dir_), | 
| 384 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady, | 370 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady, | 
| 385 this, | 371 this, | 
| 386 &get_page_callbacks_.back())); | 372 &get_page_callbacks_.back())); | 
| 387 } | 373 } | 
| 388 | 374 | 
| 389 void PdfToEmfUtilityProcessHostClient::OnTempEmfReady( | 375 void PdfToEmfUtilityProcessHostClient::OnTempEmfReady( | 
| 390 GetPageCallbackData* callback_data, | 376 GetPageCallbackData* callback_data, | 
| 391 ScopedTempFile emf) { | 377 ScopedTempFile emf) { | 
| 392 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 378 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 393 if (!utility_process_host_ || !emf) | 379 if (!utility_client_ || !emf) | 
| 394 return OnFailed(); | 380 return OnFailed(); | 
| 395 IPC::PlatformFileForTransit transit = | |
| 396 IPC::GetPlatformFileForTransit(emf->GetPlatformFile(), false); | |
| 397 callback_data->set_emf(std::move(emf)); | 381 callback_data->set_emf(std::move(emf)); | 
| 398 // Should reply with OnPageDone(). | 382 printing_->RenderPDFPagesToMetafilesGetPage( | 
| 399 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage( | 383 callback_data->page_number(), emf->Duplicate(), | 
| 400 callback_data->page_number(), transit)); | 384 base::Bind(&PdfToEmfUtilityProcessHostClient::OnPageDone, this)); | 
| 401 } | 385 } | 
| 402 | 386 | 
| 403 void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, | 387 void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, | 
| 404 float scale_factor) { | 388 float scale_factor) { | 
| 405 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 389 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 406 if (get_page_callbacks_.empty()) | 390 if (get_page_callbacks_.empty()) | 
| 407 return OnFailed(); | 391 return OnFailed(); | 
| 408 GetPageCallbackData& data = get_page_callbacks_.front(); | 392 GetPageCallbackData& data = get_page_callbacks_.front(); | 
| 409 std::unique_ptr<MetafilePlayer> emf; | 393 std::unique_ptr<MetafilePlayer> emf; | 
| 410 | 394 | 
| 411 if (success) { | 395 if (success) { | 
| 412 ScopedTempFile temp_emf = data.TakeEmf(); | 396 ScopedTempFile temp_emf = data.TakeEmf(); | 
| 413 if (!temp_emf) // Unexpected message from utility process. | 397 if (!temp_emf) // Unexpected message from utility process. | 
| 414 return OnFailed(); | 398 return OnFailed(); | 
| 415 emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf)); | 399 emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf)); | 
| 416 } | 400 } | 
| 417 | 401 | 
| 418 BrowserThread::PostTask(BrowserThread::UI, | 402 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(); | 403 get_page_callbacks_.pop(); | 
| 427 } | 404 } | 
| 428 | 405 | 
| 429 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( | 406 void PdfToEmfUtilityProcessHostClient::PreCacheFontCharacters( | 
| 
Sam McNally
2017/01/05 06:23:15
Is the UI thread the right place to be doing this?
 
tibell
2017/01/12 03:30:14
Done.
 | |
| 430 const LOGFONT& font, | 407 const LOGFONT& font, | 
| 431 const base::string16& str) { | 408 const base::string16& str, | 
| 409 const PreCacheFontCharactersCallback& callback) { | |
| 432 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache | 410 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache | 
| 433 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. | 411 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. | 
| 434 // Eventually this shouldn't be added and should be moved to | 412 // Eventually this shouldn't be added and should be moved to | 
| 435 // FontCacheDispatcher too. http://crbug.com/356346. | 413 // FontCacheDispatcher too. http://crbug.com/356346. | 
| 436 | 414 | 
| 437 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. | 415 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. | 
| 438 // Except that for True Type fonts, | 416 // Except that for True Type fonts, | 
| 439 // GetTextMetrics will not load the font in memory. | 417 // GetTextMetrics will not load the font in memory. | 
| 440 // The only way windows seem to load properly, it is to create a similar | 418 // 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, | 419 // device (like the one in which we print), then do an ExtTextOut, | 
| 442 // as we do in the printing thread, which is sandboxed. | 420 // as we do in the printing thread, which is sandboxed. | 
| 443 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); | 421 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); | 
| 444 HFONT font_handle = CreateFontIndirect(&font); | 422 HFONT font_handle = CreateFontIndirect(&font); | 
| 445 DCHECK(font_handle != nullptr); | 423 DCHECK(font_handle != nullptr); | 
| 446 | 424 | 
| 447 HGDIOBJ old_font = SelectObject(hdc, font_handle); | 425 HGDIOBJ old_font = SelectObject(hdc, font_handle); | 
| 448 DCHECK(old_font != nullptr); | 426 DCHECK(old_font != nullptr); | 
| 449 | 427 | 
| 450 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); | 428 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); | 
| 451 | 429 | 
| 452 SelectObject(hdc, old_font); | 430 SelectObject(hdc, old_font); | 
| 453 DeleteObject(font_handle); | 431 DeleteObject(font_handle); | 
| 454 | 432 | 
| 455 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); | 433 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); | 
| 456 | 434 | 
| 457 if (metafile) | 435 if (metafile) | 
| 458 DeleteEnhMetaFile(metafile); | 436 DeleteEnhMetaFile(metafile); | 
| 437 callback.Run(); | |
| 459 } | 438 } | 
| 460 | 439 | 
| 461 void PdfToEmfUtilityProcessHostClient::Stop() { | 440 void PdfToEmfUtilityProcessHostClient::Stop() { | 
| 462 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 441 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 463 BrowserThread::PostTask( | 442 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 } | 443 } | 
| 501 | 444 | 
| 502 void PdfToEmfUtilityProcessHostClient::OnFailed() { | 445 void PdfToEmfUtilityProcessHostClient::OnFailed() { | 
| 503 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 446 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 504 if (!start_callback_.is_null()) | 447 if (!start_callback_.is_null()) | 
| 505 OnPageCount(0); | 448 OnPageCount(0); | 
| 506 while (!get_page_callbacks_.empty()) | 449 while (!get_page_callbacks_.empty()) | 
| 507 OnPageDone(false, 0.0f); | 450 OnPageDone(false, 0.0f); | 
| 508 utility_process_host_.reset(); | 451 utility_client_.reset(); | 
| 509 } | 452 } | 
| 510 | 453 | 
| 511 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) { | 454 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) { | 
| 512 } | 455 } | 
| 513 | 456 | 
| 514 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { | 457 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { | 
| 515 if (utility_client_.get()) | 458 if (utility_client_.get()) | 
| 516 utility_client_->Stop(); | 459 utility_client_->Stop(); | 
| 517 } | 460 } | 
| 518 | 461 | 
| (...skipping 22 matching lines...) Expand all Loading... | |
| 541 | 484 | 
| 542 PdfToEmfConverter::~PdfToEmfConverter() { | 485 PdfToEmfConverter::~PdfToEmfConverter() { | 
| 543 } | 486 } | 
| 544 | 487 | 
| 545 // static | 488 // static | 
| 546 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { | 489 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { | 
| 547 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); | 490 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); | 
| 548 } | 491 } | 
| 549 | 492 | 
| 550 } // namespace printing | 493 } // namespace printing | 
| OLD | NEW |