Home | History | Annotate | Download | only in service_process
      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_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_
      6 #define CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_
      7 
      8 #include <queue>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/callback.h"
     15 #include "base/cancelable_callback.h"
     16 #include "base/id_map.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/memory/singleton.h"
     19 #include "base/process/process.h"
     20 #include "content/public/browser/notification_observer.h"
     21 #include "content/public/browser/notification_registrar.h"
     22 #include "ipc/ipc_channel_proxy.h"
     23 #include "ipc/ipc_listener.h"
     24 #include "ipc/ipc_sender.h"
     25 
     26 namespace base {
     27 class CommandLine;
     28 }
     29 
     30 namespace cloud_print {
     31 struct CloudPrintProxyInfo;
     32 }  // namespace cloud_print
     33 
     34 // A ServiceProcessControl works as a portal between the service process and
     35 // the browser process.
     36 //
     37 // It is used to start and terminate the service process. It is also used
     38 // to send and receive IPC messages from the service process.
     39 //
     40 // THREADING
     41 //
     42 // This class is accessed on the UI thread through some UI actions. It then
     43 // talks to the IPC channel on the IO thread.
     44 class ServiceProcessControl : public IPC::Sender,
     45                               public IPC::Listener,
     46                               public content::NotificationObserver {
     47  public:
     48   enum ServiceProcessEvent {
     49     SERVICE_EVENT_INITIALIZE,
     50     SERVICE_EVENT_ENABLED_ON_LAUNCH,
     51     SERVICE_EVENT_ENABLE,
     52     SERVICE_EVENT_DISABLE,
     53     SERVICE_EVENT_DISABLE_BY_POLICY,
     54     SERVICE_EVENT_LAUNCH,
     55     SERVICE_EVENT_LAUNCHED,
     56     SERVICE_EVENT_LAUNCH_FAILED,
     57     SERVICE_EVENT_CHANNEL_CONNECTED,
     58     SERVICE_EVENT_CHANNEL_ERROR,
     59     SERVICE_EVENT_INFO_REQUEST,
     60     SERVICE_EVENT_INFO_REPLY,
     61     SERVICE_EVENT_HISTOGRAMS_REQUEST,
     62     SERVICE_EVENT_HISTOGRAMS_REPLY,
     63     SERVICE_PRINTERS_REQUEST,
     64     SERVICE_PRINTERS_REPLY,
     65     SERVICE_EVENT_MAX,
     66   };
     67 
     68   typedef IDMap<ServiceProcessControl>::iterator iterator;
     69   typedef std::queue<IPC::Message> MessageQueue;
     70   typedef base::Callback<void(const cloud_print::CloudPrintProxyInfo&)>
     71       CloudPrintProxyInfoCallback;
     72   typedef base::Callback<void(const std::vector<std::string>&)>
     73       PrintersCallback;
     74 
     75   // Returns the singleton instance of this class.
     76   static ServiceProcessControl* GetInstance();
     77 
     78   // Return true if this object is connected to the service.
     79   // Virtual for testing.
     80   virtual bool IsConnected() const;
     81 
     82   // If no service process is currently running, creates a new service process
     83   // and connects to it. If a service process is already running this method
     84   // will try to connect to it.
     85   // |success_task| is called when we have successfully launched the process
     86   // and connected to it.
     87   // |failure_task| is called when we failed to connect to the service process.
     88   // It is OK to pass the same value for |success_task| and |failure_task|. In
     89   // this case, the task is invoked on success or failure.
     90   // Note that if we are already connected to service process then
     91   // |success_task| can be invoked in the context of the Launch call.
     92   // Virtual for testing.
     93   virtual void Launch(const base::Closure& success_task,
     94                       const base::Closure& failure_task);
     95 
     96   // Disconnect the IPC channel from the service process.
     97   // Virtual for testing.
     98   virtual void Disconnect();
     99 
    100   // IPC::Listener implementation.
    101   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
    102   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
    103   virtual void OnChannelError() OVERRIDE;
    104 
    105   // IPC::Sender implementation
    106   virtual bool Send(IPC::Message* message) OVERRIDE;
    107 
    108   // content::NotificationObserver implementation.
    109   virtual void Observe(int type,
    110                        const content::NotificationSource& source,
    111                        const content::NotificationDetails& details) OVERRIDE;
    112 
    113   // Send a shutdown message to the service process. IPC channel will be
    114   // destroyed after calling this method.
    115   // Return true if the message was sent.
    116   // Virtual for testing.
    117   virtual bool Shutdown();
    118 
    119   // Send request for cloud print proxy info (enabled state, email, proxy id).
    120   // The callback gets the information when received.
    121   // Returns true if request was sent. Callback will be called only in case of
    122   // reply from service. The method resets any previous callback.
    123   // This call starts service if needed.
    124   bool GetCloudPrintProxyInfo(
    125       const CloudPrintProxyInfoCallback& cloud_print_status_callback);
    126 
    127   // Send request for histograms collected in service process.
    128   // Returns true if request was sent, and callback will be called in case of
    129   // success or timeout. The method resets any previous callback.
    130   // Returns false if service is not running or other failure, callback will not
    131   // be called in this case.
    132   bool GetHistograms(const base::Closure& cloud_print_status_callback,
    133                      const base::TimeDelta& timeout);
    134 
    135   // Send request for printers available for cloud print proxy.
    136   // The callback gets the information when received.
    137   // Returns true if request was sent. Callback will be called only in case of
    138   // reply from service. The method resets any previous callback.
    139   // This call starts service if needed.
    140   bool GetPrinters(const PrintersCallback& enumerate_printers_callback);
    141 
    142  private:
    143   // This class is responsible for launching the service process on the
    144   // PROCESS_LAUNCHER thread.
    145   class Launcher
    146       : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> {
    147    public:
    148     Launcher(ServiceProcessControl* process,
    149              scoped_ptr<base::CommandLine> cmd_line);
    150     // Execute the command line to start the process asynchronously. After the
    151     // command is executed |task| is called with the process handle on the UI
    152     // thread.
    153     void Run(const base::Closure& task);
    154 
    155     bool launched() const { return launched_; }
    156 
    157    private:
    158     friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>;
    159     virtual ~Launcher();
    160 
    161 #if !defined(OS_MACOSX)
    162     void DoDetectLaunched();
    163 #endif  // !OS_MACOSX
    164 
    165     void DoRun();
    166     void Notify();
    167     void CloseProcessHandle();
    168     ServiceProcessControl* process_;
    169     scoped_ptr<base::CommandLine> cmd_line_;
    170     base::Closure notify_task_;
    171     bool launched_;
    172     uint32 retry_count_;
    173     base::ProcessHandle process_handle_;
    174   };
    175 
    176   friend class MockServiceProcessControl;
    177   friend class CloudPrintProxyPolicyStartupTest;
    178 
    179   ServiceProcessControl();
    180   virtual ~ServiceProcessControl();
    181 
    182   friend struct DefaultSingletonTraits<ServiceProcessControl>;
    183 
    184   typedef std::vector<base::Closure> TaskList;
    185 
    186   // Message handlers
    187   void OnCloudPrintProxyInfo(
    188       const cloud_print::CloudPrintProxyInfo& proxy_info);
    189   void OnHistograms(const std::vector<std::string>& pickled_histograms);
    190   void OnPrinters(const std::vector<std::string>& printers);
    191 
    192   // Runs callback provided in |GetHistograms()|.
    193   void RunHistogramsCallback();
    194 
    195   // Helper method to invoke all the callbacks based on success or failure.
    196   void RunConnectDoneTasks();
    197 
    198   // Method called by Launcher when the service process is launched.
    199   void OnProcessLaunched();
    200 
    201   // Used internally to connect to the service process.
    202   void ConnectInternal();
    203 
    204   // Takes ownership of the pointer. Split out for testing.
    205   void SetChannel(scoped_ptr<IPC::ChannelProxy> channel);
    206 
    207   static void RunAllTasksHelper(TaskList* task_list);
    208 
    209   // IPC channel to the service process.
    210   scoped_ptr<IPC::ChannelProxy> channel_;
    211 
    212   // Service process launcher.
    213   scoped_refptr<Launcher> launcher_;
    214 
    215   // Callbacks that get invoked when the channel is successfully connected.
    216   TaskList connect_success_tasks_;
    217   // Callbacks that get invoked when there was a connection failure.
    218   TaskList connect_failure_tasks_;
    219 
    220   // Callback that gets invoked when a printers is received from
    221   // the cloud print proxy.
    222   PrintersCallback printers_callback_;
    223 
    224   // Callback that gets invoked when a status message is received from
    225   // the cloud print proxy.
    226   CloudPrintProxyInfoCallback cloud_print_info_callback_;
    227 
    228   // Callback that gets invoked when a message with histograms is received from
    229   // the service process.
    230   base::Closure histograms_callback_;
    231 
    232   content::NotificationRegistrar registrar_;
    233 
    234   // Callback that gets invoked if service didn't reply in time.
    235   base::CancelableClosure histograms_timeout_callback_;
    236 };
    237 
    238 #endif  // CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_
    239