blob: 13bf3ea575ad2dfebe62737cef02fb4be5050747 [file] [log] [blame]
// Copyright 2015 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 COMPONENTS_ARC_ARC_SESSION_RUNNER_H_
#define COMPONENTS_ARC_ARC_SESSION_RUNNER_H_
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/arc/arc_session.h"
#include "components/arc/arc_stop_reason.h"
namespace arc {
// Accept requests to start/stop ARC instance. Also supports automatic
// restarting on unexpected ARC instance crash.
class ArcSessionRunner : public ArcSession::Observer,
public chromeos::SessionManagerClient::Observer {
public:
// Observer to notify events across multiple ARC session runs.
class Observer {
public:
// Called when ARC instance is stopped. If |restarting| is true, another
// ARC session is being restarted (practically after certain delay).
// Note: this is called once per ARC session, including unexpected
// CRASH on ARC container, and expected SHUTDOWN of ARC triggered by
// RequestStop(), so may be called multiple times for one RequestStart().
virtual void OnSessionStopped(ArcStopReason reason, bool restarting) = 0;
protected:
virtual ~Observer() = default;
};
// This is the factory interface to inject ArcSession instance
// for testing purpose.
using ArcSessionFactory = base::Callback<std::unique_ptr<ArcSession>()>;
explicit ArcSessionRunner(const ArcSessionFactory& factory);
~ArcSessionRunner() override;
// Add/Remove an observer.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Starts the ARC service, then it will connect the Mojo channel. When the
// bridge becomes ready, registered Observer's OnSessionReady() is called.
void RequestStart();
// Stops the ARC service.
// TODO(yusukes): Remove the parameter.
void RequestStop(bool always_stop_session);
// OnShutdown() should be called when the browser is shutting down. This can
// only be called on the thread that this class was created on. We assume that
// when this function is called, MessageLoop is no longer exists.
void OnShutdown();
// Returns whether currently ARC instance is running or stopped respectively.
// Note that, both can return false at same time when, e.g., starting
// or stopping ARC instance.
bool IsRunning() const;
bool IsStopped() const;
// Returns the current ArcSession instance for testing purpose.
ArcSession* GetArcSessionForTesting() { return arc_session_.get(); }
// Normally, automatic restarting happens after a short delay. When testing,
// however, we'd like it to happen immediately to avoid adding unnecessary
// delays.
void SetRestartDelayForTesting(const base::TimeDelta& restart_delay);
private:
// The possible states. In the normal flow, the state changes in the
// following sequence:
//
// STOPPED
// RequestStart() ->
// STARTING
// OnSessionReady() ->
// RUNNING
//
// The ArcSession state machine can be thought of being substates of
// ArcBridgeService's STARTING state.
// ArcBridgeService's state machine can be stopped at any phase.
//
// *
// RequestStop() ->
// STOPPING
// OnSessionStopped() ->
// STOPPED
enum class State {
// ARC instance is not currently running.
STOPPED,
// Request to start ARC instance for login screen is received. Starting an
// ARC instance.
STARTING_FOR_LOGIN_SCREEN,
// Request to start ARC instance is received. Starting an ARC instance.
STARTING,
// ARC instance has finished initializing, and is now ready for interaction
// with other services.
RUNNING,
// Request to stop ARC instance is recieved. Stopping the ARC instance.
STOPPING,
};
// Starts to run an ARC instance.
void StartArcSession();
// ArcSession::Observer:
void OnSessionReady() override;
void OnSessionStopped(ArcStopReason reason) override;
// chromeos::SessionManagerClient::Observer:
void EmitLoginPromptVisibleCalled() override;
THREAD_CHECKER(thread_checker_);
// Observers for the ARC instance state change events.
base::ObserverList<Observer> observer_list_;
// Whether a client requests to run session or not.
bool run_requested_ = false;
// Instead of immediately trying to restart the container, give it some time
// to finish tearing down in case it is still in the process of stopping.
base::TimeDelta restart_delay_;
base::OneShotTimer restart_timer_;
// Factory to inject a fake ArcSession instance for testing.
ArcSessionFactory factory_;
// Current runner's state.
State state_ = State::STOPPED;
// ArcSession object for currently running ARC instance. This should be
// nullptr if the state is STOPPED, otherwise non-nullptr.
std::unique_ptr<ArcSession> arc_session_;
// WeakPtrFactory to use callbacks.
base::WeakPtrFactory<ArcSessionRunner> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcSessionRunner);
};
} // namespace arc
#endif // COMPONENTS_ARC_ARC_SESSION_RUNNER_H_