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

Unified 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: Mon Sep 15 03:22:54 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 side-by-side diff with in-line comments
Download patch
Index: chrome/service/service_utility_process_host.cc
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index df2cf9400d0302903a1d352a863a383c99ccdc0d..d3dd78d71c296d224f5ad0f2c1b5b687068d5bb9 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -6,68 +6,31 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/process/kill.h"
-#include "base/strings/utf_string_conversions.h"
+#include "base/process/launch.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_utility_printing_messages.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandbox_init.h"
-#include "ipc/ipc_switches.h"
-#include "printing/page_range.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/rect.h"
-
-#if defined(OS_WIN)
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/launch.h"
-#include "base/win/scoped_handle.h"
-#include "content/public/common/sandbox_init.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "ipc/ipc_switches.h"
#include "printing/emf_win.h"
#include "sandbox/win/src/sandbox_policy_base.h"
+#include "ui/base/ui_base_switches.h"
namespace {
-// NOTE: changes to this class need to be reviewed by the security team.
-class ServiceSandboxedProcessLauncherDelegate
- : public content::SandboxedProcessLauncherDelegate {
- public:
- explicit ServiceSandboxedProcessLauncherDelegate(
- const base::FilePath& exposed_dir)
- : exposed_dir_(exposed_dir) {
- }
-
- virtual void PreSandbox(bool* disable_default_policy,
- base::FilePath* exposed_dir) OVERRIDE {
- *exposed_dir = exposed_dir_;
- }
-
- virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
- bool* success) OVERRIDE {
- // Service process may run as windows service and it fails to create a
- // window station.
- policy->SetAlternateDesktop(false);
- }
-
- private:
- base::FilePath exposed_dir_;
-};
-
-} // namespace
-
-#endif // OS_WIN
-
using content::ChildProcessHost;
-namespace {
+const int kMaxNumberOfTempFilesPerDocument = 3;
+
enum ServiceUtilityProcessHostEvent {
SERVICE_UTILITY_STARTED,
SERVICE_UTILITY_DISCONNECTED,
@@ -82,14 +45,46 @@ enum ServiceUtilityProcessHostEvent {
SERVICE_UTILITY_SEMANTIC_CAPS_FAILED,
SERVICE_UTILITY_EVENT_MAX,
};
+
+// NOTE: changes to this class need to be reviewed by the security team.
+class ServiceSandboxedProcessLauncherDelegate
+ : public content::SandboxedProcessLauncherDelegate {
+ public:
+ ServiceSandboxedProcessLauncherDelegate() {}
+
+ virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
+ bool* success) OVERRIDE {
+ // Service process may run as windows service and it fails to create a
+ // window station.
+ policy->SetAlternateDesktop(false);
+ }
+
+ private:
+};
+
+base::File CreateTempFile() {
+ base::FilePath path;
+ if (!base::CreateTemporaryFile(&path))
+ return base::File();
+ return base::File(path,
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
+ base::File::FLAG_READ |
+ base::File::FLAG_DELETE_ON_CLOSE |
+ base::File::FLAG_TEMPORARY);
+}
+
} // namespace
ServiceUtilityProcessHost::ServiceUtilityProcessHost(
- Client* client, base::MessageLoopProxy* client_message_loop_proxy)
- : handle_(base::kNullProcessHandle),
- client_(client),
- client_message_loop_proxy_(client_message_loop_proxy),
- waiting_for_reply_(false) {
+ Client* client,
+ base::MessageLoopProxy* client_message_loop_proxy)
+ : handle_(base::kNullProcessHandle),
+ client_(client),
+ client_message_loop_proxy_(client_message_loop_proxy),
+ waiting_for_reply_(false),
+ number_of_emf_in_progress_(0),
+ create_file_reply_msg_(NULL),
+ weak_ptr_factory_(this) {
child_process_host_.reset(ChildProcessHost::Create(this));
}
@@ -100,37 +95,20 @@ ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
const base::FilePath& pdf_path,
- const printing::PdfRenderSettings& render_settings,
- const std::vector<printing::PageRange>& page_ranges) {
+ const printing::PdfRenderSettings& render_settings) {
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
SERVICE_UTILITY_METAFILE_REQUEST,
SERVICE_UTILITY_EVENT_MAX);
start_time_ = base::Time::Now();
-#if !defined(OS_WIN)
- // This is only implemented on Windows (because currently it is only needed
- // on Windows). Will add implementations on other platforms when needed.
- NOTIMPLEMENTED();
- return false;
-#else // !defined(OS_WIN)
- scratch_metafile_dir_.reset(new base::ScopedTempDir);
- if (!scratch_metafile_dir_->CreateUniqueTempDir())
- return false;
- metafile_path_ = scratch_metafile_dir_->path().AppendASCII("output.emf");
- if (!StartProcess(false, scratch_metafile_dir_->path()))
+ base::File pdf_file(pdf_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!pdf_file.IsValid() || !StartProcess(false))
return false;
- base::File pdf_file(
- pdf_path,
- base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
DCHECK(!waiting_for_reply_);
waiting_for_reply_ = true;
- return child_process_host_->Send(
- new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
- IPC::TakeFileHandleForProcess(pdf_file.Pass(), handle()),
- metafile_path_,
- render_settings,
- page_ranges));
-#endif // !defined(OS_WIN)
+ return Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
+ IPC::TakeFileHandleForProcess(pdf_file.Pass(), handle()),
+ render_settings));
}
bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
@@ -139,13 +117,11 @@ bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
SERVICE_UTILITY_CAPS_REQUEST,
SERVICE_UTILITY_EVENT_MAX);
start_time_ = base::Time::Now();
- base::FilePath exposed_path;
- if (!StartProcess(true, exposed_path))
+ if (!StartProcess(true))
return false;
DCHECK(!waiting_for_reply_);
waiting_for_reply_ = true;
- return child_process_host_->Send(
- new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
+ return Send(new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
}
bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults(
@@ -154,18 +130,22 @@ bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults(
SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST,
SERVICE_UTILITY_EVENT_MAX);
start_time_ = base::Time::Now();
- base::FilePath exposed_path;
- if (!StartProcess(true, exposed_path))
+ if (!StartProcess(true))
return false;
DCHECK(!waiting_for_reply_);
waiting_for_reply_ = true;
- return child_process_host_->Send(
+ return Send(
new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name));
}
-bool ServiceUtilityProcessHost::StartProcess(
- bool no_sandbox,
- const base::FilePath& exposed_dir) {
+bool ServiceUtilityProcessHost::Send(IPC::Message* msg) {
+ if (child_process_host_)
+ return child_process_host_->Send(msg);
+ delete msg;
+ return false;
+}
+
+bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox) {
std::string channel_id = child_process_host_->CreateChannel();
if (channel_id.empty())
return false;
@@ -181,7 +161,7 @@ bool ServiceUtilityProcessHost::StartProcess(
cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id);
cmd_line.AppendSwitch(switches::kLang);
- if (Launch(&cmd_line, no_sandbox, exposed_dir)) {
+ if (Launch(&cmd_line, no_sandbox)) {
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
SERVICE_UTILITY_STARTED,
SERVICE_UTILITY_EVENT_MAX);
@@ -190,25 +170,16 @@ bool ServiceUtilityProcessHost::StartProcess(
return false;
}
-bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line,
- bool no_sandbox,
- const base::FilePath& exposed_dir) {
-#if !defined(OS_WIN)
- // TODO(sanjeevr): Implement for non-Windows OSes.
- NOTIMPLEMENTED();
- return false;
-#else // !defined(OS_WIN)
-
+bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line, bool no_sandbox) {
if (no_sandbox) {
base::ProcessHandle process = base::kNullProcessHandle;
cmd_line->AppendSwitch(switches::kNoSandbox);
base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
} else {
- ServiceSandboxedProcessLauncherDelegate delegate(exposed_dir);
+ ServiceSandboxedProcessLauncherDelegate delegate;
handle_ = content::StartSandboxedProcess(&delegate, cmd_line);
}
return (handle_ != base::kNullProcessHandle);
-#endif // !defined(OS_WIN)
}
base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
@@ -238,13 +209,10 @@ void ServiceUtilityProcessHost::OnChildDisconnected() {
bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message)
-#if defined(OS_WIN)
- IPC_MESSAGE_HANDLER(
- ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded,
- OnRenderPDFPagesToMetafilesSucceeded)
- IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed,
- OnRenderPDFPagesToMetafileFailed)
-#endif
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
+ OnRenderPDFPagesToMetafilesPageCount)
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
+ OnRenderPDFPagesToMetafilesPageDone)
IPC_MESSAGE_HANDLER(
ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded,
OnGetPrinterCapsAndDefaultsSucceeded)
@@ -265,51 +233,99 @@ base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const {
return handle_;
}
-#if defined(OS_WIN)
-void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesSucceeded(
- const std::vector<printing::PageRange>& page_ranges,
+void ServiceUtilityProcessHost::OnMetafileSpooled() {
+ --number_of_emf_in_progress_;
+ // ReplayCreateFileIfReady();
+}
+
+// void ServiceUtilityProcessHost::ReplayCreateFileIfReady() {
+// if (!create_file_reply_msg_ ||
+// number_of_emf_in_progress_ >= kMaxNumberOfTempFilesPerDocument) {
+// return;
+// }
+// DCHECK(waiting_for_reply_);
+// if (emf_file_.IsValid()) {
+// NOTREACHED() << "Utility can't request more than one file.";
+// return FailReplyOnCreate();
+// }
+// emf_file_ = CreateTempFile();
+// DCHECK(emf_file_.IsValid());
+// /*OnRenderPDFPagesToMetafilesCreateFileReply(IPC::GetFileHandleForProcess(
+// emf_file_.GetPlatformFile(), handle(), false));*/
+//}
+
+// void ServiceUtilityProcessHost::FailReplyOnCreate() {
+// OnRenderPDFPagesToMetafilesCreateFileReply(
+// IPC::InvalidPlatformFileForTransit());
+// return OnRenderPDFPagesToMetafileFailed();
+//}
+//
+// void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesCreateFile(
+// IPC::Message* reply_msg) {
+// DCHECK(waiting_for_reply_);
+// if (create_file_reply_msg_) {
+// NOTREACHED() << "Utility can't create more than one request.";
+// // Fail both.
+// FailReplyOnCreate();
+// create_file_reply_msg_ = reply_msg;
+// FailReplyOnCreate();
+// return;
+// }
+// create_file_reply_msg_ = reply_msg;
+// ReplayCreateFileIfReady();
+//}
+//
+// void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesCreateFileReply(
+// IPC::PlatformFileForTransit file) {
+// DCHECK(waiting_for_reply_);
+// ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_CreateFile::WriteReplyParams(
+// create_file_reply_msg_, file);
+// Send(create_file_reply_msg_);
+// create_file_reply_msg_ = NULL;
+//}
+
+void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageDone(
+ bool success,
double scale_factor) {
- UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
- SERVICE_UTILITY_METAFILE_SUCCEEDED,
- SERVICE_UTILITY_EVENT_MAX);
- UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
- base::Time::Now() - start_time_);
DCHECK(waiting_for_reply_);
- waiting_for_reply_ = false;
- // If the metafile was successfully created, we need to take our hands off the
- // scratch metafile directory. The client will delete it when it is done with
- // metafile.
- scratch_metafile_dir_->Take();
-
- // TODO(vitalybuka|scottmg): http://crbug.com/170859: Currently, only one
- // page is printed at a time. This would need to be refactored to change
- // this.
- CHECK_EQ(1u, page_ranges.size());
- CHECK_EQ(page_ranges[0].from, page_ranges[0].to);
- int page_number = page_ranges[0].from;
- client_message_loop_proxy_->PostTask(
+ ++number_of_emf_in_progress_;
+ client_message_loop_proxy_->PostTaskAndReply(
FROM_HERE,
base::Bind(&Client::MetafileAvailable,
client_.get(),
- metafile_path_.InsertBeforeExtensionASCII(
- base::StringPrintf(".%d", page_number)),
- page_number,
- scale_factor));
+ scale_factor,
+ base::Passed(&emf_file_)),
+ base::Bind(&ServiceUtilityProcessHost::OnMetafileSpooled,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileFailed() {
- DCHECK(waiting_for_reply_);
- UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
- SERVICE_UTILITY_METAFILE_FAILED,
- SERVICE_UTILITY_EVENT_MAX);
- UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
- base::Time::Now() - start_time_);
- waiting_for_reply_ = false;
- client_message_loop_proxy_->PostTask(
- FROM_HERE,
- base::Bind(&Client::OnRenderPDFPagesToMetafileFailed, client_.get()));
-}
-#endif // defined(OS_WIN)
+// void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesSucceeded() {
+// DCHECK(waiting_for_reply_);
+// UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
+// SERVICE_UTILITY_METAFILE_SUCCEEDED,
+// SERVICE_UTILITY_EVENT_MAX);
+// UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
+// base::Time::Now() - start_time_);
+// waiting_for_reply_ = false;
+// client_message_loop_proxy_->PostTask(
+// FROM_HERE,
+// base::Bind(&Client::OnRenderPDFPagesToMetafileSucceeded,
+// client_.get()));
+//}
+//
+// void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileFailed() {
+// if (!waiting_for_reply_)
+// return;
+// waiting_for_reply_ = false;
+// UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
+// SERVICE_UTILITY_METAFILE_FAILED,
+// SERVICE_UTILITY_EVENT_MAX);
+// UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
+// base::Time::Now() - start_time_);
+// client_message_loop_proxy_->PostTask(
+// FROM_HERE,
+// base::Bind(&Client::OnRenderPDFPagesToMetafileFailed, client_.get()));
+//}
void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded(
const std::string& printer_name,
@@ -374,27 +390,17 @@ void ServiceUtilityProcessHost::OnGetPrinterSemanticCapsAndDefaultsFailed(
printing::PrinterSemanticCapsAndDefaults()));
}
-void ServiceUtilityProcessHost::Client::MetafileAvailable(
- const base::FilePath& metafile_path,
- int highest_rendered_page_number,
- double scale_factor) {
- // The metafile was created in a temp folder which needs to get deleted after
- // we have processed it.
- base::ScopedTempDir scratch_metafile_dir;
- if (!scratch_metafile_dir.Set(metafile_path.DirName()))
- LOG(WARNING) << "Unable to set scratch metafile directory";
-#if defined(OS_WIN)
- // It's important that metafile is declared after scratch_metafile_dir so
- // that the metafile destructor closes the file before the base::ScopedTempDir
- // destructor tries to remove the directory.
- printing::Emf metafile;
- if (!metafile.InitFromFile(metafile_path)) {
- OnRenderPDFPagesToMetafileFailed();
- } else {
- OnRenderPDFPagesToMetafileSucceeded(metafile,
- highest_rendered_page_number,
- scale_factor);
- }
-#endif // defined(OS_WIN)
+void ServiceUtilityProcessHost::Client::MetafileAvailable(double scale_factor,
+ base::File file) {
+ file.Seek(base::File::FROM_BEGIN, 0);
+ int64 size = file.GetLength();
+ if (size <= 0)
+ return OnRenderPDFPagesToMetafileFailed();
+ std::vector<char> data(size);
+ if (file.ReadAtCurrentPos(&data[0], data.size()) != size)
+ return OnRenderPDFPagesToMetafileFailed();
+ printing::Emf emf;
+ if (!emf.InitFromData(&data[0], data.size()))
+ return OnRenderPDFPagesToMetafileFailed();
+ OnRenderPDFPagesToMetafilePageDone(scale_factor, emf);
}
-

Powered by Google App Engine
This is Rietveld 408576698