| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 #include "media/remoting/remoting_renderer_controller.h" | |
| 6 | |
| 7 #include "base/callback.h" | |
| 8 #include "base/memory/ptr_util.h" | |
| 9 #include "base/message_loop/message_loop.h" | |
| 10 #include "base/run_loop.h" | |
| 11 #include "media/base/audio_decoder_config.h" | |
| 12 #include "media/base/cdm_config.h" | |
| 13 #include "media/base/limits.h" | |
| 14 #include "media/base/media_util.h" | |
| 15 #include "media/base/test_helpers.h" | |
| 16 #include "media/base/video_decoder_config.h" | |
| 17 #include "media/remoting/fake_remoting_controller.h" | |
| 18 #include "media/remoting/remoting_cdm.h" | |
| 19 #include "mojo/public/cpp/bindings/strong_binding.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 | |
| 22 namespace media { | |
| 23 namespace { | |
| 24 | |
| 25 constexpr mojom::RemotingSinkCapabilities kAllCapabilities = | |
| 26 mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING; | |
| 27 | |
| 28 PipelineMetadata DefaultMetadata() { | |
| 29 PipelineMetadata data; | |
| 30 data.has_audio = true; | |
| 31 data.has_video = true; | |
| 32 data.video_decoder_config = TestVideoConfig::Normal(); | |
| 33 return data; | |
| 34 } | |
| 35 | |
| 36 PipelineMetadata EncryptedMetadata() { | |
| 37 PipelineMetadata data; | |
| 38 data.has_audio = true; | |
| 39 data.has_video = true; | |
| 40 data.video_decoder_config = TestVideoConfig::NormalEncrypted(); | |
| 41 return data; | |
| 42 } | |
| 43 | |
| 44 } // namespace | |
| 45 | |
| 46 class RemotingRendererControllerTest : public ::testing::Test { | |
| 47 public: | |
| 48 RemotingRendererControllerTest() {} | |
| 49 ~RemotingRendererControllerTest() override {} | |
| 50 | |
| 51 void TearDown() final { RunUntilIdle(); } | |
| 52 | |
| 53 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } | |
| 54 | |
| 55 void ToggleRenderer() { | |
| 56 is_rendering_remotely_ = | |
| 57 remoting_renderer_controller_->remote_rendering_started(); | |
| 58 } | |
| 59 | |
| 60 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; } | |
| 61 | |
| 62 base::MessageLoop message_loop_; | |
| 63 | |
| 64 protected: | |
| 65 std::unique_ptr<RemotingRendererController> remoting_renderer_controller_; | |
| 66 bool is_rendering_remotely_ = false; | |
| 67 bool is_remoting_cdm_ = false; | |
| 68 | |
| 69 private: | |
| 70 DISALLOW_COPY_AND_ASSIGN(RemotingRendererControllerTest); | |
| 71 }; | |
| 72 | |
| 73 TEST_F(RemotingRendererControllerTest, ToggleRendererOnFullscreenChange) { | |
| 74 EXPECT_FALSE(is_rendering_remotely_); | |
| 75 scoped_refptr<RemotingSourceImpl> remoting_source_impl = | |
| 76 CreateRemotingSourceImpl(false); | |
| 77 remoting_renderer_controller_ = | |
| 78 base::MakeUnique<RemotingRendererController>(remoting_source_impl); | |
| 79 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 80 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 81 RunUntilIdle(); | |
| 82 EXPECT_FALSE(is_rendering_remotely_); | |
| 83 remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 84 RunUntilIdle(); | |
| 85 EXPECT_FALSE(is_rendering_remotely_); | |
| 86 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 87 RunUntilIdle(); | |
| 88 EXPECT_FALSE(is_rendering_remotely_); | |
| 89 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata()); | |
| 90 RunUntilIdle(); | |
| 91 EXPECT_FALSE(is_rendering_remotely_); | |
| 92 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 93 RunUntilIdle(); | |
| 94 EXPECT_FALSE(is_rendering_remotely_); | |
| 95 remoting_renderer_controller_->OnPlaying(); | |
| 96 RunUntilIdle(); | |
| 97 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied. | |
| 98 | |
| 99 // Leaving fullscreen should shut down remoting. | |
| 100 remoting_renderer_controller_->OnExitedFullscreen(); | |
| 101 RunUntilIdle(); | |
| 102 EXPECT_FALSE(is_rendering_remotely_); | |
| 103 } | |
| 104 | |
| 105 TEST_F(RemotingRendererControllerTest, ToggleRendererOnSinkCapabilities) { | |
| 106 EXPECT_FALSE(is_rendering_remotely_); | |
| 107 scoped_refptr<RemotingSourceImpl> remoting_source_impl = | |
| 108 CreateRemotingSourceImpl(false); | |
| 109 remoting_renderer_controller_ = | |
| 110 base::MakeUnique<RemotingRendererController>(remoting_source_impl); | |
| 111 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 112 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 113 RunUntilIdle(); | |
| 114 EXPECT_FALSE(is_rendering_remotely_); | |
| 115 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata()); | |
| 116 RunUntilIdle(); | |
| 117 EXPECT_FALSE(is_rendering_remotely_); | |
| 118 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 119 RunUntilIdle(); | |
| 120 EXPECT_FALSE(is_rendering_remotely_); | |
| 121 remoting_renderer_controller_->OnPlaying(); | |
| 122 RunUntilIdle(); | |
| 123 EXPECT_FALSE(is_rendering_remotely_); | |
| 124 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 125 RunUntilIdle(); | |
| 126 EXPECT_FALSE(is_rendering_remotely_); | |
| 127 // An available sink that does not support remote rendering should not cause | |
| 128 // the controller to toggle remote rendering on. | |
| 129 remoting_source_impl->OnSinkAvailable(mojom::RemotingSinkCapabilities::NONE); | |
| 130 RunUntilIdle(); | |
| 131 EXPECT_FALSE(is_rendering_remotely_); | |
| 132 remoting_source_impl->OnSinkGone(); // Bye-bye useless sink! | |
| 133 RunUntilIdle(); | |
| 134 EXPECT_FALSE(is_rendering_remotely_); | |
| 135 // A sink that *does* support remote rendering *does* cause the controller to | |
| 136 // toggle remote rendering on. | |
| 137 remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 138 RunUntilIdle(); | |
| 139 EXPECT_TRUE(is_rendering_remotely_); | |
| 140 remoting_renderer_controller_->OnExitedFullscreen(); | |
| 141 RunUntilIdle(); | |
| 142 EXPECT_FALSE(is_rendering_remotely_); | |
| 143 } | |
| 144 | |
| 145 TEST_F(RemotingRendererControllerTest, ToggleRendererOnDisableChange) { | |
| 146 EXPECT_FALSE(is_rendering_remotely_); | |
| 147 scoped_refptr<RemotingSourceImpl> remoting_source_impl = | |
| 148 CreateRemotingSourceImpl(false); | |
| 149 remoting_renderer_controller_ = | |
| 150 base::MakeUnique<RemotingRendererController>(remoting_source_impl); | |
| 151 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 152 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 153 RunUntilIdle(); | |
| 154 EXPECT_FALSE(is_rendering_remotely_); | |
| 155 remoting_renderer_controller_->OnRemotePlaybackDisabled(true); | |
| 156 RunUntilIdle(); | |
| 157 EXPECT_FALSE(is_rendering_remotely_); | |
| 158 remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 159 RunUntilIdle(); | |
| 160 EXPECT_FALSE(is_rendering_remotely_); | |
| 161 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata()); | |
| 162 RunUntilIdle(); | |
| 163 EXPECT_FALSE(is_rendering_remotely_); | |
| 164 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 165 RunUntilIdle(); | |
| 166 EXPECT_FALSE(is_rendering_remotely_); | |
| 167 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 168 RunUntilIdle(); | |
| 169 EXPECT_FALSE(is_rendering_remotely_); | |
| 170 remoting_renderer_controller_->OnPlaying(); | |
| 171 RunUntilIdle(); | |
| 172 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied. | |
| 173 | |
| 174 // If the page disables remote playback (e.g., by setting the | |
| 175 // disableRemotePlayback attribute), this should shut down remoting. | |
| 176 remoting_renderer_controller_->OnRemotePlaybackDisabled(true); | |
| 177 RunUntilIdle(); | |
| 178 EXPECT_FALSE(is_rendering_remotely_); | |
| 179 } | |
| 180 | |
| 181 TEST_F(RemotingRendererControllerTest, StartFailed) { | |
| 182 EXPECT_FALSE(is_rendering_remotely_); | |
| 183 scoped_refptr<RemotingSourceImpl> remoting_source_impl = | |
| 184 CreateRemotingSourceImpl(true); | |
| 185 remoting_renderer_controller_ = | |
| 186 base::MakeUnique<RemotingRendererController>(remoting_source_impl); | |
| 187 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 188 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 189 RunUntilIdle(); | |
| 190 EXPECT_FALSE(is_rendering_remotely_); | |
| 191 remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 192 RunUntilIdle(); | |
| 193 EXPECT_FALSE(is_rendering_remotely_); | |
| 194 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 195 RunUntilIdle(); | |
| 196 EXPECT_FALSE(is_rendering_remotely_); | |
| 197 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata()); | |
| 198 RunUntilIdle(); | |
| 199 EXPECT_FALSE(is_rendering_remotely_); | |
| 200 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 201 RunUntilIdle(); | |
| 202 EXPECT_FALSE(is_rendering_remotely_); | |
| 203 remoting_renderer_controller_->OnPlaying(); | |
| 204 RunUntilIdle(); | |
| 205 EXPECT_FALSE(is_rendering_remotely_); | |
| 206 } | |
| 207 | |
| 208 TEST_F(RemotingRendererControllerTest, EncryptedWithRemotingCdm) { | |
| 209 EXPECT_FALSE(is_rendering_remotely_); | |
| 210 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>( | |
| 211 CreateRemotingSourceImpl(false)); | |
| 212 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 213 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 214 RunUntilIdle(); | |
| 215 EXPECT_FALSE(is_rendering_remotely_); | |
| 216 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata()); | |
| 217 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 218 remoting_renderer_controller_->OnPlaying(); | |
| 219 RunUntilIdle(); | |
| 220 EXPECT_FALSE(is_rendering_remotely_); | |
| 221 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl = | |
| 222 CreateRemotingSourceImpl(false); | |
| 223 std::unique_ptr<RemotingCdmController> remoting_cdm_controller = | |
| 224 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl); | |
| 225 cdm_remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 226 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind( | |
| 227 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this))); | |
| 228 RunUntilIdle(); | |
| 229 EXPECT_FALSE(is_rendering_remotely_); | |
| 230 EXPECT_TRUE(is_remoting_cdm_); | |
| 231 | |
| 232 // Create a RemotingCdm with |remoting_cdm_controller|. | |
| 233 scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm( | |
| 234 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(), | |
| 235 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(), | |
| 236 std::move(remoting_cdm_controller)); | |
| 237 std::unique_ptr<RemotingCdmContext> remoting_cdm_context = | |
| 238 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get()); | |
| 239 remoting_renderer_controller_->OnSetCdm(remoting_cdm_context.get()); | |
| 240 RunUntilIdle(); | |
| 241 EXPECT_TRUE(is_rendering_remotely_); | |
| 242 | |
| 243 // For encrypted contents, entering/exiting full screen has no effect. | |
| 244 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 245 RunUntilIdle(); | |
| 246 EXPECT_TRUE(is_rendering_remotely_); | |
| 247 remoting_renderer_controller_->OnExitedFullscreen(); | |
| 248 RunUntilIdle(); | |
| 249 EXPECT_TRUE(is_rendering_remotely_); | |
| 250 | |
| 251 EXPECT_NE(RemotingSessionState::SESSION_PERMANENTLY_STOPPED, | |
| 252 remoting_renderer_controller_->remoting_source()->state()); | |
| 253 cdm_remoting_source_impl->OnSinkGone(); | |
| 254 RunUntilIdle(); | |
| 255 EXPECT_EQ(RemotingSessionState::SESSION_PERMANENTLY_STOPPED, | |
| 256 remoting_renderer_controller_->remoting_source()->state()); | |
| 257 // Don't switch renderer in this case. Still using the remoting renderer to | |
| 258 // show the failure interstitial. | |
| 259 EXPECT_TRUE(is_rendering_remotely_); | |
| 260 } | |
| 261 | |
| 262 TEST_F(RemotingRendererControllerTest, EncryptedWithLocalCdm) { | |
| 263 EXPECT_FALSE(is_rendering_remotely_); | |
| 264 scoped_refptr<RemotingSourceImpl> renderer_remoting_source_impl = | |
| 265 CreateRemotingSourceImpl(false); | |
| 266 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>( | |
| 267 renderer_remoting_source_impl); | |
| 268 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 269 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 270 RunUntilIdle(); | |
| 271 EXPECT_FALSE(is_rendering_remotely_); | |
| 272 renderer_remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 273 RunUntilIdle(); | |
| 274 EXPECT_FALSE(is_rendering_remotely_); | |
| 275 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 276 RunUntilIdle(); | |
| 277 EXPECT_FALSE(is_rendering_remotely_); | |
| 278 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata()); | |
| 279 RunUntilIdle(); | |
| 280 EXPECT_FALSE(is_rendering_remotely_); | |
| 281 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 282 RunUntilIdle(); | |
| 283 EXPECT_FALSE(is_rendering_remotely_); | |
| 284 remoting_renderer_controller_->OnPlaying(); | |
| 285 RunUntilIdle(); | |
| 286 EXPECT_FALSE(is_rendering_remotely_); | |
| 287 | |
| 288 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl = | |
| 289 CreateRemotingSourceImpl(true); | |
| 290 std::unique_ptr<RemotingCdmController> remoting_cdm_controller = | |
| 291 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl); | |
| 292 cdm_remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 293 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind( | |
| 294 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this))); | |
| 295 RunUntilIdle(); | |
| 296 EXPECT_FALSE(is_rendering_remotely_); | |
| 297 EXPECT_FALSE(is_remoting_cdm_); | |
| 298 } | |
| 299 | |
| 300 TEST_F(RemotingRendererControllerTest, EncryptedWithFailedRemotingCdm) { | |
| 301 EXPECT_FALSE(is_rendering_remotely_); | |
| 302 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>( | |
| 303 CreateRemotingSourceImpl(false)); | |
| 304 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind( | |
| 305 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this))); | |
| 306 RunUntilIdle(); | |
| 307 EXPECT_FALSE(is_rendering_remotely_); | |
| 308 remoting_renderer_controller_->OnEnteredFullscreen(); | |
| 309 RunUntilIdle(); | |
| 310 EXPECT_FALSE(is_rendering_remotely_); | |
| 311 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata()); | |
| 312 RunUntilIdle(); | |
| 313 EXPECT_FALSE(is_rendering_remotely_); | |
| 314 remoting_renderer_controller_->OnRemotePlaybackDisabled(false); | |
| 315 RunUntilIdle(); | |
| 316 EXPECT_FALSE(is_rendering_remotely_); | |
| 317 remoting_renderer_controller_->OnPlaying(); | |
| 318 RunUntilIdle(); | |
| 319 EXPECT_FALSE(is_rendering_remotely_); | |
| 320 | |
| 321 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl = | |
| 322 CreateRemotingSourceImpl(false); | |
| 323 std::unique_ptr<RemotingCdmController> remoting_cdm_controller = | |
| 324 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl); | |
| 325 cdm_remoting_source_impl->OnSinkAvailable(kAllCapabilities); | |
| 326 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind( | |
| 327 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this))); | |
| 328 RunUntilIdle(); | |
| 329 EXPECT_FALSE(is_rendering_remotely_); | |
| 330 EXPECT_TRUE(is_remoting_cdm_); | |
| 331 | |
| 332 cdm_remoting_source_impl->OnSinkGone(); | |
| 333 RunUntilIdle(); | |
| 334 EXPECT_FALSE(is_rendering_remotely_); | |
| 335 EXPECT_NE(RemotingSessionState::SESSION_PERMANENTLY_STOPPED, | |
| 336 remoting_renderer_controller_->remoting_source()->state()); | |
| 337 | |
| 338 scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm( | |
| 339 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(), | |
| 340 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(), | |
| 341 std::move(remoting_cdm_controller)); | |
| 342 std::unique_ptr<RemotingCdmContext> remoting_cdm_context = | |
| 343 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get()); | |
| 344 remoting_renderer_controller_->OnSetCdm(remoting_cdm_context.get()); | |
| 345 RunUntilIdle(); | |
| 346 // Switch to using the remoting renderer, even when the remoting CDM session | |
| 347 // was already terminated, to show the failure interstitial. | |
| 348 EXPECT_TRUE(is_rendering_remotely_); | |
| 349 EXPECT_EQ(RemotingSessionState::SESSION_PERMANENTLY_STOPPED, | |
| 350 remoting_renderer_controller_->remoting_source()->state()); | |
| 351 } | |
| 352 | |
| 353 } // namespace media | |
| OLD | NEW |