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

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: Wed Sep 17 10:40: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
« no previous file with comments | « chrome/service/service_utility_process_host.h ('k') | chrome/utility/printing_handler.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 (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 |
139 base::File::FLAG_WRITE |
140 base::File::FLAG_READ |
141 base::File::FLAG_DELETE_ON_CLOSE |
142 base::File::FLAG_TEMPORARY);
143 }
144
145 base::ScopedTempDir temp_dir_;
146 ServiceUtilityProcessHost* host_;
147 std::queue<base::File> emf_files_;
148 int page_count_;
149 int current_page_;
150 int pages_in_progress_;
151 };
152
96 ServiceUtilityProcessHost::ServiceUtilityProcessHost( 153 ServiceUtilityProcessHost::ServiceUtilityProcessHost(
97 Client* client, base::MessageLoopProxy* client_message_loop_proxy) 154 Client* client,
98 : handle_(base::kNullProcessHandle), 155 base::MessageLoopProxy* client_message_loop_proxy)
99 client_(client), 156 : handle_(base::kNullProcessHandle),
100 client_message_loop_proxy_(client_message_loop_proxy), 157 client_(client),
101 waiting_for_reply_(false) { 158 client_message_loop_proxy_(client_message_loop_proxy),
159 waiting_for_reply_(false),
160 weak_ptr_factory_(this) {
102 child_process_host_.reset(ChildProcessHost::Create(this)); 161 child_process_host_.reset(ChildProcessHost::Create(this));
103 } 162 }
104 163
105 ServiceUtilityProcessHost::~ServiceUtilityProcessHost() { 164 ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
106 // We need to kill the child process when the host dies. 165 // We need to kill the child process when the host dies.
107 base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false); 166 base::KillProcess(handle_, content::RESULT_CODE_NORMAL_EXIT, false);
108 } 167 }
109 168
110 bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile( 169 bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
111 const base::FilePath& pdf_path, 170 const base::FilePath& pdf_path,
112 const printing::PdfRenderSettings& render_settings, 171 const printing::PdfRenderSettings& render_settings) {
113 const std::vector<printing::PageRange>& page_ranges) {
114 ReportUmaEvent(SERVICE_UTILITY_METAFILE_REQUEST); 172 ReportUmaEvent(SERVICE_UTILITY_METAFILE_REQUEST);
115 start_time_ = base::Time::Now(); 173 start_time_ = base::Time::Now();
116 #if !defined(OS_WIN) 174 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 175 if (!pdf_file.IsValid() || !StartProcess(false))
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; 176 return false;
128 177
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_); 178 DCHECK(!waiting_for_reply_);
133 waiting_for_reply_ = true; 179 waiting_for_reply_ = true;
134 return child_process_host_->Send( 180
135 new ChromeUtilityMsg_RenderPDFPagesToMetafiles( 181 pdf_to_emf_state_.reset(new PdfToEmfState(this));
136 IPC::TakeFileHandleForProcess(pdf_file.Pass(), handle()), 182 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 } 183 }
142 184
143 bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults( 185 bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
144 const std::string& printer_name) { 186 const std::string& printer_name) {
145 ReportUmaEvent(SERVICE_UTILITY_CAPS_REQUEST); 187 ReportUmaEvent(SERVICE_UTILITY_CAPS_REQUEST);
146 start_time_ = base::Time::Now(); 188 start_time_ = base::Time::Now();
147 base::FilePath exposed_path; 189 if (!StartProcess(true))
148 if (!StartProcess(true, exposed_path))
149 return false; 190 return false;
150 DCHECK(!waiting_for_reply_); 191 DCHECK(!waiting_for_reply_);
151 waiting_for_reply_ = true; 192 waiting_for_reply_ = true;
152 return child_process_host_->Send( 193 return Send(new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
153 new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
154 } 194 }
155 195
156 bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults( 196 bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults(
157 const std::string& printer_name) { 197 const std::string& printer_name) {
158 ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST); 198 ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST);
159 start_time_ = base::Time::Now(); 199 start_time_ = base::Time::Now();
160 base::FilePath exposed_path; 200 if (!StartProcess(true))
161 if (!StartProcess(true, exposed_path))
162 return false; 201 return false;
163 DCHECK(!waiting_for_reply_); 202 DCHECK(!waiting_for_reply_);
164 waiting_for_reply_ = true; 203 waiting_for_reply_ = true;
165 return child_process_host_->Send( 204 return Send(
166 new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name)); 205 new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name));
167 } 206 }
168 207
169 bool ServiceUtilityProcessHost::StartProcess( 208 bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox) {
170 bool no_sandbox,
171 const base::FilePath& exposed_dir) {
172 std::string channel_id = child_process_host_->CreateChannel(); 209 std::string channel_id = child_process_host_->CreateChannel();
173 if (channel_id.empty()) 210 if (channel_id.empty())
174 return false; 211 return false;
175 212
176 base::FilePath exe_path = GetUtilityProcessCmd(); 213 base::FilePath exe_path = GetUtilityProcessCmd();
177 if (exe_path.empty()) { 214 if (exe_path.empty()) {
178 NOTREACHED() << "Unable to get utility process binary name."; 215 NOTREACHED() << "Unable to get utility process binary name.";
179 return false; 216 return false;
180 } 217 }
181 218
182 CommandLine cmd_line(exe_path); 219 base::CommandLine cmd_line(exe_path);
183 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess); 220 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess);
184 cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id); 221 cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id);
185 cmd_line.AppendSwitch(switches::kLang); 222 cmd_line.AppendSwitch(switches::kLang);
186 223
187 if (Launch(&cmd_line, no_sandbox, exposed_dir)) { 224 if (Launch(&cmd_line, no_sandbox)) {
188 ReportUmaEvent(SERVICE_UTILITY_STARTED); 225 ReportUmaEvent(SERVICE_UTILITY_STARTED);
189 return true; 226 return true;
190 } 227 }
191 ReportUmaEvent(SERVICE_UTILITY_FAILED_TO_START); 228 ReportUmaEvent(SERVICE_UTILITY_FAILED_TO_START);
192 return false; 229 return false;
193 } 230 }
194 231
195 bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line, 232 bool ServiceUtilityProcessHost::Launch(base::CommandLine* cmd_line,
196 bool no_sandbox, 233 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) { 234 if (no_sandbox) {
205 base::ProcessHandle process = base::kNullProcessHandle; 235 base::ProcessHandle process = base::kNullProcessHandle;
206 cmd_line->AppendSwitch(switches::kNoSandbox); 236 cmd_line->AppendSwitch(switches::kNoSandbox);
207 base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_); 237 base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
208 } else { 238 } else {
209 ServiceSandboxedProcessLauncherDelegate delegate(exposed_dir); 239 ServiceSandboxedProcessLauncherDelegate delegate;
210 handle_ = content::StartSandboxedProcess(&delegate, cmd_line); 240 handle_ = content::StartSandboxedProcess(&delegate, cmd_line);
211 } 241 }
212 return (handle_ != base::kNullProcessHandle); 242 return (handle_ != base::kNullProcessHandle);
213 #endif // !defined(OS_WIN) 243 }
244
245 bool ServiceUtilityProcessHost::Send(IPC::Message* msg) {
246 if (child_process_host_)
247 return child_process_host_->Send(msg);
248 delete msg;
249 return false;
214 } 250 }
215 251
216 base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() { 252 base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
217 #if defined(OS_LINUX) 253 #if defined(OS_LINUX)
218 int flags = ChildProcessHost::CHILD_ALLOW_SELF; 254 int flags = ChildProcessHost::CHILD_ALLOW_SELF;
219 #else 255 #else
220 int flags = ChildProcessHost::CHILD_NORMAL; 256 int flags = ChildProcessHost::CHILD_NORMAL;
221 #endif 257 #endif
222 return ChildProcessHost::GetChildPath(flags); 258 return ChildProcessHost::GetChildPath(flags);
223 } 259 }
224 260
225 void ServiceUtilityProcessHost::OnChildDisconnected() { 261 void ServiceUtilityProcessHost::OnChildDisconnected() {
226 if (waiting_for_reply_) { 262 if (waiting_for_reply_) {
227 // If we are yet to receive a reply then notify the client that the 263 // If we are yet to receive a reply then notify the client that the
228 // child died. 264 // child died.
229 client_message_loop_proxy_->PostTask( 265 client_message_loop_proxy_->PostTask(
230 FROM_HERE, base::Bind(&Client::OnChildDied, client_.get())); 266 FROM_HERE, base::Bind(&Client::OnChildDied, client_.get()));
231 ReportUmaEvent(SERVICE_UTILITY_DISCONNECTED); 267 ReportUmaEvent(SERVICE_UTILITY_DISCONNECTED);
232 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityDisconnectTime", 268 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityDisconnectTime",
233 base::Time::Now() - start_time_); 269 base::Time::Now() - start_time_);
234 } 270 }
235 delete this; 271 delete this;
236 } 272 }
237 273
238 bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) { 274 bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
239 bool handled = true; 275 bool handled = true;
240 IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message) 276 IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message)
241 #if defined(OS_WIN)
242 IPC_MESSAGE_HANDLER( 277 IPC_MESSAGE_HANDLER(
243 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded, 278 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
244 OnRenderPDFPagesToMetafilesSucceeded) 279 OnRenderPDFPagesToMetafilesPageCount)
245 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed, 280 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
246 OnRenderPDFPagesToMetafileFailed) 281 OnRenderPDFPagesToMetafilesPageDone)
247 #endif
248 IPC_MESSAGE_HANDLER( 282 IPC_MESSAGE_HANDLER(
249 ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded, 283 ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded,
250 OnGetPrinterCapsAndDefaultsSucceeded) 284 OnGetPrinterCapsAndDefaultsSucceeded)
251 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed, 285 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed,
252 OnGetPrinterCapsAndDefaultsFailed) 286 OnGetPrinterCapsAndDefaultsFailed)
253 IPC_MESSAGE_HANDLER( 287 IPC_MESSAGE_HANDLER(
254 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded, 288 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded,
255 OnGetPrinterSemanticCapsAndDefaultsSucceeded) 289 OnGetPrinterSemanticCapsAndDefaultsSucceeded)
256 IPC_MESSAGE_HANDLER( 290 IPC_MESSAGE_HANDLER(
257 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed, 291 ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed,
258 OnGetPrinterSemanticCapsAndDefaultsFailed) 292 OnGetPrinterSemanticCapsAndDefaultsFailed)
259 IPC_MESSAGE_UNHANDLED(handled = false) 293 IPC_MESSAGE_UNHANDLED(handled = false)
260 IPC_END_MESSAGE_MAP() 294 IPC_END_MESSAGE_MAP()
261 return handled; 295 return handled;
262 } 296 }
263 297
264 base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const { 298 base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const {
265 return handle_; 299 return handle_;
266 } 300 }
267 301
268 #if defined(OS_WIN) 302 void ServiceUtilityProcessHost::OnMetafileSpooled(bool success) {
269 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesSucceeded( 303 if (!success || pdf_to_emf_state_->OnPageProcessed())
270 const std::vector<printing::PageRange>& page_ranges, 304 OnPDFToEmfFinished(success);
305 }
306
307 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageCount(
308 int page_count) {
309 DCHECK(waiting_for_reply_);
310 if (!pdf_to_emf_state_ || page_count <= 0 ||
311 pdf_to_emf_state_->has_page_count()) {
312 return OnPDFToEmfFinished(false);
313 }
314 pdf_to_emf_state_->set_page_count(page_count);
315 pdf_to_emf_state_->GetMorePages();
316 }
317
318 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageDone(
319 bool success,
271 double scale_factor) { 320 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_); 321 DCHECK(waiting_for_reply_);
276 waiting_for_reply_ = false; 322 if (!pdf_to_emf_state_ || !success)
277 // If the metafile was successfully created, we need to take our hands off the 323 return OnPDFToEmfFinished(false);
278 // scratch metafile directory. The client will delete it when it is done with 324 base::File emf_file = pdf_to_emf_state_->TakeNextFile();
279 // metafile. 325 base::PostTaskAndReplyWithResult(
280 scratch_metafile_dir_->Take(); 326 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, 327 FROM_HERE,
290 base::Bind(&Client::MetafileAvailable, 328 base::Bind(&Client::MetafileAvailable,
291 client_.get(), 329 client_.get(),
292 metafile_path_.InsertBeforeExtensionASCII( 330 scale_factor,
293 base::StringPrintf(".%d", page_number)), 331 base::Passed(&emf_file)),
294 page_number, 332 base::Bind(&ServiceUtilityProcessHost::OnMetafileSpooled,
295 scale_factor)); 333 weak_ptr_factory_.GetWeakPtr()));
296 } 334 }
297 335
298 void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileFailed() { 336 void ServiceUtilityProcessHost::OnPDFToEmfFinished(bool success) {
299 DCHECK(waiting_for_reply_); 337 if (!waiting_for_reply_)
300 ReportUmaEvent(SERVICE_UTILITY_METAFILE_FAILED); 338 return;
301 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
302 base::Time::Now() - start_time_);
303 waiting_for_reply_ = false; 339 waiting_for_reply_ = false;
340 if (success) {
341 ReportUmaEvent(SERVICE_UTILITY_METAFILE_SUCCEEDED);
342 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
343 base::Time::Now() - start_time_);
344 } else {
345 ReportUmaEvent(SERVICE_UTILITY_METAFILE_FAILED);
346 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
347 base::Time::Now() - start_time_);
348 }
304 client_message_loop_proxy_->PostTask( 349 client_message_loop_proxy_->PostTask(
305 FROM_HERE, 350 FROM_HERE,
306 base::Bind(&Client::OnRenderPDFPagesToMetafileFailed, client_.get())); 351 base::Bind(
352 &Client::OnRenderPDFPagesToMetafileDone, client_.get(), success));
353 pdf_to_emf_state_.reset();
307 } 354 }
308 #endif // defined(OS_WIN)
309 355
310 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded( 356 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded(
311 const std::string& printer_name, 357 const std::string& printer_name,
312 const printing::PrinterCapsAndDefaults& caps_and_defaults) { 358 const printing::PrinterCapsAndDefaults& caps_and_defaults) {
313 DCHECK(waiting_for_reply_); 359 DCHECK(waiting_for_reply_);
314 ReportUmaEvent(SERVICE_UTILITY_CAPS_SUCCEEDED); 360 ReportUmaEvent(SERVICE_UTILITY_CAPS_SUCCEEDED);
315 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsTime", 361 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsTime",
316 base::Time::Now() - start_time_); 362 base::Time::Now() - start_time_);
317 waiting_for_reply_ = false; 363 waiting_for_reply_ = false;
318 client_message_loop_proxy_->PostTask( 364 client_message_loop_proxy_->PostTask(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsFailTime", 401 UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsFailTime",
356 base::Time::Now() - start_time_); 402 base::Time::Now() - start_time_);
357 waiting_for_reply_ = false; 403 waiting_for_reply_ = false;
358 client_message_loop_proxy_->PostTask( 404 client_message_loop_proxy_->PostTask(
359 FROM_HERE, 405 FROM_HERE,
360 base::Bind(&Client::OnGetPrinterSemanticCapsAndDefaults, 406 base::Bind(&Client::OnGetPrinterSemanticCapsAndDefaults,
361 client_.get(), false, printer_name, 407 client_.get(), false, printer_name,
362 printing::PrinterSemanticCapsAndDefaults())); 408 printing::PrinterSemanticCapsAndDefaults()));
363 } 409 }
364 410
365 void ServiceUtilityProcessHost::Client::MetafileAvailable( 411 bool ServiceUtilityProcessHost::Client::MetafileAvailable(double scale_factor,
366 const base::FilePath& metafile_path, 412 base::File file) {
367 int highest_rendered_page_number, 413 file.Seek(base::File::FROM_BEGIN, 0);
368 double scale_factor) { 414 int64 size = file.GetLength();
369 // The metafile was created in a temp folder which needs to get deleted after 415 if (size <= 0) {
370 // we have processed it. 416 OnRenderPDFPagesToMetafileDone(false);
371 base::ScopedTempDir scratch_metafile_dir; 417 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 } 418 }
386 #endif // defined(OS_WIN) 419 std::vector<char> data(size);
420 if (file.ReadAtCurrentPos(data.data(), data.size()) != size) {
421 OnRenderPDFPagesToMetafileDone(false);
422 return false;
423 }
424 printing::Emf emf;
425 if (!emf.InitFromData(data.data(), data.size())) {
426 OnRenderPDFPagesToMetafileDone(false);
427 return false;
428 }
429 OnRenderPDFPagesToMetafilePageDone(scale_factor, emf);
430 return true;
387 } 431 }
388
OLDNEW
« no previous file with comments | « chrome/service/service_utility_process_host.h ('k') | chrome/utility/printing_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698