summaryrefslogtreecommitdiffstats
path: root/chrome/service
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-20 00:15:43 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-20 00:15:43 +0000
commit130954003bdd03f9c3ae563a2ed67466528e71c5 (patch)
treec59200233fd6fdaeec0c6279efa5fdba2493f402 /chrome/service
parent8a871374acb440a7d35a7b6c10840c7a2f712b65 (diff)
downloadchromium_src-130954003bdd03f9c3ae563a2ed67466528e71c5.zip
chromium_src-130954003bdd03f9c3ae563a2ed67466528e71c5.tar.gz
chromium_src-130954003bdd03f9c3ae563a2ed67466528e71c5.tar.bz2
Created a host for running the utility process as a child of the service process. This is used for rendering PDFs to a metafile in a sandbox for the Cloud Print proxy on Windows.
BUG=None TEST=Test Windows Cloud Print proxy Review URL: http://codereview.chromium.org/2917013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52970 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service')
-rw-r--r--chrome/service/service_child_process_host.cc33
-rw-r--r--chrome/service/service_child_process_host.h29
-rw-r--r--chrome/service/service_main.cc8
-rw-r--r--chrome/service/service_utility_process_host.cc147
-rw-r--r--chrome/service/service_utility_process_host.h120
5 files changed, 337 insertions, 0 deletions
diff --git a/chrome/service/service_child_process_host.cc b/chrome/service/service_child_process_host.cc
new file mode 100644
index 0000000..cea04fe
--- /dev/null
+++ b/chrome/service/service_child_process_host.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/service/service_child_process_host.h"
+
+#include "base/logging.h"
+#include "base/process_util.h"
+#include "chrome/common/result_codes.h"
+#if defined(OS_WIN)
+#include "chrome/common/sandbox_policy.h"
+#endif // defined(OS_WIN)
+
+ServiceChildProcessHost::ServiceChildProcessHost(ProcessType type)
+ : ChildProcessInfo(type, -1) {
+}
+
+ServiceChildProcessHost::~ServiceChildProcessHost() {
+ // We need to kill the child process when the host dies.
+ base::KillProcess(handle(), ResultCodes::NORMAL_EXIT, false);
+}
+
+bool ServiceChildProcessHost::Launch(CommandLine* cmd_line) {
+#if !defined(OS_WIN)
+ // TODO(sanjeevr): Implement for non-Windows OSes.
+ NOTIMPLEMENTED();
+ return false;
+#else // !defined(OS_WIN)
+ set_handle(sandbox::StartProcessWithAccess(cmd_line, FilePath()));
+ return (handle() != base::kNullProcessHandle);
+#endif // !defined(OS_WIN)
+}
+
diff --git a/chrome/service/service_child_process_host.h b/chrome/service/service_child_process_host.h
new file mode 100644
index 0000000..bfc833b
--- /dev/null
+++ b/chrome/service/service_child_process_host.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
+#define CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
+
+#include "base/process.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/child_process_info.h"
+
+
+// Plugins/workers and other child processes that live on the IO thread should
+// derive from this class.
+//
+class ServiceChildProcessHost : public ChildProcessHost,
+ public ChildProcessInfo {
+ public:
+ virtual ~ServiceChildProcessHost();
+
+ protected:
+ explicit ServiceChildProcessHost(ProcessType type);
+ // Derived classes call this to launch the child process synchronously.
+ // TODO(sanjeevr): Determine whether we need to make the launch asynchronous.
+ bool Launch(CommandLine* cmd_line);
+};
+
+#endif // CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_
+
diff --git a/chrome/service/service_main.cc b/chrome/service/service_main.cc
index a3fcd69..2f09489 100644
--- a/chrome/service/service_main.cc
+++ b/chrome/service/service_main.cc
@@ -9,6 +9,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/json_pref_store.h"
#include "chrome/common/main_function_params.h"
+#include "chrome/common/sandbox_policy.h"
#include "chrome/service/cloud_print/cloud_print_proxy.h"
#include "chrome/service/service_process.h"
@@ -33,6 +34,13 @@ int ServiceProcessMain(const MainFunctionParams& parameters) {
MessageLoopForUI main_message_loop;
PlatformThread::SetName("CrServiceMain");
+#if defined(OS_WIN)
+ sandbox::BrokerServices* broker_services =
+ parameters.sandbox_info_.BrokerServices();
+ if (broker_services)
+ sandbox::InitBrokerServices(broker_services);
+#endif // defined(OS_WIN)
+
ServiceProcess service_process;
service_process.Initialize();
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
new file mode 100644
index 0000000..e465eb2
--- /dev/null
+++ b/chrome/service/service_utility_process_host.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/service/service_utility_process_host.h"
+
+#include "app/app_switches.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/utility_messages.h"
+#include "gfx/rect.h"
+#include "ipc/ipc_switches.h"
+#include "printing/native_metafile.h"
+#include "printing/page_range.h"
+
+ServiceUtilityProcessHost::ServiceUtilityProcessHost(
+ Client* client, base::MessageLoopProxy* client_message_loop_proxy)
+ : ServiceChildProcessHost(ChildProcessInfo::UTILITY_PROCESS),
+ client_(client),
+ client_message_loop_proxy_(client_message_loop_proxy),
+ waiting_for_reply_(false) {
+}
+
+ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
+}
+
+bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
+ const FilePath& pdf_path,
+ const gfx::Rect& render_area,
+ int render_dpi,
+ const std::vector<printing::PageRange>& page_ranges) {
+#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)
+ if (!StartProcess())
+ return false;
+
+ ScopedHandle pdf_file(
+ ::CreateFile(pdf_path.value().c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL));
+ if (pdf_file == INVALID_HANDLE_VALUE)
+ return false;
+ HANDLE pdf_file_in_utility_process = NULL;
+ ::DuplicateHandle(::GetCurrentProcess(), pdf_file, handle(),
+ &pdf_file_in_utility_process, 0, false,
+ DUPLICATE_SAME_ACCESS);
+ if (!pdf_file_in_utility_process)
+ return false;
+ waiting_for_reply_ = true;
+ return SendOnChannel(
+ new UtilityMsg_RenderPDFPagesToMetafile(pdf_file_in_utility_process,
+ render_area,
+ render_dpi,
+ page_ranges));
+#endif // !defined(OS_WIN)
+}
+
+bool ServiceUtilityProcessHost::StartProcess() {
+ // Name must be set or metrics_service will crash in any test which
+ // launches a UtilityProcessHost.
+ set_name(L"utility process");
+
+ if (!CreateChannel())
+ return false;
+
+ FilePath exe_path = GetUtilityProcessCmd();
+ if (exe_path.empty()) {
+ NOTREACHED() << "Unable to get utility process binary name.";
+ return false;
+ }
+
+ CommandLine cmd_line(exe_path);
+ cmd_line.AppendSwitchWithValue(switches::kProcessType,
+ switches::kUtilityProcess);
+ cmd_line.AppendSwitchWithValue(switches::kProcessChannelID,
+ ASCIIToWide(channel_id()));
+ cmd_line.AppendSwitch(switches::kLang);
+
+ return Launch(&cmd_line);
+}
+
+FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
+ return GetChildPath(true);
+}
+
+void ServiceUtilityProcessHost::OnChildDied() {
+ if (waiting_for_reply_) {
+ // If we are yet to receive a reply then notify the client that the
+ // child died.
+ client_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(client_.get(), &Client::OnChildDied));
+ }
+ // The base class implementation will delete |this|.
+ ServiceChildProcessHost::OnChildDied();
+}
+
+void ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
+ bool msg_is_ok = false;
+ IPC_BEGIN_MESSAGE_MAP_EX(ServiceUtilityProcessHost, message, msg_is_ok)
+#if defined(OS_WIN) // This hack is Windows-specific.
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_PreCacheFont, OnPreCacheFont)
+#endif
+ IPC_MESSAGE_UNHANDLED(msg_is_ok__ = MessageForClient(message))
+ IPC_END_MESSAGE_MAP_EX()
+}
+
+bool ServiceUtilityProcessHost::MessageForClient(const IPC::Message& message) {
+ DCHECK(waiting_for_reply_);
+ bool ret = client_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(client_.get(), &Client::OnMessageReceived,
+ message));
+ waiting_for_reply_ = false;
+ return ret;
+}
+
+#if defined(OS_WIN) // This hack is Windows-specific.
+void ServiceUtilityProcessHost::OnPreCacheFont(LOGFONT font) {
+ PreCacheFont(font);
+}
+#endif // OS_WIN
+
+
+void ServiceUtilityProcessHost::Client::OnMessageReceived(
+ const IPC::Message& message) {
+ IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message)
+#if defined(OS_WIN)
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded,
+ Client::OnRenderPDFPagesToMetafileSucceeded)
+#endif // OS_WIN
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_RenderPDFPagesToMetafile_Failed,
+ Client::OnRenderPDFPagesToMetafileFailed)
+ IPC_END_MESSAGE_MAP_EX()
+}
+
diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h
new file mode 100644
index 0000000..7474c8eb
--- /dev/null
+++ b/chrome/service/service_utility_process_host.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
+#define CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif // defined(OS_WIN)
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/task.h"
+#include "ipc/ipc_channel.h"
+#include "chrome/service/service_child_process_host.h"
+#include "printing/native_metafile.h"
+
+class CommandLine;
+
+namespace base {
+class MessageLoopProxy;
+} // namespace base
+
+namespace gfx {
+class Rect;
+} // namespace gfx
+
+namespace printing {
+struct PageRange;
+} // namespace printing
+
+// Acts as the service-side host to a utility child process. A
+// utility process is a short-lived sandboxed process that is created to run
+// a specific task.
+class ServiceUtilityProcessHost : public ServiceChildProcessHost {
+ public:
+ // Consumers of ServiceUtilityProcessHost must implement this interface to
+ // get results back. All functions are called on the thread passed along
+ // to ServiceUtilityProcessHost.
+ class Client : public base::RefCountedThreadSafe<Client> {
+ public:
+ Client() {}
+
+ // Called when the child process died before a reply was receieved.
+ virtual void OnChildDied() {}
+
+ // Called when at least one page in the specified PDF has been rendered
+ // successfully into |metafile|.
+ virtual void OnRenderPDFPagesToMetafileSucceeded(
+ const printing::NativeMetafile& metafile,
+ int highest_rendered_page_number) {}
+ // Called when no page in the passed in PDF could be rendered.
+ virtual void OnRenderPDFPagesToMetafileFailed() {}
+
+ protected:
+ virtual ~Client() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<Client>;
+ friend class ServiceUtilityProcessHost;
+
+ void OnMessageReceived(const IPC::Message& message);
+
+ DISALLOW_COPY_AND_ASSIGN(Client);
+ };
+
+ ServiceUtilityProcessHost(Client* client,
+ base::MessageLoopProxy* client_message_loop_proxy);
+ virtual ~ServiceUtilityProcessHost();
+
+ // Starts a process to render the specified pages in the given PDF file into
+ // a metafile. Currently only implemented for Windows. If the PDF has fewer
+ // pages than the specified page ranges, it will render as many as available.
+ bool StartRenderPDFPagesToMetafile(
+ const FilePath& pdf_path,
+ const gfx::Rect& render_area,
+ int render_dpi,
+ const std::vector<printing::PageRange>& page_ranges);
+
+ // Since we handle a sync IPC message (UtilityHostMsg_PreCacheFont), we need
+ // an Send method.
+ bool Send(IPC::Message* message) {
+ return SendOnChannel(message);
+ }
+
+ protected:
+ // Allows this method to be overridden for tests.
+ virtual FilePath GetUtilityProcessCmd();
+
+ // Overriden from ChildProcessHost.
+ virtual bool CanShutdown() { return true; }
+ virtual void OnChildDied();
+
+ private:
+ // Starts a process. Returns true iff it succeeded.
+ bool StartProcess();
+
+ // IPC messages:
+ void OnMessageReceived(const IPC::Message& message);
+ bool MessageForClient(const IPC::Message& message);
+
+#if defined(OS_WIN) // This hack is Windows-specific.
+ void OnPreCacheFont(LOGFONT font);
+#endif // defined(OS_WIN)
+
+
+ // A pointer to our client interface, who will be informed of progress.
+ scoped_refptr<Client> client_;
+ scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy_;
+ bool waiting_for_reply_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceUtilityProcessHost);
+};
+
+#endif // CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
+