// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_
#define CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_
#include <queue>
#include <set>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/id_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
#include "base/task.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "ipc/ipc_sync_channel.h"
class Profile;
class CommandLine;
namespace remoting {
struct ChromotingHostInfo;
} // namespace remoting
// A ServiceProcessControl works as a portal between the service process and
// the browser process.
//
// It is used to start and terminate the service process. It is also used
// to send and receive IPC messages from the service process.
//
// THREADING
//
// This class is accessed on the UI thread through some UI actions. It then
// talks to the IPC channel on the IO thread.
class ServiceProcessControl : public IPC::Channel::Sender,
public IPC::Channel::Listener,
public NotificationObserver {
public:
typedef IDMap<ServiceProcessControl>::iterator iterator;
typedef std::queue<IPC::Message> MessageQueue;
typedef Callback1<const remoting::ChromotingHostInfo&>::Type
RemotingHostStatusHandler;
// An interface for handling messages received from the service process.
class MessageHandler {
public:
virtual ~MessageHandler() {}
// Called when we receive reply to remoting host status request.
virtual void OnRemotingHostInfo(
const remoting::ChromotingHostInfo& host_info) = 0;
};
// Construct a ServiceProcessControl with |profile|..
explicit ServiceProcessControl(Profile* profile);
virtual ~ServiceProcessControl();
// Return the user profile associated with this service process.
Profile* profile() const { return profile_; }
// Return true if this object is connected to the service.
bool is_connected() const { return channel_.get() != NULL; }
// If no service process is currently running, creates a new service process
// and connects to it.
// If a service process is already running this method will try to connect
// to it.
// |success_task| is called when we have successfully launched the process
// and connected to it.
// |failure_task| is called when we failed to connect to the service process.
// It is OK to pass the same value for |success_task| and |failure_task|. In
// this case, the task is invoked on success or failure.
// Note that if we are already connected to service process then
// |success_task| can be invoked in the context of the Launch call.
// Takes ownership of |success_task| and |failure_task|.
void Launch(Task* success_task, Task* failure_task);
// IPC::Channel::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message);
virtual void OnChannelConnected(int32 peer_pid);
virtual void OnChannelError();
// IPC::Channel::Sender implementation
virtual bool Send(IPC::Message* message);
// NotificationObserver implementation.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
// Message handlers
void OnCloudPrintProxyIsEnabled(bool enabled, std::string email);
void OnRemotingHostInfo(const remoting::ChromotingHostInfo& host_info);
// Send a shutdown message to the service process. IPC channel will be
// destroyed after calling this method.
// Return true if the message was sent.
bool Shutdown();
// Send request for cloud print proxy status and the registered
// email address. The callback gets the information when received.
bool GetCloudPrintProxyStatus(
Callback2<bool, std::string>::Type* cloud_print_status_callback);
// Send a message to enable the remoting service in the service process.
// Return true if the message was sent.
bool SetRemotingHostCredentials(const std::string& user,
const std::string& auth_token);
bool EnableRemotingHost();
bool DisableRemotingHost();
// Send request for current status of the remoting service.
// MessageHandler::OnRemotingHostInfo() will be called when remoting host
// status is available.
bool RequestRemotingHostStatus();
// Add a message handler for receiving messages from the service
// process.
void AddMessageHandler(MessageHandler* message_handler);
// Remove a message handler from the list of message handlers. Must
// not be called from a message handler (i.e. while a message is
// being processed).
void RemoveMessageHandler(MessageHandler* message_handler);
private:
// This class is responsible for launching the service process on the
// PROCESS_LAUNCHER thread.
class Launcher
: public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> {
public:
Launcher(ServiceProcessControl* process, CommandLine* cmd_line);
// Execute the command line to start the process asynchronously.
// After the comamnd is executed |task| is called with the process handle on
// the UI thread.
void Run(Task* task);
bool launched() const { return launched_; }
private:
friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>;
virtual ~Launcher();
#if !defined(OS_MACOSX)
void DoDetectLaunched();
#endif // !OS_MACOSX
void DoRun();
void Notify();
ServiceProcessControl* process_;
scoped_ptr<CommandLine> cmd_line_;
scoped_ptr<Task> notify_task_;
bool launched_;
uint32 retry_count_;
};
typedef std::vector<Task*> TaskList;
// Helper method to invoke all the callbacks based on success on failure.
void RunConnectDoneTasks();
// Method called by Launcher when the service process is launched.
void OnProcessLaunched();
// Used internally to connect to the service process.
void ConnectInternal();
static void RunAllTasksHelper(TaskList* task_list);
Profile* profile_;
// IPC channel to the service process.
scoped_ptr<IPC::SyncChannel> channel_;
// Service process launcher.
scoped_refptr<Launcher> launcher_;
// Callbacks that get invoked when the channel is successfully connected or
// if there was a failure in connecting.
TaskList connect_done_tasks_;
// Callbacks that get invoked ONLY when the channel is successfully connected.
TaskList connect_success_tasks_;
// Callbacks that get invoked ONLY when there was a connection failure.
TaskList connect_failure_tasks_;
// Callback that gets invoked when a status message is received from
// the cloud print proxy.
scoped_ptr<Callback2<bool, std::string>::Type> cloud_print_status_callback_;
// Handler for messages from service process.
std::set<MessageHandler*> message_handlers_;
NotificationRegistrar registrar_;
};
#endif // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_