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> |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "chrome/common/chrome_utility_printing_messages.h" | 23 #include "chrome/common/chrome_utility_printing_messages.h" |
24 #include "chrome/grit/generated_resources.h" | 24 #include "chrome/grit/generated_resources.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_host.h" |
28 #include "content/public/browser/utility_process_host_client.h" | 28 #include "content/public/browser/utility_process_host_client.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 "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
32 | 32 |
| 33 using content::BrowserThread; |
| 34 |
33 namespace printing { | 35 namespace printing { |
34 | 36 |
35 namespace { | 37 namespace { |
36 | 38 |
37 using content::BrowserThread; | 39 class PdfConverterImpl; |
38 | |
39 class PdfToEmfConverterImpl; | |
40 | 40 |
41 // Allows to delete temporary directory after all temporary files created inside | 41 // Allows to delete temporary directory after all temporary files created inside |
42 // are closed. Windows cannot delete directory with opened files. Directory is | 42 // are closed. Windows cannot delete directory with opened files. Directory is |
43 // used to store PDF and metafiles. PDF should be gone by the time utility | 43 // used to store PDF and metafiles. PDF should be gone by the time utility |
44 // process exits. Metafiles should be gone when all LazyEmf destroyed. | 44 // process exits. Metafiles should be gone when all LazyEmf destroyed. |
45 class RefCountedTempDir | 45 class RefCountedTempDir |
46 : public base::RefCountedThreadSafe<RefCountedTempDir, | 46 : public base::RefCountedThreadSafe<RefCountedTempDir, |
47 BrowserThread::DeleteOnFileThread> { | 47 BrowserThread::DeleteOnFileThread> { |
48 public: | 48 public: |
49 RefCountedTempDir() { ignore_result(temp_dir_.CreateUniqueTempDir()); } | 49 RefCountedTempDir() { ignore_result(temp_dir_.CreateUniqueTempDir()); } |
50 bool IsValid() const { return temp_dir_.IsValid(); } | 50 bool IsValid() const { return temp_dir_.IsValid(); } |
51 const base::FilePath& GetPath() const { return temp_dir_.GetPath(); } | 51 const base::FilePath& GetPath() const { return temp_dir_.GetPath(); } |
52 | 52 |
53 private: | 53 private: |
54 friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>; | 54 friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>; |
55 friend class base::DeleteHelper<RefCountedTempDir>; | 55 friend class base::DeleteHelper<RefCountedTempDir>; |
56 ~RefCountedTempDir() {} | 56 ~RefCountedTempDir() {} |
57 | 57 |
58 base::ScopedTempDir temp_dir_; | 58 base::ScopedTempDir temp_dir_; |
59 DISALLOW_COPY_AND_ASSIGN(RefCountedTempDir); | 59 DISALLOW_COPY_AND_ASSIGN(RefCountedTempDir); |
60 }; | 60 }; |
61 | 61 |
62 typedef std::unique_ptr<base::File, BrowserThread::DeleteOnFileThread> | 62 using ScopedTempFile = |
63 ScopedTempFile; | 63 std::unique_ptr<base::File, BrowserThread::DeleteOnFileThread>; |
64 | 64 |
65 // Wrapper for Emf to keep only file handle in memory, and load actual data only | 65 // Wrapper for Emf to keep only file handle in memory, and load actual data only |
66 // on playback. Emf::InitFromFile() can play metafile directly from disk, but it | 66 // on playback. Emf::InitFromFile() can play metafile directly from disk, but it |
67 // can't open file handles. We need file handles to reliably delete temporary | 67 // can't open file handles. We need file handles to reliably delete temporary |
68 // files, and to efficiently interact with utility process. | 68 // files, and to efficiently interact with utility process. |
69 class LazyEmf : public MetafilePlayer { | 69 class LazyEmf : public MetafilePlayer { |
70 public: | 70 public: |
71 LazyEmf(const scoped_refptr<RefCountedTempDir>& temp_dir, ScopedTempFile file) | 71 LazyEmf(const scoped_refptr<RefCountedTempDir>& temp_dir, ScopedTempFile file) |
72 : temp_dir_(temp_dir), file_(std::move(file)) { | 72 : temp_dir_(temp_dir), file_(std::move(file)) { |
73 CHECK(file_); | 73 CHECK(file_); |
74 } | 74 } |
75 ~LazyEmf() override { Close(); } | 75 ~LazyEmf() override { Close(); } |
76 | 76 |
| 77 protected: |
| 78 // MetafilePlayer: |
77 bool SafePlayback(HDC hdc) const override; | 79 bool SafePlayback(HDC hdc) const override; |
78 bool GetDataAsVector(std::vector<char>* buffer) const override; | |
79 bool SaveTo(base::File* file) const override; | |
80 | 80 |
81 private: | |
82 void Close() const; | 81 void Close() const; |
83 bool LoadEmf(Emf* emf) const; | 82 bool LoadEmf(Emf* emf) const; |
84 | 83 |
| 84 private: |
85 mutable scoped_refptr<RefCountedTempDir> temp_dir_; | 85 mutable scoped_refptr<RefCountedTempDir> temp_dir_; |
86 mutable ScopedTempFile file_; // Mutable because of consts in base class. | 86 mutable ScopedTempFile file_; // Mutable because of consts in base class. |
87 | 87 |
| 88 bool GetDataAsVector(std::vector<char>* buffer) const override; |
| 89 bool SaveTo(base::File* file) const override; |
| 90 |
88 DISALLOW_COPY_AND_ASSIGN(LazyEmf); | 91 DISALLOW_COPY_AND_ASSIGN(LazyEmf); |
89 }; | 92 }; |
90 | 93 |
91 // Converts PDF into EMF. | 94 // Class for converting PDF to another format for printing (Emf, Postscript). |
92 // Class uses 3 threads: UI, IO and FILE. | 95 // Class uses 3 threads: UI, IO and FILE. |
93 // Internal workflow is following: | 96 // Internal workflow is following: |
94 // 1. Create instance on the UI thread. (files_, settings_,) | 97 // 1. Create instance on the UI thread. (files_, settings_,) |
95 // 2. Create pdf file on the FILE thread. | 98 // 2. Create pdf file on the FILE thread. |
96 // 3. Start utility process and start conversion on the IO thread. | 99 // 3. Start utility process and start conversion on the IO thread. |
97 // 4. Utility process returns page count. | 100 // 4. Utility process returns page count. |
98 // 5. For each page: | 101 // 5. For each page: |
99 // 1. Clients requests page with file handle to a temp file. | 102 // 1. Clients requests page with file handle to a temp file. |
100 // 2. Utility converts the page, save it to the file and reply. | 103 // 2. Utility converts the page, save it to the file and reply. |
101 // | 104 // |
102 // All these steps work sequentially, so no data should be accessed | 105 // All these steps work sequentially, so no data should be accessed |
103 // simultaneously by several threads. | 106 // simultaneously by several threads. |
104 class PdfToEmfUtilityProcessHostClient | 107 class PdfConverterUtilityProcessHostClient |
105 : public content::UtilityProcessHostClient { | 108 : public content::UtilityProcessHostClient { |
106 public: | 109 public: |
107 PdfToEmfUtilityProcessHostClient( | 110 PdfConverterUtilityProcessHostClient( |
108 base::WeakPtr<PdfToEmfConverterImpl> converter, | 111 base::WeakPtr<PdfConverterImpl> converter, |
109 const PdfRenderSettings& settings); | 112 const PdfRenderSettings& settings); |
110 | 113 |
111 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 114 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
112 bool print_text_with_gdi, | 115 bool print_text_with_gdi, |
113 const PdfToEmfConverter::StartCallback& start_callback); | 116 const PdfConverter::StartCallback& start_callback); |
114 | 117 |
115 void GetPage(int page_number, | 118 void GetPage(int page_number, |
116 const PdfToEmfConverter::GetPageCallback& get_page_callback); | 119 const PdfConverter::GetPageCallback& get_page_callback); |
117 | 120 |
118 void Stop(); | 121 void Stop(); |
119 | 122 |
| 123 // UtilityProcessHostClient implementation. |
| 124 void OnProcessCrashed(int exit_code) override; |
| 125 void OnProcessLaunchFailed(int exit_code) override; |
| 126 |
120 // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters | 127 // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters |
121 // sync message replies. | 128 // sync message replies. |
122 bool Send(IPC::Message* msg); | 129 bool Send(IPC::Message* msg); |
123 | 130 |
124 // UtilityProcessHostClient implementation. | 131 protected: |
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: | |
130 class GetPageCallbackData { | 132 class GetPageCallbackData { |
131 public: | 133 public: |
132 GetPageCallbackData(int page_number, | 134 GetPageCallbackData(int page_number, PdfConverter::GetPageCallback callback) |
133 PdfToEmfConverter::GetPageCallback callback) | |
134 : page_number_(page_number), callback_(callback) {} | 135 : page_number_(page_number), callback_(callback) {} |
135 | 136 |
136 GetPageCallbackData(GetPageCallbackData&& other) { | 137 GetPageCallbackData(GetPageCallbackData&& other) { |
137 *this = std::move(other); | 138 *this = std::move(other); |
138 } | 139 } |
139 | 140 |
140 GetPageCallbackData& operator=(GetPageCallbackData&& rhs) { | 141 GetPageCallbackData& operator=(GetPageCallbackData&& rhs) { |
141 page_number_ = rhs.page_number_; | 142 page_number_ = rhs.page_number_; |
142 callback_ = rhs.callback_; | 143 callback_ = rhs.callback_; |
143 emf_ = std::move(rhs.emf_); | 144 file_ = std::move(rhs.file_); |
144 return *this; | 145 return *this; |
145 } | 146 } |
146 | 147 |
147 int page_number() const { return page_number_; } | 148 int page_number() const { return page_number_; } |
148 const PdfToEmfConverter::GetPageCallback& callback() const { | 149 const PdfConverter::GetPageCallback& callback() const { return callback_; } |
149 return callback_; | 150 ScopedTempFile TakeFile() { return std::move(file_); } |
150 } | 151 void set_file(ScopedTempFile file) { file_ = std::move(file); } |
151 ScopedTempFile TakeEmf() { return std::move(emf_); } | |
152 void set_emf(ScopedTempFile emf) { emf_ = std::move(emf); } | |
153 | 152 |
154 private: | 153 private: |
155 int page_number_; | 154 int page_number_; |
156 PdfToEmfConverter::GetPageCallback callback_; | 155 |
157 ScopedTempFile emf_; | 156 PdfConverter::GetPageCallback callback_; |
| 157 ScopedTempFile file_; |
158 | 158 |
159 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); | 159 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); |
160 }; | 160 }; |
161 | 161 |
162 ~PdfToEmfUtilityProcessHostClient() override; | 162 ~PdfConverterUtilityProcessHostClient() override; |
163 | 163 |
164 // Message handlers. | 164 // Helper functions: must be overridden by subclasses |
| 165 // Set the process name |
| 166 virtual base::string16 GetName() const = 0; |
| 167 // Create a metafileplayer subclass file from a temporary file. |
| 168 virtual std::unique_ptr<MetafilePlayer> GetFileFromTemp( |
| 169 std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| 170 temp_file) = 0; |
| 171 // Send the messages to Start, GetPage, and Stop. |
| 172 virtual void SendStartMessage(IPC::PlatformFileForTransit transit, |
| 173 bool print_text_with_gdi) = 0; |
| 174 virtual void SendGetPageMessage(int page_number, |
| 175 IPC::PlatformFileForTransit transit) = 0; |
| 176 virtual void SendStopMessage() = 0; |
| 177 |
| 178 // Message handlers: |
165 void OnPageCount(int page_count); | 179 void OnPageCount(int page_count); |
166 void OnPageDone(bool success, float scale_factor); | 180 void OnPageDone(bool success, float scale_factor); |
167 void OnPreCacheFontCharacters(const LOGFONT& log_font, | |
168 const base::string16& characters); | |
169 | 181 |
170 void OnFailed(); | 182 void OnFailed(); |
171 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); | 183 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); |
172 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); | 184 void OnTempFileReady(GetPageCallbackData* callback_data, |
| 185 ScopedTempFile temp_file); |
173 | 186 |
174 scoped_refptr<RefCountedTempDir> temp_dir_; | 187 scoped_refptr<RefCountedTempDir> temp_dir_; |
175 | 188 |
176 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. | 189 // Used to suppress callbacks after PdfConverter is deleted. |
177 base::WeakPtr<PdfToEmfConverterImpl> converter_; | 190 base::WeakPtr<PdfConverterImpl> converter_; |
178 PdfRenderSettings settings_; | 191 PdfRenderSettings settings_; |
179 | 192 |
180 // Document loaded callback. | 193 // Document loaded callback. |
181 PdfToEmfConverter::StartCallback start_callback_; | 194 PdfConverter::StartCallback start_callback_; |
182 | 195 |
183 // Process host for IPC. | 196 // Process host for IPC. |
184 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; | 197 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; |
185 | 198 |
186 // Queue of callbacks for GetPage() requests. Utility process should reply | 199 // Queue of callbacks for GetPage() requests. Utility process should reply |
187 // with PageDone in the same order as requests were received. | 200 // with PageDone in the same order as requests were received. |
188 // Use containers that keeps element pointers valid after push() and pop(). | 201 // Use containers that keeps element pointers valid after push() and pop(). |
189 typedef std::queue<GetPageCallbackData> GetPageCallbacks; | 202 using GetPageCallbacks = std::queue<GetPageCallbackData>; |
190 GetPageCallbacks get_page_callbacks_; | 203 GetPageCallbacks get_page_callbacks_; |
| 204 }; |
| 205 |
| 206 // Converts PDF into Emf. |
| 207 class PdfToEmfUtilityProcessHostClient |
| 208 : public PdfConverterUtilityProcessHostClient { |
| 209 public: |
| 210 PdfToEmfUtilityProcessHostClient(base::WeakPtr<PdfConverterImpl> converter, |
| 211 const PdfRenderSettings& settings) |
| 212 : PdfConverterUtilityProcessHostClient(converter, settings) {} |
| 213 |
| 214 bool OnMessageReceived(const IPC::Message& message) override; |
| 215 |
| 216 private: |
| 217 ~PdfToEmfUtilityProcessHostClient() override; |
| 218 // Helpers to send messages and set process name |
| 219 base::string16 GetName() const override; |
| 220 std::unique_ptr<MetafilePlayer> GetFileFromTemp( |
| 221 std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| 222 temp_file) override; |
| 223 void SendStartMessage(IPC::PlatformFileForTransit transit, |
| 224 bool print_text_with_gdi) override; |
| 225 void SendGetPageMessage(int page_number, |
| 226 IPC::PlatformFileForTransit transit) override; |
| 227 void SendStopMessage() override; |
| 228 |
| 229 // Additional message handler needed for Pdf to Emf |
| 230 void OnPreCacheFontCharacters(const LOGFONT& log_font, |
| 231 const base::string16& characters); |
191 | 232 |
192 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); | 233 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); |
193 }; | 234 }; |
194 | 235 |
195 class PdfToEmfConverterImpl : public PdfToEmfConverter { | 236 class PdfConverterImpl : public PdfConverter { |
196 public: | 237 public: |
197 PdfToEmfConverterImpl(); | 238 PdfConverterImpl(); |
198 | 239 |
199 ~PdfToEmfConverterImpl() override; | 240 ~PdfConverterImpl() override; |
200 | 241 |
201 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 242 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
202 const PdfRenderSettings& conversion_settings, | 243 const PdfRenderSettings& conversion_settings, |
203 bool print_text_with_gdi, | 244 bool print_text_with_gdi, |
204 const StartCallback& start_callback) override; | 245 const StartCallback& start_callback) override; |
205 | 246 |
206 void GetPage(int page_number, | 247 void GetPage(int page_number, |
207 const GetPageCallback& get_page_callback) override; | 248 const GetPageCallback& get_page_callback) override; |
208 | 249 |
209 // Helps to cancel callbacks if this object is destroyed. | 250 // Helps to cancel callbacks if this object is destroyed. |
210 void RunCallback(const base::Closure& callback); | 251 void RunCallback(const base::Closure& callback); |
211 | 252 |
| 253 protected: |
| 254 scoped_refptr<PdfConverterUtilityProcessHostClient> utility_client_; |
| 255 |
212 private: | 256 private: |
213 scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_; | 257 DISALLOW_COPY_AND_ASSIGN(PdfConverterImpl); |
| 258 }; |
| 259 |
| 260 class PdfToEmfConverterImpl : public PdfConverterImpl { |
| 261 public: |
| 262 PdfToEmfConverterImpl(); |
| 263 |
| 264 ~PdfToEmfConverterImpl() override; |
| 265 |
| 266 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
| 267 const PdfRenderSettings& conversion_settings, |
| 268 bool print_text_with_gdi, |
| 269 const StartCallback& start_callback) override; |
| 270 |
| 271 private: |
214 base::WeakPtrFactory<PdfToEmfConverterImpl> weak_ptr_factory_; | 272 base::WeakPtrFactory<PdfToEmfConverterImpl> weak_ptr_factory_; |
215 | 273 |
216 DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl); | 274 DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl); |
217 }; | 275 }; |
218 | 276 |
219 ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) { | 277 ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) { |
220 if (!temp_dir->get()) | 278 if (!temp_dir->get()) |
221 *temp_dir = new RefCountedTempDir(); | 279 *temp_dir = new RefCountedTempDir(); |
222 ScopedTempFile file; | 280 ScopedTempFile file; |
223 if (!(*temp_dir)->IsValid()) | 281 if (!(*temp_dir)->IsValid()) |
(...skipping 29 matching lines...) Expand all Loading... |
253 pdf_file.reset(); | 311 pdf_file.reset(); |
254 return pdf_file; | 312 return pdf_file; |
255 } | 313 } |
256 pdf_file->Seek(base::File::FROM_BEGIN, 0); | 314 pdf_file->Seek(base::File::FROM_BEGIN, 0); |
257 return pdf_file; | 315 return pdf_file; |
258 } | 316 } |
259 | 317 |
260 bool LazyEmf::SafePlayback(HDC hdc) const { | 318 bool LazyEmf::SafePlayback(HDC hdc) const { |
261 Emf emf; | 319 Emf emf; |
262 bool result = LoadEmf(&emf) && emf.SafePlayback(hdc); | 320 bool result = LoadEmf(&emf) && emf.SafePlayback(hdc); |
263 // TODO(vitalybuka): Fix destruction of metafiles. For some reasons | 321 // TODO(thestig): Fix destruction of metafiles. For some reasons |
264 // instances of Emf are not deleted. crbug.com/411683 | 322 // instances of Emf are not deleted. https://crbug.com/260806 |
265 // It's known that the Emf going to be played just once to a printer. So just | 323 // It's known that the Emf going to be played just once to a printer. So just |
266 // release file here. | 324 // release |file_| here. |
267 Close(); | 325 Close(); |
268 return result; | 326 return result; |
269 } | 327 } |
270 | 328 |
271 bool LazyEmf::GetDataAsVector(std::vector<char>* buffer) const { | 329 bool LazyEmf::GetDataAsVector(std::vector<char>* buffer) const { |
272 NOTREACHED(); | 330 NOTREACHED(); |
273 return false; | 331 return false; |
274 } | 332 } |
275 | 333 |
276 bool LazyEmf::SaveTo(base::File* file) const { | 334 bool LazyEmf::SaveTo(base::File* file) const { |
277 Emf emf; | 335 Emf emf; |
278 return LoadEmf(&emf) && emf.SaveTo(file); | 336 return LoadEmf(&emf) && emf.SaveTo(file); |
279 } | 337 } |
280 | 338 |
281 void LazyEmf::Close() const { | 339 void LazyEmf::Close() const { |
282 file_.reset(); | 340 file_.reset(); |
283 temp_dir_ = NULL; | 341 temp_dir_ = nullptr; |
284 } | 342 } |
285 | 343 |
286 bool LazyEmf::LoadEmf(Emf* emf) const { | 344 bool LazyEmf::LoadEmf(Emf* emf) const { |
287 file_->Seek(base::File::FROM_BEGIN, 0); | 345 file_->Seek(base::File::FROM_BEGIN, 0); |
288 int64_t size = file_->GetLength(); | 346 int64_t size = file_->GetLength(); |
289 if (size <= 0) | 347 if (size <= 0) |
290 return false; | 348 return false; |
291 std::vector<char> data(size); | 349 std::vector<char> data(size); |
292 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) | 350 if (file_->ReadAtCurrentPos(data.data(), data.size()) != size) |
293 return false; | 351 return false; |
294 return emf->InitFromData(data.data(), data.size()); | 352 return emf->InitFromData(data.data(), data.size()); |
295 } | 353 } |
296 | 354 |
297 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( | 355 PdfConverterUtilityProcessHostClient::PdfConverterUtilityProcessHostClient( |
298 base::WeakPtr<PdfToEmfConverterImpl> converter, | 356 base::WeakPtr<PdfConverterImpl> converter, |
299 const PdfRenderSettings& settings) | 357 const PdfRenderSettings& settings) |
300 : converter_(converter), settings_(settings) { | 358 : converter_(converter), settings_(settings) {} |
301 } | |
302 | 359 |
303 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | 360 PdfConverterUtilityProcessHostClient::~PdfConverterUtilityProcessHostClient() {} |
304 } | |
305 | 361 |
306 void PdfToEmfUtilityProcessHostClient::Start( | 362 void PdfConverterUtilityProcessHostClient::Start( |
307 const scoped_refptr<base::RefCountedMemory>& data, | 363 const scoped_refptr<base::RefCountedMemory>& data, |
308 bool print_text_with_gdi, | 364 bool print_text_with_gdi, |
309 const PdfToEmfConverter::StartCallback& start_callback) { | 365 const PdfConverter::StartCallback& start_callback) { |
310 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 366 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
311 BrowserThread::PostTask( | 367 BrowserThread::PostTask( |
312 BrowserThread::IO, FROM_HERE, | 368 BrowserThread::IO, FROM_HERE, |
313 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data, | 369 base::Bind(&PdfConverterUtilityProcessHostClient::Start, this, data, |
314 print_text_with_gdi, start_callback)); | 370 print_text_with_gdi, start_callback)); |
315 return; | 371 return; |
316 } | 372 } |
317 | 373 |
318 // Store callback before any OnFailed() call to make it called on failure. | 374 // Store callback before any OnFailed() call to make it called on failure. |
319 start_callback_ = start_callback; | 375 start_callback_ = start_callback; |
320 | 376 |
321 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load | 377 // 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 | 378 // gdiplus.dll, change how rendering happens, and not be able to correctly |
323 // generate when sent to a metafile DC. | 379 // generate when sent to a metafile DC. |
324 utility_process_host_ = content::UtilityProcessHost::Create( | 380 utility_process_host_ = content::UtilityProcessHost::Create( |
325 this, base::ThreadTaskRunnerHandle::Get()) | 381 this, base::ThreadTaskRunnerHandle::Get()) |
326 ->AsWeakPtr(); | 382 ->AsWeakPtr(); |
327 utility_process_host_->SetName(l10n_util::GetStringUTF16( | 383 utility_process_host_->SetName(GetName()); |
328 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); | |
329 | 384 |
330 BrowserThread::PostTaskAndReplyWithResult( | 385 BrowserThread::PostTaskAndReplyWithResult( |
331 BrowserThread::FILE, FROM_HERE, | 386 BrowserThread::FILE, FROM_HERE, |
332 base::Bind(&CreateTempPdfFile, data, &temp_dir_), | 387 base::Bind(&CreateTempPdfFile, data, &temp_dir_), |
333 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, | 388 base::Bind(&PdfConverterUtilityProcessHostClient::OnTempPdfReady, this, |
334 print_text_with_gdi)); | 389 print_text_with_gdi)); |
335 } | 390 } |
336 | 391 |
337 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, | 392 void PdfConverterUtilityProcessHostClient::OnTempPdfReady( |
338 ScopedTempFile pdf) { | 393 bool print_text_with_gdi, |
| 394 ScopedTempFile pdf) { |
339 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 395 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
340 if (!utility_process_host_ || !pdf) | 396 if (!utility_process_host_ || !pdf) |
341 return OnFailed(); | 397 return OnFailed(); |
342 // Should reply with OnPageCount(). | 398 // Should reply with OnPageCount(). |
343 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( | 399 SendStartMessage( |
344 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, | 400 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), |
345 print_text_with_gdi)); | 401 print_text_with_gdi); |
346 } | 402 } |
347 | 403 |
348 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { | 404 void PdfConverterUtilityProcessHostClient::OnPageCount(int page_count) { |
349 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 405 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
350 if (start_callback_.is_null()) | 406 if (start_callback_.is_null()) |
351 return OnFailed(); | 407 return OnFailed(); |
352 BrowserThread::PostTask(BrowserThread::UI, | 408 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
353 FROM_HERE, | 409 base::Bind(&PdfConverterImpl::RunCallback, converter_, |
354 base::Bind(&PdfToEmfConverterImpl::RunCallback, | |
355 converter_, | |
356 base::Bind(start_callback_, page_count))); | 410 base::Bind(start_callback_, page_count))); |
357 start_callback_.Reset(); | 411 start_callback_.Reset(); |
358 } | 412 } |
359 | 413 |
360 void PdfToEmfUtilityProcessHostClient::GetPage( | 414 void PdfConverterUtilityProcessHostClient::GetPage( |
361 int page_number, | 415 int page_number, |
362 const PdfToEmfConverter::GetPageCallback& get_page_callback) { | 416 const PdfConverter::GetPageCallback& get_page_callback) { |
363 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 417 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
364 BrowserThread::PostTask( | 418 BrowserThread::PostTask( |
365 BrowserThread::IO, | 419 BrowserThread::IO, FROM_HERE, |
366 FROM_HERE, | 420 base::Bind(&PdfConverterUtilityProcessHostClient::GetPage, this, |
367 base::Bind(&PdfToEmfUtilityProcessHostClient::GetPage, | 421 page_number, get_page_callback)); |
368 this, | |
369 page_number, | |
370 get_page_callback)); | |
371 return; | 422 return; |
372 } | 423 } |
373 | 424 |
374 // Store callback before any OnFailed() call to make it called on failure. | 425 // Store callback before any OnFailed() call to make it called on failure. |
375 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); | 426 get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); |
376 | 427 |
377 if (!utility_process_host_) | 428 if (!utility_process_host_) |
378 return OnFailed(); | 429 return OnFailed(); |
379 | 430 |
380 BrowserThread::PostTaskAndReplyWithResult( | 431 BrowserThread::PostTaskAndReplyWithResult( |
381 BrowserThread::FILE, | 432 BrowserThread::FILE, FROM_HERE, base::Bind(&CreateTempFile, &temp_dir_), |
382 FROM_HERE, | 433 base::Bind(&PdfConverterUtilityProcessHostClient::OnTempFileReady, this, |
383 base::Bind(&CreateTempFile, &temp_dir_), | |
384 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady, | |
385 this, | |
386 &get_page_callbacks_.back())); | 434 &get_page_callbacks_.back())); |
387 } | 435 } |
388 | 436 |
389 void PdfToEmfUtilityProcessHostClient::OnTempEmfReady( | 437 void PdfConverterUtilityProcessHostClient::OnTempFileReady( |
390 GetPageCallbackData* callback_data, | 438 GetPageCallbackData* callback_data, |
391 ScopedTempFile emf) { | 439 ScopedTempFile temp_file) { |
392 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 440 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
393 if (!utility_process_host_ || !emf) | 441 if (!utility_process_host_ || !temp_file) |
394 return OnFailed(); | 442 return OnFailed(); |
395 IPC::PlatformFileForTransit transit = | 443 IPC::PlatformFileForTransit transit = |
396 IPC::GetPlatformFileForTransit(emf->GetPlatformFile(), false); | 444 IPC::GetPlatformFileForTransit(temp_file->GetPlatformFile(), false); |
397 callback_data->set_emf(std::move(emf)); | 445 callback_data->set_file(std::move(temp_file)); |
398 // Should reply with OnPageDone(). | 446 // Should reply with OnPageDone(). |
399 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage( | 447 SendGetPageMessage(callback_data->page_number(), transit); |
400 callback_data->page_number(), transit)); | |
401 } | 448 } |
402 | 449 |
403 void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, | 450 void PdfConverterUtilityProcessHostClient::OnPageDone(bool success, |
404 float scale_factor) { | 451 float scale_factor) { |
405 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 452 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
406 if (get_page_callbacks_.empty()) | 453 if (get_page_callbacks_.empty()) |
407 return OnFailed(); | 454 return OnFailed(); |
408 GetPageCallbackData& data = get_page_callbacks_.front(); | 455 GetPageCallbackData& data = get_page_callbacks_.front(); |
409 std::unique_ptr<MetafilePlayer> emf; | 456 std::unique_ptr<MetafilePlayer> file; |
410 | 457 |
411 if (success) { | 458 if (success) { |
412 ScopedTempFile temp_emf = data.TakeEmf(); | 459 ScopedTempFile temp_file = data.TakeFile(); |
413 if (!temp_emf) // Unexpected message from utility process. | 460 if (!temp_file) // Unexpected message from utility process. |
414 return OnFailed(); | 461 return OnFailed(); |
415 emf = base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_emf)); | 462 file = GetFileFromTemp(std::move(temp_file)); |
416 } | 463 } |
417 | 464 |
418 BrowserThread::PostTask(BrowserThread::UI, | 465 BrowserThread::PostTask( |
419 FROM_HERE, | 466 BrowserThread::UI, FROM_HERE, |
420 base::Bind(&PdfToEmfConverterImpl::RunCallback, | 467 base::Bind(&PdfConverterImpl::RunCallback, converter_, |
421 converter_, | 468 base::Bind(data.callback(), data.page_number(), scale_factor, |
422 base::Bind(data.callback(), | 469 base::Passed(&file)))); |
423 data.page_number(), | |
424 scale_factor, | |
425 base::Passed(&emf)))); | |
426 get_page_callbacks_.pop(); | 470 get_page_callbacks_.pop(); |
427 } | 471 } |
428 | 472 |
| 473 void PdfConverterUtilityProcessHostClient::Stop() { |
| 474 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 475 BrowserThread::PostTask( |
| 476 BrowserThread::IO, FROM_HERE, |
| 477 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); |
| 478 return; |
| 479 } |
| 480 SendStopMessage(); |
| 481 } |
| 482 |
| 483 void PdfConverterUtilityProcessHostClient::OnProcessCrashed(int exit_code) { |
| 484 OnFailed(); |
| 485 } |
| 486 |
| 487 void PdfConverterUtilityProcessHostClient::OnProcessLaunchFailed( |
| 488 int exit_code) { |
| 489 OnFailed(); |
| 490 } |
| 491 |
| 492 bool PdfConverterUtilityProcessHostClient::Send(IPC::Message* msg) { |
| 493 if (utility_process_host_) |
| 494 return utility_process_host_->Send(msg); |
| 495 delete msg; |
| 496 return false; |
| 497 } |
| 498 |
| 499 void PdfConverterUtilityProcessHostClient::OnFailed() { |
| 500 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 501 if (!start_callback_.is_null()) |
| 502 OnPageCount(0); |
| 503 while (!get_page_callbacks_.empty()) |
| 504 OnPageDone(false, 0.0f); |
| 505 utility_process_host_.reset(); |
| 506 } |
| 507 |
| 508 // PDF to Emf |
| 509 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {} |
| 510 |
429 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( | 511 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( |
430 const LOGFONT& font, | 512 const LOGFONT& font, |
431 const base::string16& str) { | 513 const base::string16& str) { |
432 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache | 514 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
433 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. | 515 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. |
434 // Eventually this shouldn't be added and should be moved to | 516 // Eventually this shouldn't be added and should be moved to |
435 // FontCacheDispatcher too. http://crbug.com/356346. | 517 // FontCacheDispatcher too. http://crbug.com/356346. |
436 | 518 |
437 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. | 519 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. |
438 // Except that for True Type fonts, | 520 // Except that for True Type fonts, |
(...skipping 12 matching lines...) Expand all Loading... |
451 | 533 |
452 SelectObject(hdc, old_font); | 534 SelectObject(hdc, old_font); |
453 DeleteObject(font_handle); | 535 DeleteObject(font_handle); |
454 | 536 |
455 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); | 537 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); |
456 | 538 |
457 if (metafile) | 539 if (metafile) |
458 DeleteEnhMetaFile(metafile); | 540 DeleteEnhMetaFile(metafile); |
459 } | 541 } |
460 | 542 |
461 void PdfToEmfUtilityProcessHostClient::Stop() { | |
462 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
463 BrowserThread::PostTask( | |
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( | 543 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( |
481 const IPC::Message& message) { | 544 const IPC::Message& message) { |
482 bool handled = true; | 545 bool handled = true; |
483 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) | 546 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) |
484 IPC_MESSAGE_HANDLER( | 547 IPC_MESSAGE_HANDLER( |
485 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) | 548 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) |
486 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, | 549 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, |
487 OnPageDone) | 550 OnPageDone) |
488 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters, | 551 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters, |
489 OnPreCacheFontCharacters) | 552 OnPreCacheFontCharacters) |
490 IPC_MESSAGE_UNHANDLED(handled = false) | 553 IPC_MESSAGE_UNHANDLED(handled = false) |
491 IPC_END_MESSAGE_MAP() | 554 IPC_END_MESSAGE_MAP() |
492 return handled; | 555 return handled; |
493 } | 556 } |
494 | 557 |
495 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) { | 558 base::string16 PdfToEmfUtilityProcessHostClient::GetName() const { |
496 if (utility_process_host_) | 559 return l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME); |
497 return utility_process_host_->Send(msg); | |
498 delete msg; | |
499 return false; | |
500 } | 560 } |
501 | 561 |
502 void PdfToEmfUtilityProcessHostClient::OnFailed() { | 562 std::unique_ptr<MetafilePlayer> |
503 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 563 PdfToEmfUtilityProcessHostClient::GetFileFromTemp( |
504 if (!start_callback_.is_null()) | 564 std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
505 OnPageCount(0); | 565 temp_file) { |
506 while (!get_page_callbacks_.empty()) | 566 return base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_file)); |
507 OnPageDone(false, 0.0f); | |
508 utility_process_host_.reset(); | |
509 } | 567 } |
510 | 568 |
511 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) { | 569 void PdfToEmfUtilityProcessHostClient::SendGetPageMessage( |
| 570 int page_number, |
| 571 IPC::PlatformFileForTransit transit) { |
| 572 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(page_number, |
| 573 transit)); |
512 } | 574 } |
513 | 575 |
| 576 void PdfToEmfUtilityProcessHostClient::SendStartMessage( |
| 577 IPC::PlatformFileForTransit transit, |
| 578 bool print_text_with_gdi) { |
| 579 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(transit, settings_, |
| 580 print_text_with_gdi)); |
| 581 } |
| 582 |
| 583 void PdfToEmfUtilityProcessHostClient::SendStopMessage() { |
| 584 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); |
| 585 } |
| 586 |
| 587 // Pdf Converter Impl and subclasses |
| 588 PdfConverterImpl::PdfConverterImpl() {} |
| 589 |
| 590 PdfConverterImpl::~PdfConverterImpl() {} |
| 591 |
| 592 void PdfConverterImpl::Start(const scoped_refptr<base::RefCountedMemory>& data, |
| 593 const PdfRenderSettings& conversion_settings, |
| 594 bool print_text_with_gdi, |
| 595 const StartCallback& start_callback) { |
| 596 DCHECK(!utility_client_.get()); |
| 597 } |
| 598 |
| 599 void PdfConverterImpl::GetPage(int page_number, |
| 600 const GetPageCallback& get_page_callback) { |
| 601 utility_client_->GetPage(page_number, get_page_callback); |
| 602 } |
| 603 |
| 604 void PdfConverterImpl::RunCallback(const base::Closure& callback) { |
| 605 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 606 callback.Run(); |
| 607 } |
| 608 |
| 609 PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) {} |
| 610 |
514 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { | 611 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { |
515 if (utility_client_.get()) | 612 if (utility_client_.get()) |
516 utility_client_->Stop(); | 613 utility_client_->Stop(); |
517 } | 614 } |
518 | 615 |
519 void PdfToEmfConverterImpl::Start( | 616 void PdfToEmfConverterImpl::Start( |
520 const scoped_refptr<base::RefCountedMemory>& data, | 617 const scoped_refptr<base::RefCountedMemory>& data, |
521 const PdfRenderSettings& conversion_settings, | 618 const PdfRenderSettings& conversion_settings, |
522 bool print_text_with_gdi, | 619 bool print_text_with_gdi, |
523 const StartCallback& start_callback) { | 620 const StartCallback& start_callback) { |
524 DCHECK(!utility_client_.get()); | 621 DCHECK(!utility_client_.get()); |
525 utility_client_ = new PdfToEmfUtilityProcessHostClient( | 622 utility_client_ = new PdfToEmfUtilityProcessHostClient( |
526 weak_ptr_factory_.GetWeakPtr(), conversion_settings); | 623 weak_ptr_factory_.GetWeakPtr(), conversion_settings); |
527 utility_client_->Start(data, print_text_with_gdi, start_callback); | 624 utility_client_->Start(data, print_text_with_gdi, start_callback); |
528 } | 625 } |
529 | 626 |
530 void PdfToEmfConverterImpl::GetPage(int page_number, | |
531 const GetPageCallback& get_page_callback) { | |
532 utility_client_->GetPage(page_number, get_page_callback); | |
533 } | |
534 | |
535 void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) { | |
536 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
537 callback.Run(); | |
538 } | |
539 | |
540 } // namespace | 627 } // namespace |
541 | 628 |
542 PdfToEmfConverter::~PdfToEmfConverter() { | 629 PdfConverter::~PdfConverter() {} |
543 } | |
544 | 630 |
545 // static | 631 // static |
546 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { | 632 std::unique_ptr<PdfConverter> PdfConverter::CreatePdfToEmfConverter() { |
547 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); | 633 return base::MakeUnique<PdfToEmfConverterImpl>(); |
548 } | 634 } |
549 | 635 |
550 } // namespace printing | 636 } // namespace printing |
OLD | NEW |