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

Side by Side Diff: chrome/service/service_utility_process_host.cc

Issue 566693002: Use file handles to interact with utility process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tue Sep 16 16:01:51 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/service/service_utility_process_host.h" 5 #include "chrome/service/service_utility_process_host.h"
6 6
7 #include <queue>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/files/file.h"
12 #include "base/files/file_path.h"
9 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h" 14 #include "base/files/scoped_temp_dir.h"
11 #include "base/logging.h" 15 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h" 16 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
15 #include "base/process/kill.h" 18 #include "base/process/kill.h"
16 #include "base/strings/utf_string_conversions.h" 19 #include "base/process/launch.h"
20 #include "base/task_runner_util.h"
17 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/chrome_utility_printing_messages.h" 22 #include "chrome/common/chrome_utility_printing_messages.h"
19 #include "content/public/common/child_process_host.h" 23 #include "content/public/common/child_process_host.h"
20 #include "content/public/common/result_codes.h" 24 #include "content/public/common/result_codes.h"
21 #include "content/public/common/sandbox_init.h" 25 #include "content/public/common/sandbox_init.h"
26 #include "content/public/common/sandboxed_process_launcher_delegate.h"
22 #include "ipc/ipc_switches.h" 27 #include "ipc/ipc_switches.h"
23 #include "printing/page_range.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/gfx/rect.h"
26
27 #if defined(OS_WIN)
28 #include "base/files/file_path.h"
29 #include "base/memory/scoped_ptr.h"
30 #include "base/process/launch.h"
31 #include "base/win/scoped_handle.h"
32 #include "content/public/common/sandbox_init.h"
33 #include "content/public/common/sandboxed_process_launcher_delegate.h"
34 #include "printing/emf_win.h" 28 #include "printing/emf_win.h"
35 #include "sandbox/win/src/sandbox_policy_base.h" 29 #include "sandbox/win/src/sandbox_policy_base.h"
30 #include "ui/base/ui_base_switches.h"
36 31
37 namespace { 32 namespace {
38 33
39 // NOTE: changes to this class need to be reviewed by the security team.
40 class ServiceSandboxedProcessLauncherDelegate
41 : public content::SandboxedProcessLauncherDelegate {
42 public:
43 explicit ServiceSandboxedProcessLauncherDelegate(
44 const base::FilePath& exposed_dir)
45 : exposed_dir_(exposed_dir) {
46 }
47
48 virtual void PreSandbox(bool* disable_default_policy,
49 base::FilePath* exposed_dir) OVERRIDE {
50 *exposed_dir = exposed_dir_;
51 }
52
53 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
54 bool* success) OVERRIDE {
55 // Service process may run as windows service and it fails to create a
56 // window station.
57 policy->SetAlternateDesktop(false);
58 }
59
60 private:
61 base::FilePath exposed_dir_;
62 };
63
64 } // namespace
65
66 #endif // OS_WIN
67
68 using content::ChildProcessHost; 34 using content::ChildProcessHost;
69 35
70 namespace {
71
72 enum ServiceUtilityProcessHostEvent { 36 enum ServiceUtilityProcessHostEvent {
73 SERVICE_UTILITY_STARTED, 37 SERVICE_UTILITY_STARTED,
74 SERVICE_UTILITY_DISCONNECTED, 38 SERVICE_UTILITY_DISCONNECTED,
75 SERVICE_UTILITY_METAFILE_REQUEST, 39 SERVICE_UTILITY_METAFILE_REQUEST,
76 SERVICE_UTILITY_METAFILE_SUCCEEDED, 40 SERVICE_UTILITY_METAFILE_SUCCEEDED,
77 SERVICE_UTILITY_METAFILE_FAILED, 41 SERVICE_UTILITY_METAFILE_FAILED,
78 SERVICE_UTILITY_CAPS_REQUEST, 42 SERVICE_UTILITY_CAPS_REQUEST,
79 SERVICE_UTILITY_CAPS_SUCCEEDED, 43 SERVICE_UTILITY_CAPS_SUCCEEDED,
80 SERVICE_UTILITY_CAPS_FAILED, 44 SERVICE_UTILITY_CAPS_FAILED,
81 SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST, 45 SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST,
82 SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED, 46 SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED,
83 SERVICE_UTILITY_SEMANTIC_CAPS_FAILED, 47 SERVICE_UTILITY_SEMANTIC_CAPS_FAILED,
84 SERVICE_UTILITY_FAILED_TO_START, 48 SERVICE_UTILITY_FAILED_TO_START,
85 SERVICE_UTILITY_EVENT_MAX, 49 SERVICE_UTILITY_EVENT_MAX,
86 }; 50 };
87 51
88 void ReportUmaEvent(ServiceUtilityProcessHostEvent id) { 52 void ReportUmaEvent(ServiceUtilityProcessHostEvent id) {
89 UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent", 53 UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
90 id, 54 id,
91 SERVICE_UTILITY_EVENT_MAX); 55 SERVICE_UTILITY_EVENT_MAX);
92 } 56 }
93 57
58 // NOTE: changes to this class need to be reviewed by the security team.
59 class ServiceSandboxedProcessLauncherDelegate
60 : public content::SandboxedProcessLauncherDelegate {
61 public:
62 ServiceSandboxedProcessLauncherDelegate() {}
63
64 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
65 bool* success) OVERRIDE {
66 // Service process may run as windows service and it fails to create a
67 // window station.
68 policy->SetAlternateDesktop(false);
69 }
70
71 private:
72 DISALLOW_COPY_AND_ASSIGN(ServiceSandboxedProcessLauncherDelegate);
73 };
74
94 } // namespace 75 } // namespace
95 76
77 class ServiceUtilityProcessHost::PdfToEmfState {
78 public:
79 explicit PdfToEmfState(ServiceUtilityProcessHost* host)
80 : host_(host), page_count_(0), current_page_(0), pages_in_progress_(0) {}
81 ~PdfToEmfState() { Stop(); }
82
83 bool Start(base::File pdf_file,
84 const printing::PdfRenderSettings& conversion_settings) {
85 if (!temp_dir_.CreateUniqueTempDir())
86 return false;
87 return host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
88 IPC::TakeFileHandleForProcess(pdf_file.Pass(), host_->handle()),
89 conversion_settings));
90 }
91
92 void GetMorePages() {
93 const int kMaxNumberOfTempFilesPerDocument = 3;
94 while (pages_in_progress_ < kMaxNumberOfTempFilesPerDocument &&
95 current_page_ < page_count_) {
96 ++pages_in_progress_;
97 emf_files_.push(CreateTempFile());
98 host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(
99 current_page_++,
100 IPC::GetFileHandleForProcess(
101 emf_files_.back().GetPlatformFile(), host_->handle(), false)));
102 }
103 }
104
105 // Returns true if all pages processed and client should not expect more
106 // results.
107 bool OnPageProcessed() {
108 --pages_in_progress_;
109 GetMorePages();
110 if (pages_in_progress_ || current_page_ < page_count_)
111 return false;
112 Stop();
113 return true;
114 }
115
116 base::File TakeNextFile() {
117 DCHECK(!emf_files_.empty());
118 base::File file;
119 if (!emf_files_.empty())
120 file = emf_files_.front().Pass();
121 emf_files_.pop();
122 return file.Pass();
123 }
124
125 void set_page_count(int page_count) { page_count_ = page_count; }
126 bool has_page_count() { return page_count_ > 0; }
127
128 private:
129 void Stop() {
130 host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
131 }
132
133 base::File CreateTempFile() {
134 base::FilePath path;
135 if (!base::CreateTemporaryFileInDir(temp_dir_.path(), &path))
136 return base::File();
137 return base::File(path,
138 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
Tom Sepez 2014/09/17 16:59:24 nit: maybe one flag per line, also check indentati
Vitaly Buka (NO REVIEWS) 2014/09/17 17:40:38 Done.
139 base::File::FLAG_READ |
140 base::File::FLAG_DELETE_ON_CLOSE |
141 base::File::FLAG_TEMPORARY);
142 }
143
144 base::ScopedTempDir temp_dir_;
145 ServiceUtilityProcessHost* host_;
146 std::queue<base::File> emf_files_;
147 int page_count_;
148 int current_page_;
149 int pages_in_progress_;
150 };
151
96 ServiceUtilityProcessHost::ServiceUtilityProcessHost( 152 ServiceUtilityProcessHost::ServiceUtilityProcessHost(
97 Client* client, base::MessageLoopProxy* client_message_loop_proxy) 153 Client* client,
98 : handle_(base::kNullProcessHandle), 154 base::MessageLoopProxy* client_message_loop_proxy)
99 client_(client), 155 : handle_(base::kNullProcessHandle),
100 client_message_loop_proxy_(client_message_loop_proxy), 156 client_(client),
101 waiting_for_reply_(false) { 157 client_message_loop_proxy_(client_message_loop_proxy),
158 waiting_for_reply_(false),
159 weak_ptr_factory_(this) {
102 child_process_host_.reset(ChildProcessHost::Create(this)); 160 child_process_host_.reset(ChildProcessHost::Create(this));
103 } 161 }
104 162
105 ServiceUtilityProcessHost::~ServiceUtilityProcessHost() { 163 ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
106 // We need to kill the child process when the host dies. 164 // We need to kill the child process when the host dies.
107 base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false); 165 base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false);
108 } 166 }
109 167
110 bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile( 168 bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
111 const base::FilePath& pdf_path, 169 const base::FilePath& pdf_path,
112 const printing::PdfRenderSettings& render_settings, 170 const printing::PdfRenderSettings& render_settings) {
113 const std::vector<printing::PageRange>& page_ranges) {
114 ReportUmaEvent(SERVICE_UTILITY_METAFILE_REQUEST); 171 ReportUmaEvent(SERVICE_UTILITY_METAFILE_REQUEST);
115 start_time_ = base::Time::Now(); 172 start_time_ = base::Time::Now();
116 #if !defined(OS_WIN) 173 base::File pdf_file(pdf_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
117 // This is only implemented on Windows (because currently it is only needed 174 if (!pdf_file.IsValid() || !StartProcess(false))
Tom Sepez 2014/09/17 16:59:24 Do we leave temporary files lying aroung if startP
Vitaly Buka (NO REVIEWS) 2014/09/17 17:40:38 No. Files are open with base::File::FLAG_DELETE_ON
118 // on Windows). Will add implementations on other platforms when needed.
119 NOTIMPLEMENTED();
120 return false;
121 #else // !defined(OS_WIN)
122 scratch_metafile_dir_.reset(new base::ScopedTempDir);
123 if (!scratch_metafile_dir_->CreateUniqueTempDir())
124 return false;
125 metafile_path_ = scratch_metafile_dir_->path().AppendASCII("output.emf");
126 if (!StartProcess(false, scratch_metafile_dir_->path()))
127 return false; 175 return false;
128 176
129 base::File pdf_file(
130 pdf_path,
131 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
132 DCHECK(!waiting_for_reply_); 177 DCHECK(!waiting_for_reply_);
133 waiting_for_reply_ = true; 178 waiting_for_reply_ = true;
134 return child_process_host_->Send( 179
135 new ChromeUtilityMsg_RenderPDFPagesToMetafiles( 180 pdf_to_emf_state_.reset(new PdfToEmfState(this));
136 IPC::TakeFileHandleForProcess(pdf_file.Pass(), handle()), 181 return pdf_to_emf_state_->Start(pdf_file.Pass(), render_settings);
137 metafile_path_,
138 render_settings,
139 page_ranges));
140 #endif // !defined(OS_WIN)
141 } 182 }
142 183
143 bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults( 184 bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
144 const std::string& printer_name) { 185 const std::string& printer_name) {
145 ReportUmaEvent(SERVICE_UTILITY_CAPS_REQUEST); 186 ReportUmaEvent(SERVICE_UTILITY_CAPS_REQUEST);
146 start_time_ = base::Time::Now(); 187 start_time_ = base::Time::Now();
147 base::FilePath exposed_path; 188 if (!StartProcess(true))
148 if (!StartProcess(true, exposed_path))
149 return false; 189 return false;
150 DCHECK(!waiting_for_reply_); 190 DCHECK(!waiting_for_reply_);
151 waiting_for_reply_ = true; 191 waiting_for_reply_ = true;
152 return child_process_host_->Send( 192 return Send(new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
153 new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
154 } 193 }
155 194
156 bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults( 195 bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults(
157 const std::string& printer_name) { 196 const std::string& printer_name) {
158 ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST); 197 ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST);
159 start_time_ = base::Time::Now(); 198 start_time_ = base::Time::Now();
160 base::FilePath exposed_path; 199 if (!StartProcess(true))
161 if (!StartProcess(true, exposed_path))
162 return false; 200 return false;
163 DCHECK(!waiting_for_reply_); 201 DCHECK(!waiting_for_reply_);
164 waiting_for_reply_ = true; 202 waiting_for_reply_ = true;
165 return child_process_host_->Send( 203 return Send(
166 new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name)); 204 new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name));
167 } 205 }
168 206
169 bool ServiceUtilityProcessHost::StartProcess( 207 bool ServiceUtilityProcessHost::Send(IPC::Message* msg) {
170 bool no_sandbox, 208 if (child_process_host_)
171 const base::FilePath& exposed_dir) { 209 return child_process_host_->Send(msg);
210 delete msg;
211 return false;
212 }
213
214 bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox) {
172 std::string channel_id = child_process_host_->CreateChannel(); 215 std::string channel_id = child_process_host_->CreateChannel();
173 if (channel_id.empty()) 216 if (channel_id.empty())
174 return false; 217 return false;
175 218
176 base::FilePath exe_path = GetUtilityProcessCmd(); 219 base::FilePath exe_path = GetUtilityProcessCmd();
177 if (exe_path.empty()) { 220 if (exe_path.empty()) {
178 NOTREACHED() << "Unable to get utility process binary name."; 221 NOTREACHED() << "Unable to get utility process binary name.";
179 return false; 222 return false;
180 } 223 }
181 224
182 CommandLine cmd_line(exe_path); 225 base::CommandLine cmd_line(exe_path);
183 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess); 226 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess);
184 cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id); 227 cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id);
185 cmd_line.AppendSwitch(switches::kLang); 228 cmd_line.AppendSwitch(switches::kLang);
186 229
187 if (Launch(&cmd_line, no_sandbox, exposed_dir)) { 230 if (Launch(&cmd_line, no_sandbox)) {
188 ReportUmaEvent(SERVICE_UTILITY_STARTED); 231 ReportUmaEvent(SERVICE_UTILITY_STARTED);
189 return true; 232 return true;
190 } 233 }
191 ReportUmaEvent(SERVICE_UTILITY_FAILED_TO_START); 234 ReportUmaEvent(SERVICE_UTILITY_FAILED_TO_START);
192 return false; 235 return false;
193 } 236 }
194 237
195 bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line, 238 bool ServiceUtilityProcessHost::Launch(base::CommandLine* cmd_line,
196 bool no_sandbox, 239 bool no_sandbox) {
197 const base::FilePath& exposed_dir) {
198 #if !defined(OS_WIN)
199 // TODO(sanjeevr): Implement for non-Windows OSes.
200 NOTIMPLEMENTED();
201 return false;
202 #else // !defined(OS_WIN)
203
204 if (no_sandbox) { 240 if (no_sandbox) {
205 base::ProcessHandle process = base::kNullProcessHandle; 241 base::ProcessHandle process = base::kNullProcessHandle;
206 cmd_line->AppendSwitch(switches::kNoSandbox); 242 cmd_line->AppendSwitch(switches::kNoSandbox);
207 base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_); 243 base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
208 } else { 244 } else {
209 ServiceSandboxedProcessLauncherDelegate delegate(exposed_dir); 245 ServiceSandboxedProcessLauncherDelegate delegate;
210 handle_ = content::StartSandboxedProcess(&delegate, cmd_line); 246 handle_ = content::StartSandboxedProcess(&delegate, cmd_line);
211 } 247 }
212 return (handle_ != base::kNullProcessHandle); 248 return (handle_ != base::kNullProcessHandle);
213 #endif // !defined(OS_WIN)
214 } 249 }
215 250
216 base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() { 251 base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
217 #if defined(OS_LINUX) 252 #if defined(OS_LINUX)
218 int flags = ChildProcessHost::CHILD_ALLOW_SELF; 253 int flags = ChildProcessHost::CHILD_ALLOW_SELF;
219 #else 254 #else
220 int flags = ChildProcessHost::CHILD_NORMAL; 255 int flags = ChildProcessHost::CHILD_NORMAL;
221 #endif 256 #endif
222 return ChildProcessHost::GetChildPath(flags); 257 return ChildProcessHost::GetChildPath(flags);
223 } 258 }
224 259
225 void ServiceUtilityProcessHost::OnChildDisconnected() { 260 void ServiceUtilityProcessHost::OnChildDisconnected() {
226 if (waiting_for_reply_) { 261 if (waiting_for_reply_) {
227 // If we are yet to receive a reply then notify the client that the 262 // If we are yet to receive a reply then notify the client that the
228 // child died. 263 // child died.
229 client_message_loop_proxy_->PostTask( 264 client_message_loop_proxy_->PostTask(
230 FROM_HERE, base::Bind(&Client::OnChildDied, client_.get())); 265 FROM_HERE, base::Bind(&Client::OnChildDied, client_.get()));
231 ReportUmaEvent(SERVICE_UTILITY_DISCONNECTED); 266 ReportUmaEvent(SERVICE_UTILITY_DISCONNECTED);
232 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityDisconnectTime", 267 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityDisconnectTime",
233 base::Time::Now() - start_time_); 268 base::Time::Now() - start_time_);
234 } 269 }
235 delete this; 270 delete this;
236 } 271 }
237 272
238 bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) { 273 bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
239 bool handled = true; 274 bool handled = true;
240 IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message) 275 IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message)
241 #if defined(OS_WIN)
242 IPC_MESSAGE_HANDLER( 276 IPC_MESSAGE_HANDLER(
243 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded, 277 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
244 OnRenderPDFPagesToMetafilesSucceeded) 278 OnRenderPDFPagesToMetafilesPageCount)
245 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed, 279 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
246 OnRenderPDFPagesToMetafileFailed) 280 OnRenderPDFPagesToMetafilesPageDone)
247 #endif
248 IPC_MESSAGE_HANDLER( 281 IPC_MESSAGE_HANDLER(
249 ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded, 282 ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded,
250 OnGetPrinterCapsAndDefaultsSucceeded) 283 OnGetPrinterCapsAndDefaultsSucceeded)
251 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed, 284 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed,
252 OnGetPrinterCapsAndDefaultsFailed) 285 OnGetPrinterCapsAndDefaultsFailed)
253 IPC_MESSAGE_HANDLER( 286 IPC_MESSAGE_HANDLER(
254 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded, 287 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded,
255 OnGetPrinterSemanticCapsAndDefaultsSucceeded) 288 OnGetPrinterSemanticCapsAndDefaultsSucceeded)
256 IPC_MESSAGE_HANDLER( 289 IPC_MESSAGE_HANDLER(
257 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed, 290 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed,
258 OnGetPrinterSemanticCapsAndDefaultsFailed) 291 OnGetPrinterSemanticCapsAndDefaultsFailed)
259 IPC_MESSAGE_UNHANDLED(handled = false) 292 IPC_MESSAGE_UNHANDLED(handled = false)
260 IPC_END_MESSAGE_MAP() 293 IPC_END_MESSAGE_MAP()
261 return handled; 294 return handled;
262 } 295 }
263 296
264 base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const { 297 base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const {
265 return handle_; 298 return handle_;
266 } 299 }
267 300
268 #if defined(OS_WIN) 301 void ServiceUtilityProcessHost::OnMetafileSpooled(bool success) {
269 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesSucceeded( 302 if (!success || pdf_to_emf_state_->OnPageProcessed())
270 const std::vector<printing::PageRange>& page_ranges, 303 OnPDFToEmfFinished(success);
304 }
305
306 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageCount(
307 int page_count) {
308 DCHECK(waiting_for_reply_);
309 if (!pdf_to_emf_state_ || page_count <= 0 ||
310 pdf_to_emf_state_->has_page_count()) {
311 return OnPDFToEmfFinished(false);
312 }
313 pdf_to_emf_state_->set_page_count(page_count);
314 pdf_to_emf_state_->GetMorePages();
315 }
316
317 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageDone(
318 bool success,
271 double scale_factor) { 319 double scale_factor) {
272 ReportUmaEvent(SERVICE_UTILITY_METAFILE_SUCCEEDED);
273 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
274 base::Time::Now() - start_time_);
275 DCHECK(waiting_for_reply_); 320 DCHECK(waiting_for_reply_);
276 waiting_for_reply_ = false; 321 if (!pdf_to_emf_state_ || !success)
277 // If the metafile was successfully created, we need to take our hands off the 322 return OnPDFToEmfFinished(false);
278 // scratch metafile directory. The client will delete it when it is done with 323 base::File emf_file = pdf_to_emf_state_->TakeNextFile();
279 // metafile. 324 base::PostTaskAndReplyWithResult(
280 scratch_metafile_dir_->Take(); 325 client_message_loop_proxy_,
281
282 // TODO(vitalybuka|scottmg): http://crbug.com/170859: Currently, only one
283 // page is printed at a time. This would need to be refactored to change
284 // this.
285 CHECK_EQ(1u, page_ranges.size());
286 CHECK_EQ(page_ranges[0].from, page_ranges[0].to);
287 int page_number = page_ranges[0].from;
288 client_message_loop_proxy_->PostTask(
289 FROM_HERE, 326 FROM_HERE,
290 base::Bind(&Client::MetafileAvailable, 327 base::Bind(&Client::MetafileAvailable,
291 client_.get(), 328 client_.get(),
292 metafile_path_.InsertBeforeExtensionASCII( 329 scale_factor,
293 base::StringPrintf(".%d", page_number)), 330 base::Passed(&emf_file)),
294 page_number, 331 base::Bind(&ServiceUtilityProcessHost::OnMetafileSpooled,
295 scale_factor)); 332 weak_ptr_factory_.GetWeakPtr()));
296 } 333 }
297 334
298 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileFailed() { 335 void ServiceUtilityProcessHost::OnPDFToEmfFinished(bool success) {
299 DCHECK(waiting_for_reply_); 336 if (!waiting_for_reply_)
300 ReportUmaEvent(SERVICE_UTILITY_METAFILE_FAILED); 337 return;
301 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
302 base::Time::Now() - start_time_);
303 waiting_for_reply_ = false; 338 waiting_for_reply_ = false;
339 if (success) {
340 ReportUmaEvent(SERVICE_UTILITY_METAFILE_SUCCEEDED);
341 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
342 base::Time::Now() - start_time_);
343 } else {
344 ReportUmaEvent(SERVICE_UTILITY_METAFILE_FAILED);
345 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
346 base::Time::Now() - start_time_);
347 }
304 client_message_loop_proxy_->PostTask( 348 client_message_loop_proxy_->PostTask(
305 FROM_HERE, 349 FROM_HERE,
306 base::Bind(&Client::OnRenderPDFPagesToMetafileFailed, client_.get())); 350 base::Bind(
351 &Client::OnRenderPDFPagesToMetafileDone, client_.get(), success));
352 pdf_to_emf_state_.reset();
307 } 353 }
308 #endif // defined(OS_WIN)
309 354
310 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded( 355 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded(
311 const std::string& printer_name, 356 const std::string& printer_name,
312 const printing::PrinterCapsAndDefaults& caps_and_defaults) { 357 const printing::PrinterCapsAndDefaults& caps_and_defaults) {
313 DCHECK(waiting_for_reply_); 358 DCHECK(waiting_for_reply_);
314 ReportUmaEvent(SERVICE_UTILITY_CAPS_SUCCEEDED); 359 ReportUmaEvent(SERVICE_UTILITY_CAPS_SUCCEEDED);
315 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsTime", 360 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsTime",
316 base::Time::Now() - start_time_); 361 base::Time::Now() - start_time_);
317 waiting_for_reply_ = false; 362 waiting_for_reply_ = false;
318 client_message_loop_proxy_->PostTask( 363 client_message_loop_proxy_->PostTask(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsFailTime", 400 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsFailTime",
356 base::Time::Now() - start_time_); 401 base::Time::Now() - start_time_);
357 waiting_for_reply_ = false; 402 waiting_for_reply_ = false;
358 client_message_loop_proxy_->PostTask( 403 client_message_loop_proxy_->PostTask(
359 FROM_HERE, 404 FROM_HERE,
360 base::Bind(&Client::OnGetPrinterSemanticCapsAndDefaults, 405 base::Bind(&Client::OnGetPrinterSemanticCapsAndDefaults,
361 client_.get(), false, printer_name, 406 client_.get(), false, printer_name,
362 printing::PrinterSemanticCapsAndDefaults())); 407 printing::PrinterSemanticCapsAndDefaults()));
363 } 408 }
364 409
365 void ServiceUtilityProcessHost::Client::MetafileAvailable( 410 bool ServiceUtilityProcessHost::Client::MetafileAvailable(double scale_factor,
366 const base::FilePath& metafile_path, 411 base::File file) {
367 int highest_rendered_page_number, 412 file.Seek(base::File::FROM_BEGIN, 0);
368 double scale_factor) { 413 int64 size = file.GetLength();
369 // The metafile was created in a temp folder which needs to get deleted after 414 if (size <= 0) {
370 // we have processed it. 415 OnRenderPDFPagesToMetafileDone(false);
371 base::ScopedTempDir scratch_metafile_dir; 416 return false;
372 if (!scratch_metafile_dir.Set(metafile_path.DirName()))
373 LOG(WARNING) << "Unable to set scratch metafile directory";
374 #if defined(OS_WIN)
375 // It's important that metafile is declared after scratch_metafile_dir so
376 // that the metafile destructor closes the file before the base::ScopedTempDir
377 // destructor tries to remove the directory.
378 printing::Emf metafile;
379 if (!metafile.InitFromFile(metafile_path)) {
380 OnRenderPDFPagesToMetafileFailed();
381 } else {
382 OnRenderPDFPagesToMetafileSucceeded(metafile,
383 highest_rendered_page_number,
384 scale_factor);
385 } 417 }
386 #endif // defined(OS_WIN) 418 std::vector<char> data(size);
419 if (file.ReadAtCurrentPos(data.data(), data.size()) != size) {
420 OnRenderPDFPagesToMetafileDone(false);
421 return false;
422 }
423 printing::Emf emf;
424 if (!emf.InitFromData(data.data(), data.size())) {
425 OnRenderPDFPagesToMetafileDone(false);
426 return false;
427 }
428 OnRenderPDFPagesToMetafilePageDone(scale_factor, emf);
429 return true;
387 } 430 }
388
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698