1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef CAST_RECEIVER_APPLICATION_AGENT_H_ 6*3f982cf4SFabien Sanglard #define CAST_RECEIVER_APPLICATION_AGENT_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <map> 9*3f982cf4SFabien Sanglard #include <memory> 10*3f982cf4SFabien Sanglard #include <string> 11*3f982cf4SFabien Sanglard #include <vector> 12*3f982cf4SFabien Sanglard 13*3f982cf4SFabien Sanglard #include "cast/common/channel/cast_socket_message_port.h" 14*3f982cf4SFabien Sanglard #include "cast/common/channel/connection_namespace_handler.h" 15*3f982cf4SFabien Sanglard #include "cast/common/channel/virtual_connection_router.h" 16*3f982cf4SFabien Sanglard #include "cast/common/public/cast_socket.h" 17*3f982cf4SFabien Sanglard #include "cast/receiver/channel/device_auth_namespace_handler.h" 18*3f982cf4SFabien Sanglard #include "cast/receiver/public/receiver_socket_factory.h" 19*3f982cf4SFabien Sanglard #include "platform/api/serial_delete_ptr.h" 20*3f982cf4SFabien Sanglard #include "platform/api/task_runner.h" 21*3f982cf4SFabien Sanglard #include "platform/base/error.h" 22*3f982cf4SFabien Sanglard #include "platform/base/ip_address.h" 23*3f982cf4SFabien Sanglard #include "util/json/json_value.h" 24*3f982cf4SFabien Sanglard 25*3f982cf4SFabien Sanglard namespace openscreen { 26*3f982cf4SFabien Sanglard namespace cast { 27*3f982cf4SFabien Sanglard 28*3f982cf4SFabien Sanglard class CastSocket; 29*3f982cf4SFabien Sanglard 30*3f982cf4SFabien Sanglard // A service accepting CastSocket connections, and providing a minimal 31*3f982cf4SFabien Sanglard // implementation of the CastV2 application control protocol to launch receiver 32*3f982cf4SFabien Sanglard // applications and route messages to/from them. 33*3f982cf4SFabien Sanglard // 34*3f982cf4SFabien Sanglard // Workflow: One or more Applications are registered under this ApplicationAgent 35*3f982cf4SFabien Sanglard // (e.g., a "mirroring" app). Later, a ReceiverSocketFactory (external to this 36*3f982cf4SFabien Sanglard // class) will listen and establish CastSocket connections, and then pass 37*3f982cf4SFabien Sanglard // CastSockets to this ApplicationAgent via the OnConnect() method. As each 38*3f982cf4SFabien Sanglard // connection is made, device authentication will take place. Then, Cast V2 39*3f982cf4SFabien Sanglard // application messages asking about application availability are received and 40*3f982cf4SFabien Sanglard // responded to, based on what Applications are registered. Finally, the remote 41*3f982cf4SFabien Sanglard // may request the LAUNCH of an Application (and later a STOP). 42*3f982cf4SFabien Sanglard // 43*3f982cf4SFabien Sanglard // In the meantime, this ApplicationAgent broadcasts RECEIVER_STATUS about what 44*3f982cf4SFabien Sanglard // application is running. In addition, it attempts to launch an "idle screen" 45*3f982cf4SFabien Sanglard // Application whenever no other Application is running. The "idle screen" 46*3f982cf4SFabien Sanglard // Application is usually some kind of screen saver or wallpaper/clock display. 47*3f982cf4SFabien Sanglard // Registering the "idle screen" Application is optional, and if it's not 48*3f982cf4SFabien Sanglard // registered, then nothing will be running during idle periods. 49*3f982cf4SFabien Sanglard class ApplicationAgent final 50*3f982cf4SFabien Sanglard : public ReceiverSocketFactory::Client, 51*3f982cf4SFabien Sanglard public CastMessageHandler, 52*3f982cf4SFabien Sanglard public ConnectionNamespaceHandler::VirtualConnectionPolicy, 53*3f982cf4SFabien Sanglard public VirtualConnectionRouter::SocketErrorHandler { 54*3f982cf4SFabien Sanglard public: 55*3f982cf4SFabien Sanglard class Application { 56*3f982cf4SFabien Sanglard public: 57*3f982cf4SFabien Sanglard // Returns the one or more application IDs that are supported. This list 58*3f982cf4SFabien Sanglard // must not mutate while the Application is registered. 59*3f982cf4SFabien Sanglard virtual const std::vector<std::string>& GetAppIds() const = 0; 60*3f982cf4SFabien Sanglard 61*3f982cf4SFabien Sanglard // Launches the application and returns true if successful. |app_id| is the 62*3f982cf4SFabien Sanglard // specific ID that was used to launch the app, and |app_params| is a 63*3f982cf4SFabien Sanglard // pass-through for any arbitrary app-specfic structure (or null if not 64*3f982cf4SFabien Sanglard // provided). If the Application wishes to send/receive messages, it uses 65*3f982cf4SFabien Sanglard // the provided |message_port| and must call MessagePort::SetClient() before 66*3f982cf4SFabien Sanglard // any flow will occur. 67*3f982cf4SFabien Sanglard virtual bool Launch(const std::string& app_id, 68*3f982cf4SFabien Sanglard const Json::Value& app_params, 69*3f982cf4SFabien Sanglard MessagePort* message_port) = 0; 70*3f982cf4SFabien Sanglard 71*3f982cf4SFabien Sanglard // These reflect the current state of the application, and the data is used 72*3f982cf4SFabien Sanglard // to populate RECEIVER_STATUS messages. 73*3f982cf4SFabien Sanglard virtual std::string GetSessionId() = 0; 74*3f982cf4SFabien Sanglard virtual std::string GetDisplayName() = 0; 75*3f982cf4SFabien Sanglard virtual std::vector<std::string> GetSupportedNamespaces() = 0; 76*3f982cf4SFabien Sanglard 77*3f982cf4SFabien Sanglard // Stops the application, if running. 78*3f982cf4SFabien Sanglard virtual void Stop() = 0; 79*3f982cf4SFabien Sanglard 80*3f982cf4SFabien Sanglard protected: 81*3f982cf4SFabien Sanglard virtual ~Application(); 82*3f982cf4SFabien Sanglard }; 83*3f982cf4SFabien Sanglard 84*3f982cf4SFabien Sanglard ApplicationAgent( 85*3f982cf4SFabien Sanglard TaskRunner* task_runner, 86*3f982cf4SFabien Sanglard DeviceAuthNamespaceHandler::CredentialsProvider* credentials_provider); 87*3f982cf4SFabien Sanglard 88*3f982cf4SFabien Sanglard ~ApplicationAgent() final; 89*3f982cf4SFabien Sanglard 90*3f982cf4SFabien Sanglard // Return the interface by which the CastSocket inbound traffic is delivered 91*3f982cf4SFabien Sanglard // into this agent and any running Applications. cast_socket_client()92*3f982cf4SFabien Sanglard CastSocket::Client* cast_socket_client() { return &router_; } 93*3f982cf4SFabien Sanglard 94*3f982cf4SFabien Sanglard // Registers an Application for launching by this agent. |app| must outlive 95*3f982cf4SFabien Sanglard // this ApplicationAgent, or until UnregisterApplication() is called. 96*3f982cf4SFabien Sanglard void RegisterApplication(Application* app, 97*3f982cf4SFabien Sanglard bool auto_launch_for_idle_screen = false); 98*3f982cf4SFabien Sanglard void UnregisterApplication(Application* app); 99*3f982cf4SFabien Sanglard 100*3f982cf4SFabien Sanglard // Stops the given |app| if it is the one currently running. This is used by 101*3f982cf4SFabien Sanglard // applications that encounter "exit" conditions where they need to STOP 102*3f982cf4SFabien Sanglard // (e.g., due to timeout of user activity, end of media playback, or fatal 103*3f982cf4SFabien Sanglard // errors). 104*3f982cf4SFabien Sanglard void StopApplicationIfRunning(Application* app); 105*3f982cf4SFabien Sanglard 106*3f982cf4SFabien Sanglard private: 107*3f982cf4SFabien Sanglard // ReceiverSocketFactory::Client overrides. 108*3f982cf4SFabien Sanglard void OnConnected(ReceiverSocketFactory* factory, 109*3f982cf4SFabien Sanglard const IPEndpoint& endpoint, 110*3f982cf4SFabien Sanglard std::unique_ptr<CastSocket> socket) final; 111*3f982cf4SFabien Sanglard void OnError(ReceiverSocketFactory* factory, Error error) final; 112*3f982cf4SFabien Sanglard 113*3f982cf4SFabien Sanglard // CastMessageHandler overrides. 114*3f982cf4SFabien Sanglard void OnMessage(VirtualConnectionRouter* router, 115*3f982cf4SFabien Sanglard CastSocket* socket, 116*3f982cf4SFabien Sanglard ::cast::channel::CastMessage message) final; 117*3f982cf4SFabien Sanglard 118*3f982cf4SFabien Sanglard // ConnectionNamespaceHandler::VirtualConnectionPolicy overrides. 119*3f982cf4SFabien Sanglard bool IsConnectionAllowed(const VirtualConnection& virtual_conn) const final; 120*3f982cf4SFabien Sanglard 121*3f982cf4SFabien Sanglard // VirtualConnectionRouter::SocketErrorHandler overrides. 122*3f982cf4SFabien Sanglard void OnClose(CastSocket* socket) final; 123*3f982cf4SFabien Sanglard void OnError(CastSocket* socket, Error error) final; 124*3f982cf4SFabien Sanglard 125*3f982cf4SFabien Sanglard // OnMessage() delegates to these to take action for each |request|. Each of 126*3f982cf4SFabien Sanglard // these returns a non-empty response message if a reply should be sent back 127*3f982cf4SFabien Sanglard // to the requestor. 128*3f982cf4SFabien Sanglard Json::Value HandlePing(); 129*3f982cf4SFabien Sanglard Json::Value HandleGetAppAvailability(const Json::Value& request); 130*3f982cf4SFabien Sanglard Json::Value HandleGetStatus(const Json::Value& request); 131*3f982cf4SFabien Sanglard Json::Value HandleLaunch(const Json::Value& request, CastSocket* socket); 132*3f982cf4SFabien Sanglard Json::Value HandleStop(const Json::Value& request); 133*3f982cf4SFabien Sanglard Json::Value HandleInvalidCommand(const Json::Value& request); 134*3f982cf4SFabien Sanglard 135*3f982cf4SFabien Sanglard // Stops the currently-running Application and attempts to launch the 136*3f982cf4SFabien Sanglard // Application referred to by |app_id|. If this fails, the "idle screen" 137*3f982cf4SFabien Sanglard // Application will be automatically launched as a failure fall-back. |socket| 138*3f982cf4SFabien Sanglard // is non-null only when the application switch was caused by a remote LAUNCH 139*3f982cf4SFabien Sanglard // request. 140*3f982cf4SFabien Sanglard Error SwitchToApplication(std::string app_id, 141*3f982cf4SFabien Sanglard const Json::Value& app_params, 142*3f982cf4SFabien Sanglard CastSocket* socket); 143*3f982cf4SFabien Sanglard 144*3f982cf4SFabien Sanglard // Stops the currently-running Application and launches the "idle screen." 145*3f982cf4SFabien Sanglard void GoIdle(); 146*3f982cf4SFabien Sanglard 147*3f982cf4SFabien Sanglard // Populates the given |message| object with the RECEIVER_STATUS fields, 148*3f982cf4SFabien Sanglard // reflecting the currently-launched app (if any), and a fake volume level 149*3f982cf4SFabien Sanglard // status. 150*3f982cf4SFabien Sanglard void PopulateReceiverStatus(Json::Value* message); 151*3f982cf4SFabien Sanglard 152*3f982cf4SFabien Sanglard // Broadcasts new RECEIVER_STATUS to all endpoints. This is called after an 153*3f982cf4SFabien Sanglard // Application LAUNCH or STOP. 154*3f982cf4SFabien Sanglard void BroadcastReceiverStatus(); 155*3f982cf4SFabien Sanglard 156*3f982cf4SFabien Sanglard TaskRunner* const task_runner_; 157*3f982cf4SFabien Sanglard DeviceAuthNamespaceHandler auth_handler_; 158*3f982cf4SFabien Sanglard VirtualConnectionRouter router_; 159*3f982cf4SFabien Sanglard ConnectionNamespaceHandler connection_handler_; 160*3f982cf4SFabien Sanglard 161*3f982cf4SFabien Sanglard std::map<std::string, Application*> registered_applications_; 162*3f982cf4SFabien Sanglard Application* idle_screen_app_ = nullptr; 163*3f982cf4SFabien Sanglard 164*3f982cf4SFabien Sanglard CastSocketMessagePort message_port_; 165*3f982cf4SFabien Sanglard Application* launched_app_ = nullptr; 166*3f982cf4SFabien Sanglard std::string launched_via_app_id_; 167*3f982cf4SFabien Sanglard }; 168*3f982cf4SFabien Sanglard 169*3f982cf4SFabien Sanglard } // namespace cast 170*3f982cf4SFabien Sanglard } // namespace openscreen 171*3f982cf4SFabien Sanglard 172*3f982cf4SFabien Sanglard #endif // CAST_RECEIVER_APPLICATION_AGENT_H_ 173