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 <memory>
9 #include <string>
10 
11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/weak_ptr.h"
14 #include "chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom.h"
15 #include "content/public/common/child_process_host_delegate.h"
16 #include "ipc/ipc_platform_file.h"
17 #include "mojo/public/cpp/bindings/pending_remote.h"
18 
19 namespace base {
20 class CommandLine;
21 class FilePath;
22 class SingleThreadTaskRunner;
23 }  // namespace base
24 
25 namespace content {
26 class ChildProcessHost;
27 }
28 
29 namespace printing {
30 class MetafilePlayer;
31 struct PdfRenderSettings;
32 struct PrinterCapsAndDefaults;
33 struct PrinterSemanticCapsAndDefaults;
34 }  // namespace printing
35 
36 // Acts as the service-side host to a utility child process. A
37 // utility process is a short-lived sandboxed process that is created to run
38 // a specific task.
39 // This class is expected to delete itself IFF one of its Start methods has been
40 // called.
41 class ServiceUtilityProcessHost : public content::ChildProcessHostDelegate {
42  public:
43   // Consumers of ServiceUtilityProcessHost must implement this interface to
44   // get results back.  All functions are called on the thread passed along
45   // to ServiceUtilityProcessHost.
46   class Client : public base::RefCountedThreadSafe<Client> {
47    public:
Client()48     Client() {}
49 
50     // Called when the child process died before a reply was receieved.
OnChildDied()51     virtual void OnChildDied() {}
52 
OnRenderPDFPagesToMetafilePageDone(float scale_factor,const printing::MetafilePlayer & emf)53     virtual void OnRenderPDFPagesToMetafilePageDone(
54         float scale_factor,
55         const printing::MetafilePlayer& emf) {}
56 
57     // Called when at all pages in the PDF has been rendered.
OnRenderPDFPagesToMetafileDone(bool success)58     virtual void OnRenderPDFPagesToMetafileDone(bool success) {}
59 
60     // Called when the printer capabilities and defaults have been
61     // retrieved successfully or if retrieval failed.
OnGetPrinterCapsAndDefaults(bool succedded,const std::string & printer_name,const printing::PrinterCapsAndDefaults & caps_and_defaults)62     virtual void OnGetPrinterCapsAndDefaults(
63         bool succedded,
64         const std::string& printer_name,
65         const printing::PrinterCapsAndDefaults& caps_and_defaults) {}
66 
67     // Called when the printer capabilities and defaults have been
68     // retrieved successfully or if retrieval failed.
OnGetPrinterSemanticCapsAndDefaults(bool succedded,const std::string & printer_name,const printing::PrinterSemanticCapsAndDefaults & caps_and_defaults)69     virtual void OnGetPrinterSemanticCapsAndDefaults(
70         bool succedded,
71         const std::string& printer_name,
72         const printing::PrinterSemanticCapsAndDefaults& caps_and_defaults) {}
73 
74    protected:
~Client()75     virtual ~Client() {}
76 
77    private:
78     friend class base::RefCountedThreadSafe<Client>;
79     friend class ServiceUtilityProcessHost;
80 
81     // Invoked when a metafile is ready.
82     // Returns true if metafile successfully loaded from |emf_region|.
83     bool MetafileAvailable(float scale_factor,
84                            base::ReadOnlySharedMemoryRegion emf_region);
85 
86     DISALLOW_COPY_AND_ASSIGN(Client);
87   };
88 
89   ServiceUtilityProcessHost(Client* client,
90                             base::SingleThreadTaskRunner* client_task_runner);
91   ~ServiceUtilityProcessHost() override;
92 
GetHost()93   content::ChildProcessHost* GetHost() { return child_process_host_.get(); }
94 
95   // Starts a process to render the specified pages in the given PDF file into
96   // a metafile. Currently only implemented for Windows. If the PDF has fewer
97   // pages than the specified page ranges, it will render as many as available.
98   bool StartRenderPDFPagesToMetafile(
99       const base::FilePath& pdf_path,
100       const printing::PdfRenderSettings& render_settings);
101 
102   // Starts a process to get capabilities and defaults for the specified
103   // printer. Used on Windows to isolate the service process from printer driver
104   // crashes by executing this in a separate process. The process does not run
105   // in a sandbox.
106   bool StartGetPrinterCapsAndDefaults(const std::string& printer_name);
107 
108   // Starts a process to get capabilities and defaults for the specified
109   // printer. Used on Windows to isolate the service process from printer driver
110   // crashes by executing this in a separate process. The process does not run
111   // in a sandbox. Returns result as printing::PrinterSemanticCapsAndDefaults.
112   bool StartGetPrinterSemanticCapsAndDefaults(const std::string& printer_name);
113 
114  protected:
115   bool Send(IPC::Message* msg);
116 
117   // Allows this method to be overridden for tests.
118   virtual base::FilePath GetUtilityProcessCmd();
119 
120   // ChildProcessHostDelegate implementation:
121   void OnChildDisconnected() override;
122   bool OnMessageReceived(const IPC::Message& message) override;
123   const base::Process& GetProcess() override;
124   void BindHostReceiver(mojo::GenericPendingReceiver receiver) override;
125 
126  private:
127   // Starts a process.  Returns true iff it succeeded.
128   bool StartProcess(bool sandbox);
129 
130   // Launch the child process synchronously.
131   bool Launch(base::CommandLine* cmd_line, bool sandbox);
132 
handle()133   base::ProcessHandle handle() const { return process_.Handle(); }
134 
135   void OnMetafileSpooled(bool success);
136   void OnPDFToEmfFinished(bool success);
137 
138   // PdfToEmfState callbacks:
139   void OnRenderPDFPagesToMetafilesPageCount(
140       mojo::PendingRemote<printing::mojom::PdfToEmfConverter> converter,
141       uint32_t page_count);
142   void OnRenderPDFPagesToMetafilesPageDone(
143       base::ReadOnlySharedMemoryRegion emf_region,
144       float scale_factor);
145 
146   // IPC Messages handlers:
147   void OnGetPrinterCapsAndDefaultsSucceeded(
148       const std::string& printer_name,
149       const printing::PrinterCapsAndDefaults& caps_and_defaults);
150   void OnGetPrinterCapsAndDefaultsFailed(const std::string& printer_name);
151   void OnGetPrinterSemanticCapsAndDefaultsSucceeded(
152       const std::string& printer_name,
153       const printing::PrinterSemanticCapsAndDefaults& caps_and_defaults);
154   void OnGetPrinterSemanticCapsAndDefaultsFailed(
155       const std::string& printer_name);
156 
157   std::unique_ptr<content::ChildProcessHost> child_process_host_;
158   base::Process process_;
159   // A pointer to our client interface, who will be informed of progress.
160   scoped_refptr<Client> client_;
161   scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
162   bool waiting_for_reply_;
163 
164   class PdfToEmfState;
165   std::unique_ptr<PdfToEmfState> pdf_to_emf_state_;
166 
167   base::WeakPtrFactory<ServiceUtilityProcessHost> weak_ptr_factory_{this};
168 
169   DISALLOW_COPY_AND_ASSIGN(ServiceUtilityProcessHost);
170 };
171 
172 #endif  // CHROME_SERVICE_SERVICE_UTILITY_PROCESS_HOST_H_
173