Index: components/arc/arc_bridge_service.h |
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..586bad211e8a9827c2f8ae0a3fe7797ca2aa0fff |
--- /dev/null |
+++ b/components/arc/arc_bridge_service.h |
@@ -0,0 +1,192 @@ |
+// 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_BRIDGE_SERVICE_H_ |
+#define COMPONENTS_ARC_ARC_BRIDGE_SERVICE_H_ |
+ |
+#include "base/macros.h" |
+#include "base/observer_list_threadsafe.h" |
+#include "base/sequenced_task_runner.h" |
+#include "chromeos/dbus/dbus_method_call_status.h" |
+#include "components/keyed_service/core/keyed_service.h" |
+#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_listener.h" |
+#include "ipc/ipc_message.h" |
+ |
+class PrefRegistrySimple; |
+class PrefService; |
+ |
+namespace arc { |
+ |
+class ArcBridgeTest; |
+ |
+// The Chrome-side service that handles ARC instances and ARC bridge creation. |
+// This service handles the lifetime of ARC instances and sets up the |
+// communication channel (the ARC bridge) used to send and receive messages. |
+class ArcBridgeService : public KeyedService, |
+ public IPC::Listener { |
+ public: |
+ // The possible states of the bridge. In the normal flow, the state changes |
+ // in the following sequence: |
+ // |
+ // STOPPED |
+ // SetEnabled(true) + HandleStartup() -> SocketConnect() -> |
+ // CONNECTING |
+ // Connect() -> |
+ // CONNECTED |
+ // SocketConnectAfterSetsocketPermissions() -> |
+ // STARTING |
+ // StartInstance() -> OnInstanceReady() -> |
+ // READY |
+ // |
+ // When Shutdown() is called, the state changes depending on the state it was at: |
oshima
2015/11/02 19:13:49
80 chars. You may want to add presubmit check for
Luis Héctor Chávez
2015/11/04 17:49:18
Done.
|
+ // |
+ // CONNECTED/CONNECTING -> STOPPED |
+ // STARTING/READY -> STOPPING -> StopInstance() -> STOPPED |
+ enum State { |
+ // ARC is not currently running. |
+ STOPPED, |
+ |
+ // The request to connect has been sent. |
+ CONNECTING, |
+ |
+ // The bridge has connected to the socket, but has not started the ARC |
+ // instance. |
+ CONNECTED, |
+ |
+ // The ARC bridge has been set up and ARC is starting up. |
+ STARTING, |
+ |
+ // The ARC instance has been fully initialized and is now ready for user |
+ // interaction. |
+ READY, |
+ |
+ // The ARC instance has started shutting down. |
+ STOPPING, |
+ }; |
+ |
+ class Observer { |
+ public: |
+ // Called whenever the state of the bridge has changed. |
+ virtual void OnStateChanged(State state) {} |
+ |
+ // Called whenever ARC's enabled status has changed for this session. |
+ virtual void OnEnabledChanged(bool enabled) {} |
+ |
+ protected: |
+ virtual ~Observer() {} |
+ }; |
+ |
+ explicit ArcBridgeService( |
+ const scoped_refptr<base::SequencedTaskRunner>& file_task_runner); |
+ virtual ~ArcBridgeService(); |
+ |
+ // Registers ARC preferences. |
+ static void RegisterPrefs(PrefRegistrySimple* registry); |
+ |
+ // Reads from the preference store if ARC has been enabled. |
+ static bool GetEnabledPref(PrefService* pref_service); |
+ |
+ // HandleStartup() should be called upon profile startup. This will only |
+ // launch an instance if the instance service is available and it is enabled. |
+ void HandleStartup(); |
+ |
+ // Shuts down the running instance, if any. This is safe to call even if |
+ // there is no instance running. |
+ void Shutdown(); |
+ |
+ // Adds or removes observers. |
+ void AddObserver(Observer* observer); |
+ void RemoveObserver(Observer* observer); |
+ |
+ // Gets the current state of the bridge service. |
+ State GetState() const { return state_; } |
+ |
+ // Enables or disables the bridge for this session. |
+ void SetEnabled(bool enabled); |
+ |
+ // Gets if the bridge is enabled for this session. |
+ bool IsEnabled() const { return enabled_; } |
+ |
+ // Requests registration of an input device on the ARC instance. |
+ // TODO(denniskempin): Make this interface more typesafe. |
+ // |name| should be the displayable name of the emulated device (e.g. "Chrome |
+ // OS Keyboard"), |device_type| the name of the device type (e.g. "keyboard") |
+ // and |fd| a file descriptor that emulates the kernel events of the device. |
+ bool RegisterInputDevice(const std::string& name, |
+ const std::string& device_type, |
+ base::ScopedFD fd); |
+ |
+ private: |
+ friend class arc::ArcBridgeTest; |
+ |
+ // Binds to the socket specified by |socket_path|. |
+ void SocketConnect(const base::FilePath& socket_path); |
+ |
+ // Binds to the socket specified by |socket_path| after creating its parent |
+ // directory is present. |
+ void SocketConnectAfterEnsureParentDirectory( |
+ const base::FilePath& socket_path, bool directory_present); |
+ |
+ // Internal connection method. Separated to make testing easier. |
+ bool Connect(const IPC::ChannelHandle& handle, IPC::Channel::Mode mode); |
+ |
+ // Finishes connecting after setting socket permissions. |
+ void SocketConnectAfterSetSocketPermissions(const base::FilePath& socket_path, |
+ bool socket_permissions_success); |
+ |
+ // Called when the ARC instance has finished setting up and is ready for user |
+ // interaction. |
+ void OnInstanceReady(); |
+ |
+ // Changes the current state and notify all observers. |
+ void SetState(State state); |
+ |
+ // IPC::Listener: |
+ bool OnMessageReceived(const IPC::Message& message) override; |
+ |
+ // DBus callbacks. |
+ void OnInstanceStarted(chromeos::DBusMethodCallStatus status); |
+ void OnInstanceStopped(chromeos::DBusMethodCallStatus status); |
+ |
+ // Thread in which IPC messaging is performed. |
+ base::Thread ipc_thread_; |
+ |
+ // Task runner on which incoming messages are handled. |
+ scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; |
+ |
+ // Task runner on which file operations are performed. |
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_; |
+ |
+ // The channel through which messages are sent. |
+ scoped_ptr<IPC::ChannelProxy> ipc_channel_; |
+ |
+ // A Lock that guards the |ipc_channel_|. Most of the methods are expected |
+ // to be run in the same thread (the one in which the ArcBridgeService |
+ // instance was created), but all the ones that send IPC messages can be |
+ // called from any method. This will prevent the |ipc_channel_| from being |
+ // destroyed while a message is being sent. |
+ base::Lock ipc_channel_lock_; |
+ |
+ // List of observers to notify of state changes. |
+ scoped_refptr<base::ObserverListThreadSafe<Observer>> observer_list_; |
+ |
+ // If the ARC instance service is available. |
+ bool available_; |
+ |
+ // If ARC has been enabled by policy and user choice. |
+ bool enabled_; |
+ |
+ // The current state of the bridge. |
+ ArcBridgeService::State state_; |
+ |
+ // WeakPtrFactory to use callbacks. |
+ base::WeakPtrFactory<ArcBridgeService> weak_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ArcBridgeService); |
+}; |
+ |
+} // namespace arc |
+ |
+#endif // COMPONENTS_ARC_ARC_BRIDGE_SERVICE_H_ |