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

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

Issue 1553333002: Move cloud print specific files out of local_discovery (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@moveprn
Patch Set: Created 4 years, 11 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/bind_helpers.h"
11 #include "base/cancelable_callback.h"
12 #include "base/files/file.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/macros.h"
18 #include "base/single_thread_task_runner.h"
19 #include "chrome/common/chrome_utility_messages.h"
20 #include "chrome/common/chrome_utility_printing_messages.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "components/cloud_devices/common/cloud_device_description.h"
23 #include "components/cloud_devices/common/printer_description.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/child_process_data.h"
26 #include "content/public/browser/utility_process_host.h"
27 #include "content/public/browser/utility_process_host_client.h"
28 #include "printing/pdf_render_settings.h"
29 #include "printing/pwg_raster_settings.h"
30 #include "printing/units.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/geometry/size.h"
34
35 namespace local_discovery {
36
37 namespace {
38
39 using content::BrowserThread;
40
41 class FileHandlers {
42 public:
43 FileHandlers() {}
44
45 ~FileHandlers() {
46 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
47 }
48
49 void Init(base::RefCountedMemory* data);
50 bool IsValid();
51
52 base::FilePath GetPwgPath() const {
53 return temp_dir_.path().AppendASCII("output.pwg");
54 }
55
56 base::FilePath GetPdfPath() const {
57 return temp_dir_.path().AppendASCII("input.pdf");
58 }
59
60 IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) {
61 DCHECK(pdf_file_.IsValid());
62 IPC::PlatformFileForTransit transit =
63 IPC::TakeFileHandleForProcess(std::move(pdf_file_), process);
64 return transit;
65 }
66
67 IPC::PlatformFileForTransit GetPwgForProcess(base::ProcessHandle process) {
68 DCHECK(pwg_file_.IsValid());
69 IPC::PlatformFileForTransit transit =
70 IPC::TakeFileHandleForProcess(std::move(pwg_file_), process);
71 return transit;
72 }
73
74 private:
75 base::ScopedTempDir temp_dir_;
76 base::File pdf_file_;
77 base::File pwg_file_;
78 };
79
80 void FileHandlers::Init(base::RefCountedMemory* data) {
81 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
82
83 if (!temp_dir_.CreateUniqueTempDir()) {
84 return;
85 }
86
87 if (static_cast<int>(data->size()) !=
88 base::WriteFile(GetPdfPath(), data->front_as<char>(), data->size())) {
89 return;
90 }
91
92 // Reopen in read only mode.
93 pdf_file_.Initialize(GetPdfPath(),
94 base::File::FLAG_OPEN | base::File::FLAG_READ);
95 pwg_file_.Initialize(GetPwgPath(),
96 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
97 }
98
99 bool FileHandlers::IsValid() {
100 return pdf_file_.IsValid() && pwg_file_.IsValid();
101 }
102
103 // Converts PDF into PWG raster.
104 // Class uses 3 threads: UI, IO and FILE.
105 // Internal workflow is following:
106 // 1. Create instance on the UI thread. (files_, settings_,)
107 // 2. Create file on the FILE thread.
108 // 3. Start utility process and start conversion on the IO thread.
109 // 4. Run result callback on the UI thread.
110 // 5. Instance is destroyed from any thread that has the last reference.
111 // 6. FileHandlers destroyed on the FILE thread.
112 // This step posts |FileHandlers| to be destroyed on the FILE thread.
113 // All these steps work sequentially, so no data should be accessed
114 // simultaneously by several threads.
115 class PwgUtilityProcessHostClient : public content::UtilityProcessHostClient {
116 public:
117 explicit PwgUtilityProcessHostClient(
118 const printing::PdfRenderSettings& settings,
119 const printing::PwgRasterSettings& bitmap_settings);
120
121 void Convert(base::RefCountedMemory* data,
122 const PWGRasterConverter::ResultCallback& callback);
123
124 // UtilityProcessHostClient implementation.
125 void OnProcessCrashed(int exit_code) override;
126 bool OnMessageReceived(const IPC::Message& message) override;
127
128 private:
129 ~PwgUtilityProcessHostClient() override;
130
131 // Message handlers.
132 void OnProcessStarted();
133 void OnSucceeded();
134 void OnFailed();
135
136 void RunCallback(bool success);
137
138 void StartProcessOnIOThread();
139
140 void RunCallbackOnUIThread(bool success);
141 void OnFilesReadyOnUIThread();
142
143 scoped_ptr<FileHandlers, BrowserThread::DeleteOnFileThread> files_;
144 printing::PdfRenderSettings settings_;
145 printing::PwgRasterSettings bitmap_settings_;
146 PWGRasterConverter::ResultCallback callback_;
147 base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
148
149 DISALLOW_COPY_AND_ASSIGN(PwgUtilityProcessHostClient);
150 };
151
152 PwgUtilityProcessHostClient::PwgUtilityProcessHostClient(
153 const printing::PdfRenderSettings& settings,
154 const printing::PwgRasterSettings& bitmap_settings)
155 : settings_(settings), bitmap_settings_(bitmap_settings) {}
156
157 PwgUtilityProcessHostClient::~PwgUtilityProcessHostClient() {
158 }
159
160 void PwgUtilityProcessHostClient::Convert(
161 base::RefCountedMemory* data,
162 const PWGRasterConverter::ResultCallback& callback) {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI);
164 callback_ = callback;
165 CHECK(!files_);
166 files_.reset(new FileHandlers());
167 BrowserThread::PostTaskAndReply(
168 BrowserThread::FILE, FROM_HERE,
169 base::Bind(&FileHandlers::Init, base::Unretained(files_.get()),
170 make_scoped_refptr(data)),
171 base::Bind(&PwgUtilityProcessHostClient::OnFilesReadyOnUIThread, this));
172 }
173
174 void PwgUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
175 OnFailed();
176 }
177
178 bool PwgUtilityProcessHostClient::OnMessageReceived(
179 const IPC::Message& message) {
180 bool handled = true;
181 IPC_BEGIN_MESSAGE_MAP(PwgUtilityProcessHostClient, message)
182 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
183 IPC_MESSAGE_HANDLER(
184 ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded, OnSucceeded)
185 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed,
186 OnFailed)
187 IPC_MESSAGE_UNHANDLED(handled = false)
188 IPC_END_MESSAGE_MAP()
189 return handled;
190 }
191
192 void PwgUtilityProcessHostClient::OnProcessStarted() {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO);
194 if (!utility_process_host_) {
195 RunCallbackOnUIThread(false);
196 return;
197 }
198
199 base::ProcessHandle process = utility_process_host_->GetData().handle;
200 utility_process_host_->Send(new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
201 files_->GetPdfForProcess(process),
202 settings_,
203 bitmap_settings_,
204 files_->GetPwgForProcess(process)));
205 utility_process_host_.reset();
206 }
207
208 void PwgUtilityProcessHostClient::OnSucceeded() {
209 DCHECK_CURRENTLY_ON(BrowserThread::IO);
210 RunCallback(true);
211 }
212
213 void PwgUtilityProcessHostClient::OnFailed() {
214 DCHECK_CURRENTLY_ON(BrowserThread::IO);
215 RunCallback(false);
216 }
217
218 void PwgUtilityProcessHostClient::OnFilesReadyOnUIThread() {
219 DCHECK_CURRENTLY_ON(BrowserThread::UI);
220 if (!files_->IsValid()) {
221 RunCallbackOnUIThread(false);
222 return;
223 }
224 BrowserThread::PostTask(
225 BrowserThread::IO, FROM_HERE,
226 base::Bind(&PwgUtilityProcessHostClient::StartProcessOnIOThread, this));
227 }
228
229 void PwgUtilityProcessHostClient::StartProcessOnIOThread() {
230 DCHECK_CURRENTLY_ON(BrowserThread::IO);
231 utility_process_host_ =
232 content::UtilityProcessHost::Create(
233 this, base::MessageLoop::current()->task_runner())->AsWeakPtr();
234 utility_process_host_->SetName(l10n_util::GetStringUTF16(
235 IDS_UTILITY_PROCESS_PWG_RASTER_CONVERTOR_NAME));
236 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
237 }
238
239 void PwgUtilityProcessHostClient::RunCallback(bool success) {
240 BrowserThread::PostTask(
241 BrowserThread::UI, FROM_HERE,
242 base::Bind(&PwgUtilityProcessHostClient::RunCallbackOnUIThread, this,
243 success));
244 }
245
246 void PwgUtilityProcessHostClient::RunCallbackOnUIThread(bool success) {
247 DCHECK_CURRENTLY_ON(BrowserThread::UI);
248 if (!callback_.is_null()) {
249 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
250 base::Bind(callback_, success,
251 files_->GetPwgPath()));
252 callback_.Reset();
253 }
254 }
255
256 class PWGRasterConverterImpl : public PWGRasterConverter {
257 public:
258 PWGRasterConverterImpl();
259
260 ~PWGRasterConverterImpl() override;
261
262 void Start(base::RefCountedMemory* data,
263 const printing::PdfRenderSettings& conversion_settings,
264 const printing::PwgRasterSettings& bitmap_settings,
265 const ResultCallback& callback) override;
266
267 private:
268 scoped_refptr<PwgUtilityProcessHostClient> utility_client_;
269 base::CancelableCallback<ResultCallback::RunType> callback_;
270
271 DISALLOW_COPY_AND_ASSIGN(PWGRasterConverterImpl);
272 };
273
274 PWGRasterConverterImpl::PWGRasterConverterImpl() {
275 }
276
277 PWGRasterConverterImpl::~PWGRasterConverterImpl() {
278 }
279
280 void PWGRasterConverterImpl::Start(
281 base::RefCountedMemory* data,
282 const printing::PdfRenderSettings& conversion_settings,
283 const printing::PwgRasterSettings& bitmap_settings,
284 const ResultCallback& callback) {
285 // Rebind cancelable callback to avoid calling callback if
286 // PWGRasterConverterImpl is destroyed.
287 callback_.Reset(callback);
288 utility_client_ =
289 new PwgUtilityProcessHostClient(conversion_settings, bitmap_settings);
290 utility_client_->Convert(data, callback_.callback());
291 }
292
293 } // namespace
294
295 // static
296 scoped_ptr<PWGRasterConverter> PWGRasterConverter::CreateDefault() {
297 return scoped_ptr<PWGRasterConverter>(new PWGRasterConverterImpl());
298 }
299
300 // static
301 printing::PdfRenderSettings PWGRasterConverter::GetConversionSettings(
302 const cloud_devices::CloudDeviceDescription& printer_capabilities,
303 const gfx::Size& page_size) {
304 int dpi = printing::kDefaultPdfDpi;
305 cloud_devices::printer::DpiCapability dpis;
306 if (dpis.LoadFrom(printer_capabilities))
307 dpi = std::max(dpis.GetDefault().horizontal, dpis.GetDefault().vertical);
308
309 double scale = dpi;
310 scale /= printing::kPointsPerInch;
311
312 // Make vertical rectangle to optimize streaming to printer. Fix orientation
313 // by autorotate.
314 gfx::Rect area(std::min(page_size.width(), page_size.height()) * scale,
315 std::max(page_size.width(), page_size.height()) * scale);
316 return printing::PdfRenderSettings(area, dpi, true /* autorotate */);
317 }
318
319 // static
320 printing::PwgRasterSettings PWGRasterConverter::GetBitmapSettings(
321 const cloud_devices::CloudDeviceDescription& printer_capabilities,
322 const cloud_devices::CloudDeviceDescription& ticket) {
323 printing::PwgRasterSettings result;
324 cloud_devices::printer::PwgRasterConfigCapability raster_capability;
325 // If the raster capability fails to load, raster_capability will contain
326 // the default value.
327 raster_capability.LoadFrom(printer_capabilities);
328
329 cloud_devices::printer::DuplexTicketItem duplex_item;
330 cloud_devices::printer::DuplexType duplex_value =
331 cloud_devices::printer::NO_DUPLEX;
332
333 cloud_devices::printer::DocumentSheetBack document_sheet_back =
334 raster_capability.value().document_sheet_back;
335
336 if (duplex_item.LoadFrom(ticket)) {
337 duplex_value = duplex_item.value();
338 }
339
340 result.odd_page_transform = printing::TRANSFORM_NORMAL;
341 switch (duplex_value) {
342 case cloud_devices::printer::NO_DUPLEX:
343 result.odd_page_transform = printing::TRANSFORM_NORMAL;
344 break;
345 case cloud_devices::printer::LONG_EDGE:
346 if (document_sheet_back == cloud_devices::printer::ROTATED) {
347 result.odd_page_transform = printing::TRANSFORM_ROTATE_180;
348 } else if (document_sheet_back == cloud_devices::printer::FLIPPED) {
349 result.odd_page_transform = printing::TRANSFORM_FLIP_VERTICAL;
350 }
351 break;
352 case cloud_devices::printer::SHORT_EDGE:
353 if (document_sheet_back == cloud_devices::printer::MANUAL_TUMBLE) {
354 result.odd_page_transform = printing::TRANSFORM_ROTATE_180;
355 } else if (document_sheet_back == cloud_devices::printer::FLIPPED) {
356 result.odd_page_transform = printing::TRANSFORM_FLIP_HORIZONTAL;
357 }
358 }
359
360 result.rotate_all_pages = raster_capability.value().rotate_all_pages;
361
362 result.reverse_page_order = raster_capability.value().reverse_order_streaming;
363 return result;
364 }
365
366 } // namespace local_discovery
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698