Home | History | Annotate | Download | only in service
      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_SERVICE_PROCESS_CONTROL_H_
      6 #define CHROME_BROWSER_SERVICE_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/id_map.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/memory/singleton.h"
     18 #include "base/process/process.h"
     19 #include "content/public/browser/notification_observer.h"
     20 #include "content/public/browser/notification_registrar.h"
     21 #include "ipc/ipc_channel_proxy.h"
     22 #include "ipc/ipc_listener.h"
     23 #include "ipc/ipc_sender.h"
     24 
     25 class CommandLine;
     26 
     27 namespace cloud_print {
     28 struct CloudPrintProxyInfo;
     29 }  // namespace cloud_print
     30 
     31 // A ServiceProcessControl works as a portal between the service process and
     32 // the browser process.
     33 //
     34 // It is used to start and terminate the service process. It is also used
     35 // to send and receive IPC messages from the service process.
     36 //
     37 // THREADING
     38 //
     39 // This class is accessed on the UI thread through some UI actions. It then
     40 // talks to the IPC channel on the IO thread.
     41 class ServiceProcessControl : public IPC::Sender,
     42                               public IPC::Listener,
     43                               public content::NotificationObserver {
     44  public:
     45   typedef IDMap<ServiceProcessControl>::iterator iterator;
     46   typedef std::queue<IPC::Message> MessageQueue;
     47   typedef base::Callback<void(const cloud_print::CloudPrintProxyInfo&)>
     48       CloudPrintProxyInfoHandler;
     49 
     50   // Returns the singleton instance of this class.
     51   static ServiceProcessControl* GetInstance();
     52 
     53   // Return true if this object is connected to the service.
     54   // Virtual for testing.
     55   virtual bool IsConnected() const;
     56 
     57   // If no service process is currently running, creates a new service process
     58   // and connects to it. If a service process is already running this method
     59   // will try to connect to it.
     60   // |success_task| is called when we have successfully launched the process
     61   // and connected to it.
     62   // |failure_task| is called when we failed to connect to the service process.
     63   // It is OK to pass the same value for |success_task| and |failure_task|. In
     64   // this case, the task is invoked on success or failure.
     65   // Note that if we are already connected to service process then
     66   // |success_task| can be invoked in the context of the Launch call.
     67   // Virtual for testing.
     68   virtual void Launch(const base::Closure& success_task,
     69                       const base::Closure& failure_task);
     70 
     71   // Disconnect the IPC channel from the service process.
     72   // Virtual for testing.
     73   virtual void Disconnect();
     74 
     75   // IPC::Listener implementation.
     76   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
     77   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
     78   virtual void OnChannelError() OVERRIDE;
     79 
     80   // IPC::Sender implementation
     81   virtual bool Send(IPC::Message* message) OVERRIDE;
     82 
     83   // content::NotificationObserver implementation.
     84   virtual void Observe(int type,
     85                        const content::NotificationSource& source,
     86                        const content::NotificationDetails& details) OVERRIDE;
     87 
     88   // Message handlers
     89   void OnCloudPrintProxyInfo(
     90       const cloud_print::CloudPrintProxyInfo& proxy_info);
     91 
     92   // Send a shutdown message to the service process. IPC channel will be
     93   // destroyed after calling this method.
     94   // Return true if the message was sent.
     95   // Virtual for testing.
     96   virtual bool Shutdown();
     97 
     98   // Send request for cloud print proxy info (enabled state, email, proxy id).
     99   // The callback gets the information when received.
    100   bool GetCloudPrintProxyInfo(
    101       const CloudPrintProxyInfoHandler& cloud_print_status_callback);
    102 
    103  private:
    104   // This class is responsible for launching the service process on the
    105   // PROCESS_LAUNCHER thread.
    106   class Launcher
    107       : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> {
    108    public:
    109     Launcher(ServiceProcessControl* process, CommandLine* cmd_line);
    110     // Execute the command line to start the process asynchronously. After the
    111     // command is executed |task| is called with the process handle on the UI
    112     // thread.
    113     void Run(const base::Closure& task);
    114 
    115     bool launched() const { return launched_; }
    116 
    117    private:
    118     friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>;
    119     virtual ~Launcher();
    120 
    121 #if !defined(OS_MACOSX)
    122     void DoDetectLaunched();
    123 #endif  // !OS_MACOSX
    124 
    125     void DoRun();
    126     void Notify();
    127     ServiceProcessControl* process_;
    128     scoped_ptr<CommandLine> cmd_line_;
    129     base::Closure notify_task_;
    130     bool launched_;
    131     uint32 retry_count_;
    132   };
    133 
    134   friend class MockServiceProcessControl;
    135   friend class CloudPrintProxyPolicyStartupTest;
    136 
    137   ServiceProcessControl();
    138   virtual ~ServiceProcessControl();
    139 
    140   friend struct DefaultSingletonTraits<ServiceProcessControl>;
    141 
    142   typedef std::vector<base::Closure> TaskList;
    143 
    144   // Helper method to invoke all the callbacks based on success or failure.
    145   void RunConnectDoneTasks();
    146 
    147   // Method called by Launcher when the service process is launched.
    148   void OnProcessLaunched();
    149 
    150   // Used internally to connect to the service process.
    151   void ConnectInternal();
    152 
    153   // Takes ownership of the pointer. Split out for testing.
    154   void SetChannel(IPC::ChannelProxy* channel);
    155 
    156   static void RunAllTasksHelper(TaskList* task_list);
    157 
    158   // IPC channel to the service process.
    159   scoped_ptr<IPC::ChannelProxy> channel_;
    160 
    161   // Service process launcher.
    162   scoped_refptr<Launcher> launcher_;
    163 
    164   // Callbacks that get invoked when the channel is successfully connected.
    165   TaskList connect_success_tasks_;
    166   // Callbacks that get invoked when there was a connection failure.
    167   TaskList connect_failure_tasks_;
    168 
    169   // Callback that gets invoked when a status message is received from
    170   // the cloud print proxy.
    171   CloudPrintProxyInfoHandler cloud_print_info_callback_;
    172 
    173   content::NotificationRegistrar registrar_;
    174 };
    175 
    176 #endif  // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_
    177