diff options
author | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-20 00:15:43 +0000 |
---|---|---|
committer | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-20 00:15:43 +0000 |
commit | 130954003bdd03f9c3ae563a2ed67466528e71c5 (patch) | |
tree | c59200233fd6fdaeec0c6279efa5fdba2493f402 /chrome/service | |
parent | 8a871374acb440a7d35a7b6c10840c7a2f712b65 (diff) | |
download | chromium_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.cc | 33 | ||||
-rw-r--r-- | chrome/service/service_child_process_host.h | 29 | ||||
-rw-r--r-- | chrome/service/service_main.cc | 8 | ||||
-rw-r--r-- | chrome/service/service_utility_process_host.cc | 147 | ||||
-rw-r--r-- | chrome/service/service_utility_process_host.h | 120 |
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_ + |