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 CHROME_BROWSER_MEDIA_ROUTER_TEST_MEDIA_ROUTER_MOJO_TEST_H_ 6 #define CHROME_BROWSER_MEDIA_ROUTER_TEST_MEDIA_ROUTER_MOJO_TEST_H_ 7 8 #include <memory> 9 #include <string> 10 #include <utility> 11 #include <vector> 12 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "chrome/browser/media/router/event_page_request_manager.h" 16 #include "chrome/browser/media/router/mojo/media_router_mojo_impl.h" 17 #include "chrome/browser/media/router/test/provider_test_helpers.h" 18 #include "chrome/test/base/testing_profile.h" 19 #include "components/media_router/browser/test/mock_media_router.h" 20 #include "components/media_router/common/mojom/media_router.mojom.h" 21 #include "content/public/test/browser_task_environment.h" 22 #include "extensions/browser/event_page_tracker.h" 23 #include "extensions/common/extension.h" 24 #include "mojo/public/cpp/bindings/pending_receiver.h" 25 #include "mojo/public/cpp/bindings/pending_remote.h" 26 #include "mojo/public/cpp/bindings/receiver.h" 27 #include "mojo/public/cpp/bindings/receiver_set.h" 28 #include "testing/gmock/include/gmock/gmock.h" 29 #include "testing/gtest/include/gtest/gtest.h" 30 31 namespace media_router { 32 33 class MediaRouterMojoImpl; 34 35 // TODO(takumif): Move MockMediaRouteProvider into its own files. 36 class MockMediaRouteProvider : public mojom::MediaRouteProvider { 37 public: 38 using RouteCallback = 39 base::OnceCallback<void(const base::Optional<MediaRoute>&, 40 mojom::RoutePresentationConnectionPtr, 41 const base::Optional<std::string>&, 42 RouteRequestResult::ResultCode)>; 43 44 MockMediaRouteProvider(); 45 ~MockMediaRouteProvider() override; 46 CreateRoute(const std::string & source_urn,const std::string & sink_id,const std::string & presentation_id,const url::Origin & origin,int tab_id,base::TimeDelta timeout,bool incognito,CreateRouteCallback callback)47 void CreateRoute(const std::string& source_urn, 48 const std::string& sink_id, 49 const std::string& presentation_id, 50 const url::Origin& origin, 51 int tab_id, 52 base::TimeDelta timeout, 53 bool incognito, 54 CreateRouteCallback callback) override { 55 CreateRouteInternal(source_urn, sink_id, presentation_id, origin, tab_id, 56 timeout, incognito, callback); 57 } 58 MOCK_METHOD8(CreateRouteInternal, 59 void(const std::string& source_urn, 60 const std::string& sink_id, 61 const std::string& presentation_id, 62 const url::Origin& origin, 63 int tab_id, 64 base::TimeDelta timeout, 65 bool incognito, 66 CreateRouteCallback& callback)); JoinRoute(const std::string & source_urn,const std::string & presentation_id,const url::Origin & origin,int tab_id,base::TimeDelta timeout,bool incognito,JoinRouteCallback callback)67 void JoinRoute(const std::string& source_urn, 68 const std::string& presentation_id, 69 const url::Origin& origin, 70 int tab_id, 71 base::TimeDelta timeout, 72 bool incognito, 73 JoinRouteCallback callback) override { 74 JoinRouteInternal(source_urn, presentation_id, origin, tab_id, timeout, 75 incognito, callback); 76 } 77 MOCK_METHOD7(JoinRouteInternal, 78 void(const std::string& source_urn, 79 const std::string& presentation_id, 80 const url::Origin& origin, 81 int tab_id, 82 base::TimeDelta timeout, 83 bool incognito, 84 JoinRouteCallback& callback)); ConnectRouteByRouteId(const std::string & source_urn,const std::string & route_id,const std::string & presentation_id,const url::Origin & origin,int tab_id,base::TimeDelta timeout,bool incognito,JoinRouteCallback callback)85 void ConnectRouteByRouteId(const std::string& source_urn, 86 const std::string& route_id, 87 const std::string& presentation_id, 88 const url::Origin& origin, 89 int tab_id, 90 base::TimeDelta timeout, 91 bool incognito, 92 JoinRouteCallback callback) override { 93 ConnectRouteByRouteIdInternal(source_urn, route_id, presentation_id, origin, 94 tab_id, timeout, incognito, callback); 95 } 96 MOCK_METHOD8(ConnectRouteByRouteIdInternal, 97 void(const std::string& source_urn, 98 const std::string& route_id, 99 const std::string& presentation_id, 100 const url::Origin& origin, 101 int tab_id, 102 base::TimeDelta timeout, 103 bool incognito, 104 JoinRouteCallback& callback)); 105 MOCK_METHOD1(DetachRoute, void(const std::string& route_id)); TerminateRoute(const std::string & route_id,TerminateRouteCallback callback)106 void TerminateRoute(const std::string& route_id, 107 TerminateRouteCallback callback) override { 108 TerminateRouteInternal(route_id, callback); 109 } 110 MOCK_METHOD2(TerminateRouteInternal, 111 void(const std::string& route_id, 112 TerminateRouteCallback& callback)); 113 MOCK_METHOD1(StartObservingMediaSinks, void(const std::string& source)); 114 MOCK_METHOD1(StopObservingMediaSinks, void(const std::string& source)); 115 MOCK_METHOD2(SendRouteMessage, 116 void(const std::string& media_route_id, 117 const std::string& message)); 118 MOCK_METHOD2(SendRouteBinaryMessage, 119 void(const std::string& media_route_id, 120 const std::vector<uint8_t>& data)); 121 MOCK_METHOD1(StartListeningForRouteMessages, 122 void(const std::string& route_id)); 123 MOCK_METHOD1(StopListeningForRouteMessages, 124 void(const std::string& route_id)); 125 MOCK_METHOD1(OnPresentationSessionDetached, 126 void(const std::string& route_id)); 127 MOCK_METHOD1(StartObservingMediaRoutes, void(const std::string& source)); 128 MOCK_METHOD1(StopObservingMediaRoutes, void(const std::string& source)); 129 MOCK_METHOD0(EnableMdnsDiscovery, void()); 130 MOCK_METHOD1(UpdateMediaSinks, void(const std::string& source)); 131 MOCK_METHOD2(ProvideSinks, 132 void(const std::string&, const std::vector<MediaSinkInternal>&)); CreateMediaRouteController(const std::string & route_id,mojo::PendingReceiver<mojom::MediaController> media_controller,mojo::PendingRemote<mojom::MediaStatusObserver> observer,CreateMediaRouteControllerCallback callback)133 void CreateMediaRouteController( 134 const std::string& route_id, 135 mojo::PendingReceiver<mojom::MediaController> media_controller, 136 mojo::PendingRemote<mojom::MediaStatusObserver> observer, 137 CreateMediaRouteControllerCallback callback) override { 138 CreateMediaRouteControllerInternal(route_id, media_controller, observer, 139 callback); 140 } 141 MOCK_METHOD4( 142 CreateMediaRouteControllerInternal, 143 void(const std::string& route_id, 144 mojo::PendingReceiver<mojom::MediaController>& media_controller, 145 mojo::PendingRemote<mojom::MediaStatusObserver>& observer, 146 CreateMediaRouteControllerCallback& callback)); GetState(GetStateCallback callback)147 void GetState(GetStateCallback callback) override { 148 GetStateInternal(callback); 149 } 150 MOCK_METHOD1(GetStateInternal, void(const GetStateCallback& callback)); 151 152 // These methods execute the callbacks with the success or timeout result 153 // code. If the callback takes a route, the route set in SetRouteToReturn() is 154 // used. 155 void RouteRequestSuccess(RouteCallback& cb) const; 156 void RouteRequestTimeout(RouteCallback& cb) const; 157 void TerminateRouteSuccess(TerminateRouteCallback& cb) const; 158 void CreateMediaRouteControllerSuccess( 159 CreateMediaRouteControllerCallback& cb) const; 160 161 // Sets the route to pass into callbacks. 162 void SetRouteToReturn(const MediaRoute& route); 163 164 private: 165 // The route that is passed into callbacks. 166 base::Optional<MediaRoute> route_; 167 168 DISALLOW_COPY_AND_ASSIGN(MockMediaRouteProvider); 169 }; 170 171 class MockEventPageTracker : public extensions::EventPageTracker { 172 public: 173 MockEventPageTracker(); 174 ~MockEventPageTracker(); 175 176 MOCK_METHOD1(IsEventPageSuspended, bool(const std::string& extension_id)); 177 MOCK_METHOD2(WakeEventPage, 178 bool(const std::string& extension_id, 179 base::OnceCallback<void(bool)> callback)); 180 }; 181 182 class MockEventPageRequestManager : public EventPageRequestManager { 183 public: 184 static std::unique_ptr<KeyedService> Create(content::BrowserContext* context); 185 186 explicit MockEventPageRequestManager(content::BrowserContext* context); 187 ~MockEventPageRequestManager() override; 188 189 MOCK_METHOD1(SetExtensionId, void(const std::string& extension_id)); 190 void RunOrDefer(base::OnceClosure request, 191 MediaRouteProviderWakeReason wake_reason) override; 192 MOCK_METHOD2(RunOrDeferInternal, 193 void(base::OnceClosure& request, 194 MediaRouteProviderWakeReason wake_reason)); 195 MOCK_METHOD0(OnMojoConnectionsReady, void()); 196 MOCK_METHOD0(OnMojoConnectionError, void()); 197 198 private: 199 DISALLOW_COPY_AND_ASSIGN(MockEventPageRequestManager); 200 }; 201 202 class MockMediaStatusObserver : public mojom::MediaStatusObserver { 203 public: 204 explicit MockMediaStatusObserver( 205 mojo::PendingReceiver<mojom::MediaStatusObserver> receiver); 206 ~MockMediaStatusObserver() override; 207 208 MOCK_METHOD1(OnMediaStatusUpdated, void(mojom::MediaStatusPtr status)); 209 210 private: 211 mojo::Receiver<mojom::MediaStatusObserver> receiver_; 212 }; 213 214 class MockMediaController : public mojom::MediaController { 215 public: 216 MockMediaController(); 217 ~MockMediaController() override; 218 219 void Bind(mojo::PendingReceiver<mojom::MediaController> receiver); 220 mojo::PendingRemote<mojom::MediaController> BindInterfaceRemote(); 221 void CloseReceiver(); 222 223 MOCK_METHOD0(Play, void()); 224 MOCK_METHOD0(Pause, void()); 225 MOCK_METHOD1(SetMute, void(bool mute)); 226 MOCK_METHOD1(SetVolume, void(float volume)); 227 MOCK_METHOD1(Seek, void(base::TimeDelta time)); 228 MOCK_METHOD0(NextTrack, void()); 229 MOCK_METHOD0(PreviousTrack, void()); 230 231 private: 232 mojo::Receiver<mojom::MediaController> receiver_{this}; 233 }; 234 235 // Tests the API call flow between the MediaRouterMojoImpl and the Media Router 236 // Mojo service in both directions. 237 class MediaRouterMojoTest : public ::testing::Test { 238 public: 239 MediaRouterMojoTest(); 240 ~MediaRouterMojoTest() override; 241 242 protected: 243 void SetUp() override; 244 void TearDown() override; 245 246 // Creates a MediaRouterMojoImpl instance to be used for this test. 247 virtual std::unique_ptr<MediaRouterMojoImpl> CreateMediaRouter() = 0; 248 249 // Notify media router that the provider provides a route or a sink. 250 // Need to be called after the provider is registered. 251 void ProvideTestRoute(MediaRouteProviderId provider_id, 252 const MediaRoute::Id& route_id); 253 void ProvideTestSink(MediaRouteProviderId provider_id, 254 const MediaSink::Id& sink_id); 255 256 // Register |mock_extension_provider_| or |mock_wired_display_provider_| with 257 // |media_router_|. 258 void RegisterExtensionProvider(); 259 void RegisterWiredDisplayProvider(); 260 261 // Tests that calling MediaRouter methods result in calls to corresponding 262 // MediaRouteProvider methods. 263 void TestCreateRoute(); 264 void TestJoinRoute(const std::string& presentation_id); 265 void TestConnectRouteByRouteId(); 266 void TestTerminateRoute(); 267 void TestSendRouteMessage(); 268 void TestSendRouteBinaryMessage(); 269 void TestDetachRoute(); 270 extension_id()271 const std::string& extension_id() const { return extension_->id(); } 272 router()273 MediaRouterMojoImpl* router() const { return media_router_.get(); } 274 profile()275 Profile* profile() { return &profile_; } 276 277 // Mock objects. 278 MockMediaRouteProvider mock_extension_provider_; 279 MockMediaRouteProvider mock_wired_display_provider_; 280 MockEventPageRequestManager* request_manager_ = nullptr; 281 282 private: 283 // Helper method for RegisterExtensionProvider() and 284 // RegisterWiredDisplayProvider(). 285 void RegisterMediaRouteProvider(mojom::MediaRouteProvider* provider, 286 MediaRouteProviderId provider_id); 287 288 content::BrowserTaskEnvironment task_environment_; 289 scoped_refptr<const extensions::Extension> extension_; 290 TestingProfile profile_; 291 std::unique_ptr<MediaRouterMojoImpl> media_router_; 292 mojo::ReceiverSet<mojom::MediaRouteProvider> provider_receivers_; 293 std::unique_ptr<MediaRoutesObserver> routes_observer_; 294 std::unique_ptr<MockMediaSinksObserver> sinks_observer_; 295 296 DISALLOW_COPY_AND_ASSIGN(MediaRouterMojoTest); 297 }; 298 299 // An object whose Invoke method can be passed as a MediaRouteResponseCallback. 300 class RouteResponseCallbackHandler { 301 public: 302 RouteResponseCallbackHandler(); 303 ~RouteResponseCallbackHandler(); 304 305 // Calls DoInvoke with the contents of |connection| and |result|. 306 void Invoke(mojom::RoutePresentationConnectionPtr connection, 307 const RouteRequestResult& result); 308 309 MOCK_METHOD5(DoInvoke, 310 void(const MediaRoute* route, 311 const std::string& presentation_id, 312 const std::string& error_text, 313 RouteRequestResult::ResultCode result_code, 314 mojom::RoutePresentationConnectionPtr& connection)); 315 316 private: 317 DISALLOW_COPY_AND_ASSIGN(RouteResponseCallbackHandler); 318 }; 319 320 } // namespace media_router 321 322 #endif // CHROME_BROWSER_MEDIA_ROUTER_TEST_MEDIA_ROUTER_MOJO_TEST_H_ 323