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

Side by Side Diff: chrome/browser/local_discovery/pwg_raster_converter.cc

Issue 79363002: Convert PDF to PWG Raster using utility process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/common/chrome_utility_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/local_discovery/pwg_raster_converter.h" 5 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
6 6
7 #include "base/bind_helpers.h"
8 #include "base/cancelable_callback.h"
9 #include "base/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
7 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "chrome/common/chrome_utility_messages.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/child_process_data.h"
15 #include "content/public/browser/utility_process_host.h"
16 #include "content/public/browser/utility_process_host_client.h"
8 17
9 namespace local_discovery { 18 namespace local_discovery {
10 19
11 namespace { 20 namespace {
12 21
22 using content::BrowserThread;
23
24 class FileHandlers {
25 public:
26 FileHandlers() : pdf_file_(base::kInvalidPlatformFileValue),
27 pwg_file_(base::kInvalidPlatformFileValue) { }
28
29 ~FileHandlers() {
30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
31 if (pdf_file_ != base::kInvalidPlatformFileValue)
32 base::ClosePlatformFile(pdf_file_);
33 if (pwg_file_ != base::kInvalidPlatformFileValue)
34 base::ClosePlatformFile(pwg_file_);
35 }
36
37 void Init(base::RefCountedMemory* data);
38 bool IsValid();
39
40 base::FilePath GetPwgPath() const {
41 return temp_dir_.path().AppendASCII("output.pwg");
42 }
43
44 base::FilePath GetPdfPath() const {
45 return temp_dir_.path().AppendASCII("input.pdf");
46 }
47
48 IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) {
49 DCHECK_NE(pdf_file_, base::kInvalidPlatformFileValue);
50 IPC::PlatformFileForTransit transit =
51 IPC::GetFileHandleForProcess(pdf_file_, process, true);
52 pdf_file_ = base::kInvalidPlatformFileValue;
53 return transit;
54 }
55
56 IPC::PlatformFileForTransit GetPwgForProcess(base::ProcessHandle process) {
57 DCHECK_NE(pwg_file_, base::kInvalidPlatformFileValue);
58 IPC::PlatformFileForTransit transit =
59 IPC::GetFileHandleForProcess(pwg_file_, process, true);
60 pwg_file_ = base::kInvalidPlatformFileValue;
61 return transit;
62 }
63
64 private:
65 base::ScopedTempDir temp_dir_;
66 base::PlatformFile pdf_file_;
67 base::PlatformFile pwg_file_;
68 };
69
70 void FileHandlers::Init(base::RefCountedMemory* data) {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
72
73 if (!temp_dir_.CreateUniqueTempDir()) {
74 return;
75 }
76
77 if (static_cast<int>(data->size()) !=
78 file_util::WriteFile(GetPdfPath(),
79 reinterpret_cast<const char*>(data->front()),
80 data->size())) {
81 return;
82 }
83
84 // Reopen in read only mode.
85 pdf_file_ = base::CreatePlatformFile(GetPdfPath(), base::PLATFORM_FILE_OPEN |
86 base::PLATFORM_FILE_READ,
87 NULL, NULL);
88 pwg_file_ = base::CreatePlatformFile(GetPwgPath(),
89 base::PLATFORM_FILE_CREATE_ALWAYS |
90 base::PLATFORM_FILE_APPEND, NULL, NULL);
91 }
92
93 bool FileHandlers::IsValid() {
94 return pdf_file_ != base::kInvalidPlatformFileValue &&
95 pwg_file_ != base::kInvalidPlatformFileValue;
96 }
97
98 // Converts PDF into PWG raster.
99 // Class uses 3 threads: UI, IO and FILE.
100 // Internal workflow is following:
101 // 1. Create instance on the UI thread. (files_, settings_,)
102 // 2. Create file on the FILE thread.
103 // 3. Start utility process and start conversion on the IO thread.
104 // 4. Run result callback on the UI thread.
105 // 5. Instance is destroyed from any thread that has the last reference.
106 // 6. FileHandlers destroyed on the FILE thread.
107 // This step posts |FileHandlers| to be destroyed on the FILE thread.
108 // All these steps work sequentially, so no data should be accessed
109 // simultaneously by several threads.
110 class PwgUtilityProcessHostClient : public content::UtilityProcessHostClient {
111 public:
112 explicit PwgUtilityProcessHostClient(
113 const printing::PdfRenderSettings& settings);
114
115 void Convert(base::RefCountedMemory* data,
116 const PWGRasterConverter::ResultCallback& callback);
117
118 // UtilityProcessHostClient implementation.
119 virtual void OnProcessCrashed(int exit_code) OVERRIDE;
120 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
121
122 private:
123 virtual ~PwgUtilityProcessHostClient();
124
125 // Message handlers.
126 void OnProcessStarted();
127 void OnSucceeded();
128 void OnFailed();
129
130 void RunCallback(bool success);
131
132 void StartProcessOnIOThread();
133
134 void RunCallbackOnUIThread(bool success);
135 void OnFilesReadyOnUIThread();
136
137 scoped_ptr<FileHandlers> files_;
138 printing::PdfRenderSettings settings_;
139 PWGRasterConverter::ResultCallback callback_;
140 base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
141
142 DISALLOW_COPY_AND_ASSIGN(PwgUtilityProcessHostClient);
143 };
144
145 PwgUtilityProcessHostClient::PwgUtilityProcessHostClient(
146 const printing::PdfRenderSettings& settings) : settings_(settings) {
147 }
148
149 PwgUtilityProcessHostClient::~PwgUtilityProcessHostClient() {
150 // Delete temp directory.
151 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, files_.release());
152 }
153
154 void PwgUtilityProcessHostClient::Convert(
155 base::RefCountedMemory* data,
156 const PWGRasterConverter::ResultCallback& callback) {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158 callback_ = callback;
159 CHECK(!files_);
160 files_.reset(new FileHandlers());
161 BrowserThread::PostTaskAndReply(
162 BrowserThread::FILE, FROM_HERE,
163 base::Bind(&FileHandlers::Init, base::Unretained(files_.get()),
164 make_scoped_refptr(data)),
165 base::Bind(&PwgUtilityProcessHostClient::OnFilesReadyOnUIThread, this));
166 }
167
168 void PwgUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
169 OnFailed();
170 }
171
172 bool PwgUtilityProcessHostClient::OnMessageReceived(
173 const IPC::Message& message) {
174 bool handled = true;
175 IPC_BEGIN_MESSAGE_MAP(PwgUtilityProcessHostClient, message)
176 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
177 IPC_MESSAGE_HANDLER(
178 ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded, OnSucceeded)
179 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed,
180 OnFailed)
181 IPC_MESSAGE_UNHANDLED(handled = false)
182 IPC_END_MESSAGE_MAP()
183 return handled;
184 }
185
186 void PwgUtilityProcessHostClient::OnProcessStarted() {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
188 if (!utility_process_host_) {
189 RunCallbackOnUIThread(false);
190 return;
191 }
192
193 base::ProcessHandle process = utility_process_host_->GetData().handle;
194 utility_process_host_->Send(
195 new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
196 files_->GetPdfForProcess(process),
197 settings_,
198 files_->GetPwgForProcess(process)));
199 utility_process_host_.reset();
200 }
201
202 void PwgUtilityProcessHostClient::OnSucceeded() {
203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
204 RunCallback(true);
205 }
206
207 void PwgUtilityProcessHostClient::OnFailed() {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
209 RunCallback(false);
210 }
211
212 void PwgUtilityProcessHostClient::OnFilesReadyOnUIThread() {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
214 if (!files_->IsValid()) {
215 RunCallbackOnUIThread(false);
216 return;
217 }
218 BrowserThread::PostTask(
219 BrowserThread::IO, FROM_HERE,
220 base::Bind(&PwgUtilityProcessHostClient::StartProcessOnIOThread, this));
221 }
222
223 void PwgUtilityProcessHostClient::StartProcessOnIOThread() {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
225 utility_process_host_ =
226 content::UtilityProcessHost::Create(
227 this,
228 base::MessageLoop::current()->message_loop_proxy())->AsWeakPtr();
229 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
230 }
231
232 void PwgUtilityProcessHostClient::RunCallback(bool success) {
233 BrowserThread::PostTask(
234 BrowserThread::UI, FROM_HERE,
235 base::Bind(&PwgUtilityProcessHostClient::RunCallbackOnUIThread, this,
236 success));
237 }
238
239 void PwgUtilityProcessHostClient::RunCallbackOnUIThread(bool success) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241 if (!callback_.is_null()) {
242 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
243 base::Bind(callback_, success,
244 files_->GetPwgPath()));
245 callback_.Reset();
246 }
247 }
248
13 class PWGRasterConverterImpl : public PWGRasterConverter { 249 class PWGRasterConverterImpl : public PWGRasterConverter {
14 public: 250 public:
15 PWGRasterConverterImpl(); 251 PWGRasterConverterImpl();
16 252
17 virtual ~PWGRasterConverterImpl(); 253 virtual ~PWGRasterConverterImpl();
18 254
19 virtual void Start(base::RefCountedMemory* data, 255 virtual void Start(base::RefCountedMemory* data,
20 const printing::PdfRenderSettings& conversion_settings, 256 const printing::PdfRenderSettings& conversion_settings,
21 const ResultCallback& callback) OVERRIDE; 257 const ResultCallback& callback) OVERRIDE;
22 private: 258 private:
259 scoped_refptr<PwgUtilityProcessHostClient> utility_client_;
260 base::CancelableCallback<ResultCallback::RunType> callback_;
261
23 DISALLOW_COPY_AND_ASSIGN(PWGRasterConverterImpl); 262 DISALLOW_COPY_AND_ASSIGN(PWGRasterConverterImpl);
24 }; 263 };
25 264
26 PWGRasterConverterImpl::PWGRasterConverterImpl() { 265 PWGRasterConverterImpl::PWGRasterConverterImpl() {
27 } 266 }
28 267
29 PWGRasterConverterImpl::~PWGRasterConverterImpl() { 268 PWGRasterConverterImpl::~PWGRasterConverterImpl() {
30 } 269 }
31 270
32 void PWGRasterConverterImpl::Start( 271 void PWGRasterConverterImpl::Start(
33 base::RefCountedMemory* data, 272 base::RefCountedMemory* data,
34 const printing::PdfRenderSettings& conversion_settings, 273 const printing::PdfRenderSettings& conversion_settings,
35 const ResultCallback& callback) { 274 const ResultCallback& callback) {
36 NOTIMPLEMENTED(); 275 // Rebind cancelable callback to avoid calling callback if
276 // PWGRasterConverterImpl is destroyed.
277 callback_.Reset(callback);
278 utility_client_ = new PwgUtilityProcessHostClient(conversion_settings);
279 utility_client_->Convert(data, callback_.callback());
37 } 280 }
38 281
39 } // namespace 282 } // namespace
40 283
41 // static 284 // static
42 scoped_ptr<PWGRasterConverter> PWGRasterConverter::CreateDefault() { 285 scoped_ptr<PWGRasterConverter> PWGRasterConverter::CreateDefault() {
43 return scoped_ptr<PWGRasterConverter>(new PWGRasterConverterImpl()); 286 return scoped_ptr<PWGRasterConverter>(new PWGRasterConverterImpl());
44 } 287 }
45 288
46 } // namespace local_discovery 289 } // namespace local_discovery
OLDNEW
« no previous file with comments | « no previous file | chrome/common/chrome_utility_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698