Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: chrome/browser/printing/pdf_to_emf_converter.cc

Issue 547203002: Delete temporarily dir for PDF to EMF conversion after all EMF files closed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mon Sep 8 12:19:46 PDT 2014 Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/bind_helpers.h" 7 #include "base/bind_helpers.h"
8 #include "base/cancelable_callback.h" 8 #include "base/cancelable_callback.h"
9 #include "base/files/file.h" 9 #include "base/files/file.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h" 11 #include "base/files/scoped_temp_dir.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "chrome/common/chrome_utility_messages.h" 13 #include "chrome/common/chrome_utility_messages.h"
14 #include "chrome/common/chrome_utility_printing_messages.h" 14 #include "chrome/common/chrome_utility_printing_messages.h"
15 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/child_process_data.h" 16 #include "content/public/browser/child_process_data.h"
17 #include "content/public/browser/utility_process_host.h" 17 #include "content/public/browser/utility_process_host.h"
18 #include "content/public/browser/utility_process_host_client.h" 18 #include "content/public/browser/utility_process_host_client.h"
19 #include "printing/emf_win.h"
19 #include "printing/page_range.h" 20 #include "printing/page_range.h"
20 #include "printing/pdf_render_settings.h" 21 #include "printing/pdf_render_settings.h"
21 22
22 namespace printing { 23 namespace printing {
23 24
24 namespace { 25 namespace {
25 26
26 using content::BrowserThread; 27 using content::BrowserThread;
27 28
28 class FileHandlers { 29 class FileHandlers
30 : public base::RefCountedThreadSafe<FileHandlers,
31 BrowserThread::DeleteOnFileThread> {
29 public: 32 public:
30 FileHandlers() {} 33 FileHandlers() {}
31 34
32 ~FileHandlers() {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
34 }
35
36 void Init(base::RefCountedMemory* data); 35 void Init(base::RefCountedMemory* data);
37 bool IsValid(); 36 bool IsValid();
38 37
39 base::FilePath GetEmfPath() const { 38 base::FilePath GetEmfPath() const {
40 return temp_dir_.path().AppendASCII("output.emf"); 39 return temp_dir_.path().AppendASCII("output.emf");
41 } 40 }
42 41
42 base::FilePath GetEmfPagePath(int page_number) const {
43 return GetEmfPath().InsertBeforeExtensionASCII(
44 base::StringPrintf(".%d", page_number));
45 }
46
43 base::FilePath GetPdfPath() const { 47 base::FilePath GetPdfPath() const {
44 return temp_dir_.path().AppendASCII("input.pdf"); 48 return temp_dir_.path().AppendASCII("input.pdf");
45 } 49 }
46 50
47 IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) { 51 IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) {
48 DCHECK(pdf_file_.IsValid()); 52 DCHECK(pdf_file_.IsValid());
49 IPC::PlatformFileForTransit transit = 53 IPC::PlatformFileForTransit transit =
50 IPC::TakeFileHandleForProcess(pdf_file_.Pass(), process); 54 IPC::TakeFileHandleForProcess(pdf_file_.Pass(), process);
51 return transit; 55 return transit;
52 } 56 }
53 57
54 const base::FilePath& GetBasePath() const { 58 const base::FilePath& GetBasePath() const {
55 return temp_dir_.path(); 59 return temp_dir_.path();
56 } 60 }
57 61
58 private: 62 private:
63 friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>;
64 friend class base::DeleteHelper<FileHandlers>;
65
66 ~FileHandlers() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); }
67
59 base::ScopedTempDir temp_dir_; 68 base::ScopedTempDir temp_dir_;
60 base::File pdf_file_; 69 base::File pdf_file_;
61 }; 70 };
62 71
63 void FileHandlers::Init(base::RefCountedMemory* data) { 72 void FileHandlers::Init(base::RefCountedMemory* data) {
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
65 74
66 if (!temp_dir_.CreateUniqueTempDir()) { 75 if (!temp_dir_.CreateUniqueTempDir()) {
67 return; 76 return;
68 } 77 }
69 78
79 pdf_file_.Initialize(GetPdfPath(),
80 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
81 base::File::FLAG_READ |
82 base::File::FLAG_DELETE_ON_CLOSE);
70 if (static_cast<int>(data->size()) != 83 if (static_cast<int>(data->size()) !=
71 base::WriteFile(GetPdfPath(), data->front_as<char>(), data->size())) { 84 pdf_file_.WriteAtCurrentPos(data->front_as<char>(), data->size())) {
85 pdf_file_.Close();
72 return; 86 return;
73 } 87 }
74 88 pdf_file_.Seek(base::File::FROM_BEGIN, 0);
75 // Reopen in read only mode. 89 pdf_file_.Flush();
76 pdf_file_.Initialize(GetPdfPath(),
77 base::File::FLAG_OPEN | base::File::FLAG_READ);
78 } 90 }
79 91
80 bool FileHandlers::IsValid() { 92 bool FileHandlers::IsValid() {
81 return pdf_file_.IsValid(); 93 return pdf_file_.IsValid();
82 } 94 }
83 95
96 // Modification of Emf to keep references to |FileHandlers|.
97 // |FileHandlers| must be deleted after the last metafile is closed because
98 // Emf holds files locked.
99 // Ideally we want to use FLAG_DELETE_ON_CLOSE, but it requires large changes.
100 // It's going to be done for crbug.com/408184
101 class TempEmf : public Emf {
102 public:
103 explicit TempEmf(const scoped_refptr<FileHandlers>& files) : files_(files) {}
104 virtual ~TempEmf() {}
105
106 virtual bool SafePlayback(HDC hdc) const OVERRIDE {
107 bool result = Emf::SafePlayback(hdc);
108 TempEmf* this_mutable = const_cast<TempEmf*>(this);
109 // TODO(vitalybuka): Fix destruction of metafiles. For some reasons
110 // instances of Emf are not deleted. crbug.com/411683
111 // |files_| must be released as soon as possible to guarantee deletion.
112 // It's know that this Emf file is going to be played just once to
113 // a printer. So just release files here.
114 this_mutable->Close();
115 this_mutable->files_ = NULL;
116 return result;
117 }
118
119 private:
120 scoped_refptr<FileHandlers> files_;
121 DISALLOW_COPY_AND_ASSIGN(TempEmf);
122 };
123
84 // Converts PDF into EMF. 124 // Converts PDF into EMF.
85 // Class uses 3 threads: UI, IO and FILE. 125 // Class uses 3 threads: UI, IO and FILE.
86 // Internal workflow is following: 126 // Internal workflow is following:
87 // 1. Create instance on the UI thread. (files_, settings_,) 127 // 1. Create instance on the UI thread. (files_, settings_,)
88 // 2. Create file on the FILE thread. 128 // 2. Create file on the FILE thread.
89 // 3. Start utility process and start conversion on the IO thread. 129 // 3. Start utility process and start conversion on the IO thread.
90 // 4. Run result callback on the UI thread. 130 // 4. Run result callback on the UI thread.
91 // 5. Instance is destroyed from any thread that has the last reference. 131 // 5. Instance is destroyed from any thread that has the last reference.
92 // 6. FileHandlers destroyed on the FILE thread. 132 // 6. FileHandlers destroyed on the FILE thread.
93 // This step posts |FileHandlers| to be destroyed on the FILE thread. 133 // This step posts |FileHandlers| to be destroyed on the FILE thread.
(...skipping 24 matching lines...) Expand all
118 void RunCallback(const std::vector<printing::PageRange>& page_ranges, 158 void RunCallback(const std::vector<printing::PageRange>& page_ranges,
119 double scale_factor); 159 double scale_factor);
120 160
121 void StartProcessOnIOThread(); 161 void StartProcessOnIOThread();
122 162
123 void RunCallbackOnUIThread( 163 void RunCallbackOnUIThread(
124 const std::vector<printing::PageRange>& page_ranges, 164 const std::vector<printing::PageRange>& page_ranges,
125 double scale_factor); 165 double scale_factor);
126 void OnFilesReadyOnUIThread(); 166 void OnFilesReadyOnUIThread();
127 167
128 scoped_ptr<FileHandlers, BrowserThread::DeleteOnFileThread> files_; 168 scoped_refptr<FileHandlers> files_;
129 printing::PdfRenderSettings settings_; 169 printing::PdfRenderSettings settings_;
130 PdfToEmfConverter::ResultCallback callback_; 170 PdfToEmfConverter::ResultCallback callback_;
131 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; 171 base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
132 172
133 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); 173 DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient);
134 }; 174 };
135 175
136 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient( 176 PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient(
137 const printing::PdfRenderSettings& settings) 177 const printing::PdfRenderSettings& settings)
138 : settings_(settings) {} 178 : settings_(settings) {}
139 179
140 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { 180 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
141 } 181 }
142 182
143 void PdfToEmfUtilityProcessHostClient::Convert( 183 void PdfToEmfUtilityProcessHostClient::Convert(
144 base::RefCountedMemory* data, 184 base::RefCountedMemory* data,
145 const PdfToEmfConverter::ResultCallback& callback) { 185 const PdfToEmfConverter::ResultCallback& callback) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147 callback_ = callback; 187 callback_ = callback;
148 CHECK(!files_); 188 CHECK(!files_.get());
149 files_.reset(new FileHandlers()); 189 files_ = new FileHandlers();
150 BrowserThread::PostTaskAndReply( 190 BrowserThread::PostTaskAndReply(
151 BrowserThread::FILE, 191 BrowserThread::FILE,
152 FROM_HERE, 192 FROM_HERE,
153 base::Bind(&FileHandlers::Init, 193 base::Bind(&FileHandlers::Init, files_, make_scoped_refptr(data)),
154 base::Unretained(files_.get()),
155 make_scoped_refptr(data)),
156 base::Bind(&PdfToEmfUtilityProcessHostClient::OnFilesReadyOnUIThread, 194 base::Bind(&PdfToEmfUtilityProcessHostClient::OnFilesReadyOnUIThread,
157 this)); 195 this));
158 } 196 }
159 197
160 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) { 198 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
161 OnFailed(); 199 OnFailed();
162 } 200 }
163 201
164 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( 202 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived(
165 const IPC::Message& message) { 203 const IPC::Message& message) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 base::Bind(&PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread, 277 base::Bind(&PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread,
240 this, 278 this,
241 page_ranges, 279 page_ranges,
242 scale_factor)); 280 scale_factor));
243 } 281 }
244 282
245 void PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread( 283 void PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread(
246 const std::vector<printing::PageRange>& page_ranges, 284 const std::vector<printing::PageRange>& page_ranges,
247 double scale_factor) { 285 double scale_factor) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
249 std::vector<base::FilePath> page_filenames; 287 ScopedVector<Metafile> pages;
250 std::vector<printing::PageRange>::const_iterator iter; 288 std::vector<printing::PageRange>::const_iterator iter;
251 for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) { 289 for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) {
252 for (int page_number = iter->from; page_number <= iter->to; ++page_number) { 290 for (int page_number = iter->from; page_number <= iter->to; ++page_number) {
253 page_filenames.push_back(files_->GetEmfPath().InsertBeforeExtensionASCII( 291 scoped_ptr<TempEmf> metafile(new TempEmf(files_));
254 base::StringPrintf(".%d", page_number))); 292 if (!metafile->InitFromFile(files_->GetEmfPagePath(page_number))) {
293 NOTREACHED() << "Invalid metafile";
294 metafile.reset();
295 }
296 pages.push_back(metafile.release());
255 } 297 }
256 } 298 }
299 files_ = NULL;
257 if (!callback_.is_null()) { 300 if (!callback_.is_null()) {
258 BrowserThread::PostTask( 301 callback_.Run(scale_factor, &pages);
259 BrowserThread::UI,
260 FROM_HERE,
261 base::Bind(callback_, scale_factor, page_filenames));
262 callback_.Reset(); 302 callback_.Reset();
263 } 303 }
264 } 304 }
265 305
266 class PdfToEmfConverterImpl : public PdfToEmfConverter { 306 class PdfToEmfConverterImpl : public PdfToEmfConverter {
267 public: 307 public:
268 PdfToEmfConverterImpl(); 308 PdfToEmfConverterImpl();
269 309
270 virtual ~PdfToEmfConverterImpl(); 310 virtual ~PdfToEmfConverterImpl();
271 311
(...skipping 26 matching lines...) Expand all
298 } 338 }
299 339
300 } // namespace 340 } // namespace
301 341
302 // static 342 // static
303 scoped_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { 343 scoped_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() {
304 return scoped_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); 344 return scoped_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl());
305 } 345 }
306 346
307 } // namespace printing 347 } // namespace printing
OLDNEW
« no previous file with comments | « chrome/browser/printing/pdf_to_emf_converter.h ('k') | chrome/browser/printing/print_view_manager_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698