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