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
3// found in the LICENSE file.
4
5#ifndef CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
6#define CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
7
8#include "build/build_config.h"
9
10#include <string>
11#include <vector>
12
13#include "base/basictypes.h"
14#include "base/files/file_path.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/process/process.h"
18#include "content/public/common/child_process_host_delegate.h"
19#include "ipc/ipc_channel.h"
20#include "printing/pdf_render_settings.h"
21
22class CommandLine;
23
24namespace base {
25class MessageLoopProxy;
26class ScopedTempDir;
27}  // namespace base
28
29namespace content {
30class ChildProcessHost;
31}
32
33namespace printing {
34class Emf;
35struct PageRange;
36struct PrinterCapsAndDefaults;
37}  // namespace printing
38
39// Acts as the service-side host to a utility child process. A
40// utility process is a short-lived sandboxed process that is created to run
41// a specific task.
42class ServiceUtilityProcessHost : public content::ChildProcessHostDelegate {
43 public:
44  // Consumers of ServiceUtilityProcessHost must implement this interface to
45  // get results back.  All functions are called on the thread passed along
46  // to ServiceUtilityProcessHost.
47  class Client : public base::RefCountedThreadSafe<Client> {
48   public:
49    Client() {}
50
51    // Called when the child process died before a reply was receieved.
52    virtual void OnChildDied() {}
53
54    // Called when at least one page in the specified PDF has been rendered
55    // successfully into |metafile|.
56    virtual void OnRenderPDFPagesToMetafileSucceeded(
57        const printing::Emf& metafile,
58        int highest_rendered_page_number,
59        double scale_factor) {}
60    // Called when no page in the passed in PDF could be rendered.
61    virtual void OnRenderPDFPagesToMetafileFailed() {}
62
63    // Called when the printer capabilities and defaults have been
64    // retrieved successfully.
65    virtual void OnGetPrinterCapsAndDefaultsSucceeded(
66        const std::string& printer_name,
67        const printing::PrinterCapsAndDefaults& caps_and_defaults) {}
68
69    // Called when the printer capabilities and defaults could not be
70    // retrieved successfully.
71    virtual void OnGetPrinterCapsAndDefaultsFailed(
72        const std::string& printer_name) {}
73
74   protected:
75    virtual ~Client() {}
76
77   private:
78    friend class base::RefCountedThreadSafe<Client>;
79    friend class ServiceUtilityProcessHost;
80
81    // Invoked when a metafile file is ready.
82    void MetafileAvailable(const base::FilePath& metafile_path,
83                           int highest_rendered_page_number,
84                           double scale_factor);
85
86    DISALLOW_COPY_AND_ASSIGN(Client);
87  };
88
89  ServiceUtilityProcessHost(Client* client,
90                            base::MessageLoopProxy* client_message_loop_proxy);
91  virtual ~ServiceUtilityProcessHost();
92
93  // Starts a process to render the specified pages in the given PDF file into
94  // a metafile. Currently only implemented for Windows. If the PDF has fewer
95  // pages than the specified page ranges, it will render as many as available.
96  bool StartRenderPDFPagesToMetafile(
97      const base::FilePath& pdf_path,
98      const printing::PdfRenderSettings& render_settings,
99      const std::vector<printing::PageRange>& page_ranges);
100
101  // Starts a process to get capabilities and defaults for the specified
102  // printer. Used on Windows to isolate the service process from printer driver
103  // crashes by executing this in a separate process. The process does not run
104  // in a sandbox.
105  bool StartGetPrinterCapsAndDefaults(const std::string& printer_name);
106
107 protected:
108  // Allows this method to be overridden for tests.
109  virtual base::FilePath GetUtilityProcessCmd();
110
111  // ChildProcessHostDelegate implementation:
112  virtual void OnChildDisconnected() OVERRIDE;
113  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
114
115 private:
116  // Starts a process.  Returns true iff it succeeded. |exposed_dir| is the
117  // path to the exposed to the sandbox. This is ignored if |no_sandbox| is
118  // true.
119  bool StartProcess(bool no_sandbox, const base::FilePath& exposed_dir);
120
121  // Launch the child process synchronously.
122  // TODO(sanjeevr): Determine whether we need to make the launch asynchronous.
123  // |exposed_dir| is the path to tbe exposed to the sandbox. This is ignored
124  // if |no_sandbox| is true.
125  bool Launch(CommandLine* cmd_line,
126              bool no_sandbox,
127              const base::FilePath& exposed_dir);
128
129  base::ProcessHandle handle() const { return handle_; }
130
131  // Messages handlers:
132  void OnRenderPDFPagesToMetafileSucceeded(int highest_rendered_page_number,
133                                           double scale_factor);
134  void OnRenderPDFPagesToMetafileFailed();
135  void OnGetPrinterCapsAndDefaultsSucceeded(
136      const std::string& printer_name,
137      const printing::PrinterCapsAndDefaults& caps_and_defaults);
138  void OnGetPrinterCapsAndDefaultsFailed(const std::string& printer_name);
139
140  scoped_ptr<content::ChildProcessHost> child_process_host_;
141  base::ProcessHandle handle_;
142  // A pointer to our client interface, who will be informed of progress.
143  scoped_refptr<Client> client_;
144  scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy_;
145  bool waiting_for_reply_;
146  // The path to the temp file where the metafile will be written to.
147  base::FilePath metafile_path_;
148  // The temporary folder created for the metafile.
149  scoped_ptr<base::ScopedTempDir> scratch_metafile_dir_;
150  // Start time of operation.
151  base::Time start_time_;
152
153  DISALLOW_COPY_AND_ASSIGN(ServiceUtilityProcessHost);
154};
155
156#endif  // CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
157