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 "third_party/blink/renderer/core/html/media/html_media_element.h"
6 
7 #include "base/test/gtest_util.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom-blink.h"
11 #include "third_party/blink/public/platform/web_media_player.h"
12 #include "third_party/blink/public/platform/web_media_player_source.h"
13 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
14 #include "third_party/blink/renderer/core/frame/settings.h"
15 #include "third_party/blink/renderer/core/html/media/html_audio_element.h"
16 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
17 #include "third_party/blink/renderer/core/html/media/media_error.h"
18 #include "third_party/blink/renderer/core/html/time_ranges.h"
19 #include "third_party/blink/renderer/core/html/track/audio_track_list.h"
20 #include "third_party/blink/renderer/core/html/track/video_track_list.h"
21 #include "third_party/blink/renderer/core/loader/empty_clients.h"
22 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
23 #include "third_party/blink/renderer/platform/heap/heap.h"
24 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
25 #include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
26 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
27 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
28 #include "third_party/blink/renderer/platform/wtf/vector.h"
29 
30 using ::testing::_;
31 using ::testing::AnyNumber;
32 using ::testing::NanSensitiveDoubleEq;
33 using ::testing::Return;
34 
35 namespace blink {
36 
37 namespace {
38 
39 class MockWebMediaPlayer : public EmptyWebMediaPlayer {
40  public:
41   MOCK_CONST_METHOD0(HasAudio, bool());
42   MOCK_CONST_METHOD0(HasVideo, bool());
43   MOCK_CONST_METHOD0(Duration, double());
44   MOCK_CONST_METHOD0(CurrentTime, double());
45   MOCK_CONST_METHOD0(IsEnded, bool());
46   MOCK_CONST_METHOD0(GetNetworkState, NetworkState());
47   MOCK_CONST_METHOD0(WouldTaintOrigin, bool());
48   MOCK_METHOD1(SetLatencyHint, void(double));
49   MOCK_METHOD1(EnabledAudioTracksChanged, void(const WebVector<TrackId>&));
50   MOCK_METHOD1(SelectedVideoTrackChanged, void(TrackId*));
51   MOCK_METHOD3(
52       Load,
53       WebMediaPlayer::LoadTiming(LoadType load_type,
54                                  const blink::WebMediaPlayerSource& source,
55                                  CorsMode cors_mode));
56   MOCK_CONST_METHOD0(DidLazyLoad, bool());
57 
58   MOCK_METHOD0(GetSrcAfterRedirects, GURL());
59 };
60 
61 class WebMediaStubLocalFrameClient : public EmptyLocalFrameClient {
62  public:
WebMediaStubLocalFrameClient(std::unique_ptr<WebMediaPlayer> player)63   explicit WebMediaStubLocalFrameClient(std::unique_ptr<WebMediaPlayer> player)
64       : player_(std::move(player)) {}
65 
CreateWebMediaPlayer(HTMLMediaElement &,const WebMediaPlayerSource &,WebMediaPlayerClient * client)66   std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
67       HTMLMediaElement&,
68       const WebMediaPlayerSource&,
69       WebMediaPlayerClient* client) override {
70     DCHECK(player_) << " Empty injected player - already used?";
71     return std::move(player_);
72   }
73 
74  private:
75   std::unique_ptr<WebMediaPlayer> player_;
76 };
77 
78 enum class MediaTestParam { kAudio, kVideo };
79 
80 }  // namespace
81 
82 class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
83  protected:
SetUp()84   void SetUp() override {
85     // Sniff the media player pointer to facilitate mocking.
86     auto mock_media_player = std::make_unique<MockWebMediaPlayer>();
87     media_player_ = mock_media_player.get();
88 
89     // Most tests do not care about this call, nor its return value. Those that
90     // do will clear this expectation and set custom expectations/returns.
91     EXPECT_CALL(*mock_media_player, HasAudio()).WillRepeatedly(Return(true));
92     EXPECT_CALL(*mock_media_player, HasVideo()).WillRepeatedly(Return(true));
93     EXPECT_CALL(*mock_media_player, Duration()).WillRepeatedly(Return(1.0));
94     EXPECT_CALL(*mock_media_player, CurrentTime()).WillRepeatedly(Return(0));
95     EXPECT_CALL(*mock_media_player, Load(_, _, _))
96         .Times(AnyNumber())
97         .WillRepeatedly(Return(WebMediaPlayer::LoadTiming::kImmediate));
98     EXPECT_CALL(*mock_media_player, DidLazyLoad).WillRepeatedly(Return(false));
99     EXPECT_CALL(*mock_media_player, WouldTaintOrigin)
100         .WillRepeatedly(Return(true));
101     EXPECT_CALL(*mock_media_player, GetNetworkState)
102         .WillRepeatedly(Return(WebMediaPlayer::kNetworkStateIdle));
103     EXPECT_CALL(*mock_media_player, SetLatencyHint(_)).Times(AnyNumber());
104 
105     dummy_page_holder_ = std::make_unique<DummyPageHolder>(
106         IntSize(), nullptr,
107         MakeGarbageCollected<WebMediaStubLocalFrameClient>(
108             std::move(mock_media_player)));
109 
110     if (GetParam() == MediaTestParam::kAudio) {
111       media_ = MakeGarbageCollected<HTMLAudioElement>(
112           dummy_page_holder_->GetDocument());
113     } else {
114       media_ = MakeGarbageCollected<HTMLVideoElement>(
115           dummy_page_holder_->GetDocument());
116     }
117   }
118 
Media() const119   HTMLMediaElement* Media() const { return media_.Get(); }
SetCurrentSrc(const AtomicString & src)120   void SetCurrentSrc(const AtomicString& src) {
121     KURL url(src);
122     Media()->current_src_ = url;
123   }
124 
MockMediaPlayer()125   MockWebMediaPlayer* MockMediaPlayer() { return media_player_; }
126 
WasAutoplayInitiated()127   bool WasAutoplayInitiated() { return Media()->WasAutoplayInitiated(); }
128 
CouldPlayIfEnoughData()129   bool CouldPlayIfEnoughData() { return Media()->CouldPlayIfEnoughData(); }
130 
ShouldDelayLoadEvent()131   bool ShouldDelayLoadEvent() { return Media()->should_delay_load_event_; }
132 
SetReadyState(HTMLMediaElement::ReadyState state)133   void SetReadyState(HTMLMediaElement::ReadyState state) {
134     Media()->SetReadyState(state);
135   }
136 
SetNetworkState(WebMediaPlayer::NetworkState state)137   void SetNetworkState(WebMediaPlayer::NetworkState state) {
138     Media()->SetNetworkState(state);
139   }
140 
MediaShouldBeOpaque() const141   bool MediaShouldBeOpaque() const { return Media()->MediaShouldBeOpaque(); }
142 
SetError(MediaError * err)143   void SetError(MediaError* err) { Media()->MediaEngineError(err); }
144 
SimulateHighMediaEngagement()145   void SimulateHighMediaEngagement() {
146     Media()->GetDocument().GetPage()->AddAutoplayFlags(
147         mojom::blink::kAutoplayFlagHighMediaEngagement);
148   }
149 
HasLazyLoadObserver() const150   bool HasLazyLoadObserver() const {
151     return !!Media()->lazy_load_intersection_observer_;
152   }
153 
GetExecutionContext() const154   ExecutionContext* GetExecutionContext() const {
155     return dummy_page_holder_->GetFrame().DomWindow();
156   }
157 
158  private:
159   std::unique_ptr<DummyPageHolder> dummy_page_holder_;
160   Persistent<HTMLMediaElement> media_;
161 
162   // Owned by WebMediaStubLocalFrameClient.
163   MockWebMediaPlayer* media_player_;
164 };
165 
166 INSTANTIATE_TEST_SUITE_P(Audio,
167                          HTMLMediaElementTest,
168                          testing::Values(MediaTestParam::kAudio));
169 INSTANTIATE_TEST_SUITE_P(Video,
170                          HTMLMediaElementTest,
171                          testing::Values(MediaTestParam::kVideo));
172 
TEST_P(HTMLMediaElementTest,effectiveMediaVolume)173 TEST_P(HTMLMediaElementTest, effectiveMediaVolume) {
174   struct TestData {
175     double volume;
176     bool muted;
177     double effective_volume;
178   } test_data[] = {
179       {0.0, false, 0.0}, {0.5, false, 0.5}, {1.0, false, 1.0},
180       {0.0, true, 0.0},  {0.5, true, 0.0},  {1.0, true, 0.0},
181   };
182 
183   for (const auto& data : test_data) {
184     Media()->setVolume(data.volume);
185     Media()->setMuted(data.muted);
186     EXPECT_EQ(data.effective_volume, Media()->EffectiveMediaVolume());
187   }
188 }
189 
190 enum class TestURLScheme {
191   kHttp,
192   kHttps,
193   kFtp,
194   kFile,
195   kData,
196   kBlob,
197 };
198 
SrcSchemeToURL(TestURLScheme scheme)199 AtomicString SrcSchemeToURL(TestURLScheme scheme) {
200   switch (scheme) {
201     case TestURLScheme::kHttp:
202       return "http://example.com/foo.mp4";
203     case TestURLScheme::kHttps:
204       return "https://example.com/foo.mp4";
205     case TestURLScheme::kFtp:
206       return "ftp://example.com/foo.mp4";
207     case TestURLScheme::kFile:
208       return "file:///foo/bar.mp4";
209     case TestURLScheme::kData:
210       return "data:video/mp4;base64,XXXXXXX";
211     case TestURLScheme::kBlob:
212       return "blob:http://example.com/00000000-0000-0000-0000-000000000000";
213     default:
214       NOTREACHED();
215   }
216   return g_empty_atom;
217 }
218 
TEST_P(HTMLMediaElementTest,preloadType)219 TEST_P(HTMLMediaElementTest, preloadType) {
220   struct TestData {
221     bool data_saver_enabled;
222     bool is_cellular;
223     TestURLScheme src_scheme;
224     AtomicString preload_to_set;
225     AtomicString preload_expected;
226   } test_data[] = {
227       // Tests for conditions in which preload type should be overriden to
228       // "none".
229       {false, false, TestURLScheme::kHttp, "auto", "auto"},
230       {true, false, TestURLScheme::kHttps, "auto", "auto"},
231       {true, false, TestURLScheme::kFtp, "metadata", "metadata"},
232       {false, false, TestURLScheme::kHttps, "auto", "auto"},
233       {false, false, TestURLScheme::kFile, "auto", "auto"},
234       {false, false, TestURLScheme::kData, "metadata", "metadata"},
235       {false, false, TestURLScheme::kBlob, "auto", "auto"},
236       {false, false, TestURLScheme::kFile, "none", "none"},
237       // Tests for conditions in which preload type should be overriden to
238       // "metadata".
239       {false, true, TestURLScheme::kHttp, "auto", "metadata"},
240       {false, true, TestURLScheme::kHttp, "scheme", "metadata"},
241       {false, true, TestURLScheme::kHttp, "none", "none"},
242       // Tests that the preload is overriden to "metadata".
243       {false, false, TestURLScheme::kHttp, "foo", "metadata"},
244   };
245 
246   int index = 0;
247   for (const auto& data : test_data) {
248     GetNetworkStateNotifier().SetSaveDataEnabledOverride(
249         data.data_saver_enabled);
250     if (data.is_cellular) {
251       GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
252           true, WebConnectionType::kWebConnectionTypeCellular3G,
253           WebEffectiveConnectionType::kTypeUnknown, 1.0, 2.0);
254     } else {
255       GetNetworkStateNotifier().ClearOverride();
256     }
257     SetCurrentSrc(SrcSchemeToURL(data.src_scheme));
258     Media()->setPreload(data.preload_to_set);
259 
260     EXPECT_EQ(data.preload_expected, Media()->preload())
261         << "preload type differs at index" << index;
262     ++index;
263   }
264 }
265 
TEST_P(HTMLMediaElementTest,CouldPlayIfEnoughDataRespondsToPlay)266 TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToPlay) {
267   EXPECT_FALSE(CouldPlayIfEnoughData());
268   Media()->Play();
269   EXPECT_TRUE(CouldPlayIfEnoughData());
270 }
271 
TEST_P(HTMLMediaElementTest,CouldPlayIfEnoughDataRespondsToEnded)272 TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToEnded) {
273   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
274   Media()->Play();
275 
276   test::RunPendingTasks();
277 
278   MockWebMediaPlayer* mock_wmpi =
279       reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
280   ASSERT_NE(mock_wmpi, nullptr);
281   EXPECT_CALL(*mock_wmpi, IsEnded()).WillRepeatedly(Return(false));
282   EXPECT_TRUE(CouldPlayIfEnoughData());
283 
284   // Playback can only end once the ready state is above kHaveMetadata.
285   SetReadyState(HTMLMediaElement::kHaveFutureData);
286   EXPECT_FALSE(Media()->paused());
287   EXPECT_FALSE(Media()->ended());
288   EXPECT_TRUE(CouldPlayIfEnoughData());
289 
290   // Now advance current time to duration and verify ended state.
291   testing::Mock::VerifyAndClearExpectations(mock_wmpi);
292   EXPECT_CALL(*mock_wmpi, CurrentTime())
293       .WillRepeatedly(Return(Media()->duration()));
294   EXPECT_CALL(*mock_wmpi, IsEnded()).WillRepeatedly(Return(true));
295   EXPECT_FALSE(CouldPlayIfEnoughData());
296   EXPECT_TRUE(Media()->ended());
297 }
298 
TEST_P(HTMLMediaElementTest,CouldPlayIfEnoughDataRespondsToError)299 TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToError) {
300   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
301   Media()->Play();
302 
303   test::RunPendingTasks();
304 
305   MockWebMediaPlayer* mock_wmpi =
306       reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
307   EXPECT_NE(mock_wmpi, nullptr);
308   EXPECT_TRUE(CouldPlayIfEnoughData());
309 
310   SetReadyState(HTMLMediaElement::kHaveMetadata);
311   EXPECT_FALSE(Media()->paused());
312   EXPECT_FALSE(Media()->ended());
313   EXPECT_TRUE(CouldPlayIfEnoughData());
314 
315   SetError(MakeGarbageCollected<MediaError>(MediaError::kMediaErrDecode, ""));
316   EXPECT_FALSE(CouldPlayIfEnoughData());
317 }
318 
TEST_P(HTMLMediaElementTest,SetLatencyHint)319 TEST_P(HTMLMediaElementTest, SetLatencyHint) {
320   const double kNan = std::numeric_limits<double>::quiet_NaN();
321 
322   // Initial value.
323   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
324   EXPECT_CALL(*MockMediaPlayer(), SetLatencyHint(NanSensitiveDoubleEq(kNan)));
325 
326   test::RunPendingTasks();
327   testing::Mock::VerifyAndClearExpectations(MockMediaPlayer());
328 
329   // Valid value.
330   EXPECT_CALL(*MockMediaPlayer(), SetLatencyHint(NanSensitiveDoubleEq(1.0)));
331   Media()->setLatencyHint(1.0);
332 
333   test::RunPendingTasks();
334   testing::Mock::VerifyAndClearExpectations(MockMediaPlayer());
335 
336   // Invalid value.
337   EXPECT_CALL(*MockMediaPlayer(), SetLatencyHint(NanSensitiveDoubleEq(kNan)));
338   Media()->setLatencyHint(-1.0);
339 }
340 
TEST_P(HTMLMediaElementTest,CouldPlayIfEnoughDataInfiniteStreamNeverEnds)341 TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataInfiniteStreamNeverEnds) {
342   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
343   Media()->Play();
344 
345   test::RunPendingTasks();
346 
347   EXPECT_CALL(*MockMediaPlayer(), Duration())
348       .WillRepeatedly(Return(std::numeric_limits<double>::infinity()));
349   EXPECT_CALL(*MockMediaPlayer(), CurrentTime())
350       .WillRepeatedly(Return(std::numeric_limits<double>::infinity()));
351 
352   SetReadyState(HTMLMediaElement::kHaveMetadata);
353   EXPECT_FALSE(Media()->paused());
354   EXPECT_FALSE(Media()->ended());
355   EXPECT_TRUE(CouldPlayIfEnoughData());
356 }
357 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_DocumentActivation_Low_Gesture)358 TEST_P(HTMLMediaElementTest, AutoplayInitiated_DocumentActivation_Low_Gesture) {
359   // Setup is the following:
360   // - Policy: DocumentUserActivation (aka. unified autoplay)
361   // - MEI: low;
362   // - Frame received user gesture.
363   ScopedMediaEngagementBypassAutoplayPoliciesForTest scoped_feature(true);
364   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
365       AutoplayPolicy::Type::kDocumentUserActivationRequired);
366   LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
367 
368   Media()->Play();
369 
370   EXPECT_FALSE(WasAutoplayInitiated());
371 }
372 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_DocumentActivation_High_Gesture)373 TEST_P(HTMLMediaElementTest,
374        AutoplayInitiated_DocumentActivation_High_Gesture) {
375   // Setup is the following:
376   // - Policy: DocumentUserActivation (aka. unified autoplay)
377   // - MEI: high;
378   // - Frame received user gesture.
379   ScopedMediaEngagementBypassAutoplayPoliciesForTest scoped_feature(true);
380   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
381       AutoplayPolicy::Type::kDocumentUserActivationRequired);
382   SimulateHighMediaEngagement();
383   LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
384 
385   Media()->Play();
386 
387   EXPECT_FALSE(WasAutoplayInitiated());
388 }
389 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_DocumentActivation_High_NoGesture)390 TEST_P(HTMLMediaElementTest,
391        AutoplayInitiated_DocumentActivation_High_NoGesture) {
392   // Setup is the following:
393   // - Policy: DocumentUserActivation (aka. unified autoplay)
394   // - MEI: high;
395   // - Frame did not receive user gesture.
396   ScopedMediaEngagementBypassAutoplayPoliciesForTest scoped_feature(true);
397   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
398       AutoplayPolicy::Type::kDocumentUserActivationRequired);
399   SimulateHighMediaEngagement();
400 
401   Media()->Play();
402 
403   EXPECT_TRUE(WasAutoplayInitiated());
404 }
405 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_GestureRequired_Gesture)406 TEST_P(HTMLMediaElementTest, AutoplayInitiated_GestureRequired_Gesture) {
407   // Setup is the following:
408   // - Policy: user gesture is required.
409   // - Frame received a user gesture.
410   // - MEI doesn't matter as it's not used by the policy.
411   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
412       AutoplayPolicy::Type::kUserGestureRequired);
413   LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
414 
415   Media()->Play();
416 
417   EXPECT_FALSE(WasAutoplayInitiated());
418 }
419 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_NoGestureRequired_Gesture)420 TEST_P(HTMLMediaElementTest, AutoplayInitiated_NoGestureRequired_Gesture) {
421   // Setup is the following:
422   // - Policy: no user gesture is required.
423   // - Frame received a user gesture.
424   // - MEI doesn't matter as it's not used by the policy.
425   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
426       AutoplayPolicy::Type::kNoUserGestureRequired);
427   LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
428 
429   Media()->Play();
430 
431   EXPECT_FALSE(WasAutoplayInitiated());
432 }
433 
TEST_P(HTMLMediaElementTest,AutoplayInitiated_NoGestureRequired_NoGesture)434 TEST_P(HTMLMediaElementTest, AutoplayInitiated_NoGestureRequired_NoGesture) {
435   // Setup is the following:
436   // - Policy: no user gesture is required.
437   // - Frame did not receive a user gesture.
438   // - MEI doesn't matter as it's not used by the policy.
439   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
440       AutoplayPolicy::Type::kNoUserGestureRequired);
441 
442   Media()->Play();
443 
444   EXPECT_TRUE(WasAutoplayInitiated());
445 }
446 
TEST_P(HTMLMediaElementTest,DeferredMediaPlayerLoadDoesNotDelayWindowLoadEvent)447 TEST_P(HTMLMediaElementTest,
448        DeferredMediaPlayerLoadDoesNotDelayWindowLoadEvent) {
449   // Source isn't really important, we just need something to let load algorithm
450   // run up to the point of calling WebMediaPlayer::Load().
451   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
452 
453   // WebMediaPlayer will signal that it will defer loading to some later time.
454   testing::Mock::VerifyAndClearExpectations(MockMediaPlayer());
455   EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _))
456       .WillOnce(Return(WebMediaPlayer::LoadTiming::kDeferred));
457 
458   // Window's 'load' event starts out "delayed".
459   EXPECT_TRUE(ShouldDelayLoadEvent());
460   Media()->load();
461   test::RunPendingTasks();
462 
463   // No longer delayed because WMP loading is deferred.
464   EXPECT_FALSE(ShouldDelayLoadEvent());
465 }
466 
TEST_P(HTMLMediaElementTest,ImmediateMediaPlayerLoadDoesDelayWindowLoadEvent)467 TEST_P(HTMLMediaElementTest, ImmediateMediaPlayerLoadDoesDelayWindowLoadEvent) {
468   // Source isn't really important, we just need something to let load algorithm
469   // run up to the point of calling WebMediaPlayer::Load().
470   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
471 
472   // WebMediaPlayer will signal that it will do the load immediately.
473   EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _))
474       .WillOnce(Return(WebMediaPlayer::LoadTiming::kImmediate));
475 
476   // Window's 'load' event starts out "delayed".
477   EXPECT_TRUE(ShouldDelayLoadEvent());
478   Media()->load();
479   test::RunPendingTasks();
480 
481   // Still delayed because WMP loading is not deferred.
482   EXPECT_TRUE(ShouldDelayLoadEvent());
483 }
484 
TEST_P(HTMLMediaElementTest,DefaultTracksAreEnabled)485 TEST_P(HTMLMediaElementTest, DefaultTracksAreEnabled) {
486   // Default tracks should start enabled, not be created then enabled.
487   EXPECT_CALL(*MockMediaPlayer(), EnabledAudioTracksChanged(_)).Times(0);
488   EXPECT_CALL(*MockMediaPlayer(), SelectedVideoTrackChanged(_)).Times(0);
489 
490   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
491   test::RunPendingTasks();
492   SetReadyState(HTMLMediaElement::kHaveFutureData);
493 
494   ASSERT_EQ(1u, Media()->audioTracks().length());
495   ASSERT_EQ(1u, Media()->videoTracks().length());
496   EXPECT_TRUE(Media()->audioTracks().AnonymousIndexedGetter(0)->enabled());
497   EXPECT_TRUE(Media()->videoTracks().AnonymousIndexedGetter(0)->selected());
498 }
499 
500 // Ensure a visibility observer is created for lazy loading.
TEST_P(HTMLMediaElementTest,VisibilityObserverCreatedForLazyLoad)501 TEST_P(HTMLMediaElementTest, VisibilityObserverCreatedForLazyLoad) {
502   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
503   test::RunPendingTasks();
504 
505   EXPECT_CALL(*MockMediaPlayer(), DidLazyLoad()).WillRepeatedly(Return(true));
506 
507   SetReadyState(HTMLMediaElement::kHaveFutureData);
508   EXPECT_EQ(HasLazyLoadObserver(), GetParam() == MediaTestParam::kVideo);
509 }
510 
TEST_P(HTMLMediaElementTest,DomInteractive)511 TEST_P(HTMLMediaElementTest, DomInteractive) {
512   EXPECT_FALSE(Media()->GetDocument().GetTiming().DomInteractive().is_null());
513 }
514 
TEST_P(HTMLMediaElementTest,ContextPaused)515 TEST_P(HTMLMediaElementTest, ContextPaused) {
516   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
517   Media()->Play();
518 
519   test::RunPendingTasks();
520   SetReadyState(HTMLMediaElement::kHaveFutureData);
521 
522   EXPECT_FALSE(Media()->paused());
523   GetExecutionContext()->SetLifecycleState(
524       mojom::FrameLifecycleState::kFrozenAutoResumeMedia);
525   EXPECT_TRUE(Media()->paused());
526   GetExecutionContext()->SetLifecycleState(
527       mojom::FrameLifecycleState::kRunning);
528   EXPECT_FALSE(Media()->paused());
529   GetExecutionContext()->SetLifecycleState(mojom::FrameLifecycleState::kFrozen);
530   EXPECT_TRUE(Media()->paused());
531   GetExecutionContext()->SetLifecycleState(
532       mojom::FrameLifecycleState::kRunning);
533   EXPECT_TRUE(Media()->paused());
534 }
535 
TEST_P(HTMLMediaElementTest,GcMarkingNoAllocWebTimeRanges)536 TEST_P(HTMLMediaElementTest, GcMarkingNoAllocWebTimeRanges) {
537   auto* thread_state = ThreadState::Current();
538   ThreadState::NoAllocationScope no_allocation_scope(thread_state);
539   EXPECT_FALSE(thread_state->IsAllocationAllowed());
540   // Use of TimeRanges is not allowed during GC marking (crbug.com/970150)
541   EXPECT_DCHECK_DEATH(MakeGarbageCollected<TimeRanges>(0, 0));
542   // Instead of using TimeRanges, WebTimeRanges can be used without GC
543   Vector<WebTimeRanges> ranges;
544   ranges.emplace_back();
545   ranges[0].emplace_back(0, 0);
546 }
547 
548 // Reproduce crbug.com/970150
TEST_P(HTMLMediaElementTest,GcMarkingNoAllocHasActivity)549 TEST_P(HTMLMediaElementTest, GcMarkingNoAllocHasActivity) {
550   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
551   Media()->Play();
552 
553   test::RunPendingTasks();
554   SetReadyState(HTMLMediaElement::kHaveFutureData);
555   SetError(MakeGarbageCollected<MediaError>(MediaError::kMediaErrDecode, ""));
556 
557   EXPECT_FALSE(Media()->paused());
558 
559   auto* thread_state = ThreadState::Current();
560   ThreadState::NoAllocationScope no_allocation_scope(thread_state);
561   EXPECT_FALSE(thread_state->IsAllocationAllowed());
562   Media()->HasPendingActivity();
563 }
564 
TEST_P(HTMLMediaElementTest,CapturesRedirectedSrc)565 TEST_P(HTMLMediaElementTest, CapturesRedirectedSrc) {
566   // Verify that the element captures the redirected URL.
567   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
568   Media()->Play();
569   test::RunPendingTasks();
570 
571   // Should start at the original.
572   EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
573 
574   GURL redirected_url("https://redirected.com");
575   EXPECT_CALL(*MockMediaPlayer(), GetSrcAfterRedirects())
576       .WillRepeatedly(Return(redirected_url));
577   SetReadyState(HTMLMediaElement::kHaveFutureData);
578 
579   EXPECT_EQ(Media()->downloadURL(), redirected_url);
580 }
581 
TEST_P(HTMLMediaElementTest,EmptyRedirectedSrcUsesOriginal)582 TEST_P(HTMLMediaElementTest, EmptyRedirectedSrcUsesOriginal) {
583   // If the player returns an empty URL for the redirected src, then the element
584   // should continue using currentSrc().
585   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
586   Media()->Play();
587   test::RunPendingTasks();
588   EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
589   SetReadyState(HTMLMediaElement::kHaveFutureData);
590   EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
591 }
592 
TEST_P(HTMLMediaElementTest,NoPendingActivityEvenIfBeforeMetadata)593 TEST_P(HTMLMediaElementTest, NoPendingActivityEvenIfBeforeMetadata) {
594   Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
595   test::RunPendingTasks();
596 
597   MockWebMediaPlayer* mock_wmpi =
598       reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
599   EXPECT_CALL(*mock_wmpi, WouldTaintOrigin()).WillRepeatedly(Return(true));
600   EXPECT_NE(mock_wmpi, nullptr);
601 
602   EXPECT_TRUE(MediaShouldBeOpaque());
603   EXPECT_TRUE(Media()->HasPendingActivity());
604   SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
605   EXPECT_FALSE(Media()->HasPendingActivity());
606   EXPECT_TRUE(MediaShouldBeOpaque());
607 }
608 
609 }  // namespace blink
610