1 // Copyright 2015 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 COMPONENTS_MEDIA_ROUTER_BROWSER_ANDROID_MEDIA_ROUTER_ANDROID_H_
6 #define COMPONENTS_MEDIA_ROUTER_BROWSER_ANDROID_MEDIA_ROUTER_ANDROID_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <unordered_map>
12 
13 #include "base/containers/id_map.h"
14 #include "base/macros.h"
15 #include "base/observer_list.h"
16 #include "components/media_router/browser/android/media_router_android_bridge.h"
17 #include "components/media_router/browser/media_router_base.h"
18 #include "mojo/public/cpp/bindings/pending_remote.h"
19 #include "mojo/public/cpp/bindings/receiver.h"
20 #include "mojo/public/cpp/bindings/remote.h"
21 
22 namespace media_router {
23 
24 // An implementation of MediaRouter interface on Android.
25 class MediaRouterAndroid : public MediaRouterBase {
26  public:
27   MediaRouterAndroid();
28   ~MediaRouterAndroid() override;
29 
30   const MediaRoute* FindRouteBySource(const MediaSource::Id& source_id) const;
31 
32   // MediaRouter implementation.
33   void CreateRoute(const MediaSource::Id& source_id,
34                    const MediaSink::Id& sink_id,
35                    const url::Origin& origin,
36                    content::WebContents* web_contents,
37                    MediaRouteResponseCallback callback,
38                    base::TimeDelta timeout,
39                    bool incognito) override;
40   void JoinRoute(const MediaSource::Id& source,
41                  const std::string& presentation_id,
42                  const url::Origin& origin,
43                  content::WebContents* web_contents,
44                  MediaRouteResponseCallback callback,
45                  base::TimeDelta timeout,
46                  bool incognito) override;
47   void ConnectRouteByRouteId(const MediaSource::Id& source,
48                              const MediaRoute::Id& route_id,
49                              const url::Origin& origin,
50                              content::WebContents* web_contents,
51                              MediaRouteResponseCallback callback,
52                              base::TimeDelta timeout,
53                              bool incognito) override;
54   void DetachRoute(const MediaRoute::Id& route_id) override;
55   void TerminateRoute(const MediaRoute::Id& route_id) override;
56   void SendRouteMessage(const MediaRoute::Id& route_id,
57                         const std::string& message) override;
58   void SendRouteBinaryMessage(
59       const MediaRoute::Id& route_id,
60       std::unique_ptr<std::vector<uint8_t>> data) override;
61   void OnUserGesture() override;
62   std::unique_ptr<media::FlingingController> GetFlingingController(
63       const MediaRoute::Id& route_id) override;
64 
65   // The methods called by the Java bridge.
66   // Notifies the media router that information about sinks is received for
67   // a specific source id.
68   void OnSinksReceived(const MediaSource::Id& source_id,
69                        const std::vector<MediaSink>& sinks);
70 
71   // Notifies the media router about a successful route creation.
72   void OnRouteCreated(const MediaRoute::Id& route_id,
73                       const MediaSink::Id& sink_id,
74                       int request_id,
75                       bool is_local);
76 
77   // Notifies the media router that route creation or joining failed.
78   void OnRouteRequestError(const std::string& error_text, int request_id);
79 
80   // Notifies the media router when the route was terminated.
81   void OnRouteTerminated(const MediaRoute::Id& route_id);
82 
83   // Notifies the media router when the route was closed with an optional error.
84   // Null error indicates no error.
85   void OnRouteClosed(const MediaRoute::Id& route_id,
86                      const base::Optional<std::string>& error);
87 
88   // Notifies the media router about a message received from the media route.
89   void OnMessage(const MediaRoute::Id& route_id, const std::string& message);
90 
91  private:
92   friend class MediaRouterAndroidTest;
93 
94   // This class bridges messages between MediaRouterAndroid's messages API and a
95   // PresentationConnection.
96   class PresentationConnectionProxy final
97       : public blink::mojom::PresentationConnection {
98    public:
99     using OnMessageCallback = base::OnceCallback<void(bool)>;
100 
101     PresentationConnectionProxy(MediaRouterAndroid* media_router_android,
102                                 const MediaRoute::Id& route_id);
103     ~PresentationConnectionProxy() override;
104 
105     // Initializes the connection binding and interface request and returns that
106     // as a mojom::RoutePresentationConnectionPtr.
107     mojom::RoutePresentationConnectionPtr Init();
108 
109     // blink::mojom::PresentationConnection overrides.
110     void OnMessage(
111         blink::mojom::PresentationConnectionMessagePtr message) override;
DidChangeState(blink::mojom::PresentationConnectionState state)112     void DidChangeState(
113         blink::mojom::PresentationConnectionState state) override {}
114     // Destroys |this| by removing it from MediaRouterAndroid's collection.
115     void DidClose(
116         blink::mojom::PresentationConnectionCloseReason reason) override;
117 
118     // Sends a text message back to router's peer for this connection (|peer_|).
119     void SendMessage(const std::string& message);
120 
121     // Sends a TERMINATED state change message directly via |peer_|.
122     void Terminate();
123 
124    private:
125     mojo::PendingRemote<blink::mojom::PresentationConnection> Bind();
126 
127     mojo::Remote<blink::mojom::PresentationConnection> peer_;
128     mojo::Receiver<blink::mojom::PresentationConnection> receiver_{this};
129     // |media_router_android_| owns |this|, so it will outlive |this|.
130     MediaRouterAndroid* media_router_android_;
131     MediaRoute::Id route_id_;
132 
133     DISALLOW_COPY_AND_ASSIGN(PresentationConnectionProxy);
134   };
135 
136   // Removes the route with the given id from |active_routes_| and updates the
137   // registered route observers.
138   void RemoveRoute(const MediaRoute::Id& route_id);
139 
140   // MediaRouter implementation.
141   bool RegisterMediaSinksObserver(MediaSinksObserver* observer) override;
142   void UnregisterMediaSinksObserver(MediaSinksObserver* observer) override;
143   void RegisterMediaRoutesObserver(MediaRoutesObserver* observer) override;
144   void UnregisterMediaRoutesObserver(MediaRoutesObserver* observer) override;
145   void RegisterRouteMessageObserver(RouteMessageObserver* observer) override;
146   void UnregisterRouteMessageObserver(RouteMessageObserver* observer) override;
147 
148   void OnPresentationConnectionError(const std::string& route_id);
149 
SetMediaRouterBridgeForTest(MediaRouterAndroidBridge * bridge)150   void SetMediaRouterBridgeForTest(MediaRouterAndroidBridge* bridge) {
151     bridge_.reset(bridge);
152   }
153 
154   std::unique_ptr<MediaRouterAndroidBridge> bridge_;
155 
156   using MediaSinksObserverList =
157       base::ObserverList<MediaSinksObserver>::Unchecked;
158   using MediaSinkObservers =
159       std::unordered_map<MediaSource::Id,
160                          std::unique_ptr<MediaSinksObserverList>>;
161   MediaSinkObservers sinks_observers_;
162 
163   base::ObserverList<MediaRoutesObserver>::Unchecked routes_observers_;
164 
165   struct MediaRouteRequest {
166     MediaRouteRequest(const MediaSource& source,
167                       const std::string& presentation_id,
168                       MediaRouteResponseCallback callback);
169     ~MediaRouteRequest();
170 
171     MediaSource media_source;
172     std::string presentation_id;
173     MediaRouteResponseCallback callback;
174   };
175 
176   using MediaRouteRequests = base::IDMap<std::unique_ptr<MediaRouteRequest>>;
177   MediaRouteRequests route_requests_;
178 
179   using MediaRoutes = std::vector<MediaRoute>;
180   MediaRoutes active_routes_;
181 
182   std::unordered_map<MediaRoute::Id,
183                      std::vector<std::unique_ptr<PresentationConnectionProxy>>>
184       presentation_connections_;
185 
186   DISALLOW_COPY_AND_ASSIGN(MediaRouterAndroid);
187 };
188 
189 }  // namespace media_router
190 
191 #endif  // COMPONENTS_MEDIA_ROUTER_BROWSER_ANDROID_MEDIA_ROUTER_ANDROID_H_
192