blob: 1dbf6e801db823fe18ccde373fe3d44073e1c5ad [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "cc/layers/layer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/picture_in_picture/picture_in_picture_control_info.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/media/html_media_test_helper.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
class HTMLVideoElementMockMediaPlayer : public EmptyWebMediaPlayer {
public:
MOCK_METHOD1(SetIsEffectivelyFullscreen, void(WebFullscreenVideoStatus));
MOCK_METHOD1(OnDisplayTypeChanged, void(WebMediaPlayer::DisplayType));
};
class HTMLVideoElementTest : public PageTestBase {
public:
void SetUp() override {
auto mock_media_player =
std::make_unique<HTMLVideoElementMockMediaPlayer>();
media_player_ = mock_media_player.get();
SetupPageWithClients(
nullptr,
test::MediaStubLocalFrameClient::Create(std::move(mock_media_player)),
nullptr);
video_ = HTMLVideoElement::Create(GetDocument());
GetDocument().body()->appendChild(video_);
}
void SetFakeCcLayer(cc::Layer* layer) { video_->SetCcLayer(layer); }
HTMLVideoElement* video() { return video_.Get(); }
HTMLVideoElementMockMediaPlayer* MockWebMediaPlayer() {
return media_player_;
}
private:
Persistent<HTMLVideoElement> video_;
// Owned by HTMLVideoElementFrameClient.
HTMLVideoElementMockMediaPlayer* media_player_;
};
TEST_F(HTMLVideoElementTest, PictureInPictureInterstitialAndTextContainer) {
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
SetFakeCcLayer(layer.get());
video()->SetBooleanAttribute(html_names::kControlsAttr, true);
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
// Simulate the text track being displayed.
video()->UpdateTextTrackDisplay();
video()->UpdateTextTrackDisplay();
// Simulate entering Picture-in-Picture.
video()->OnEnteredPictureInPicture();
// Simulate that text track are displayed again.
video()->UpdateTextTrackDisplay();
EXPECT_EQ(3u, video()->EnsureUserAgentShadowRoot().CountChildren());
// Reset cc::layer to avoid crashes depending on timing.
SetFakeCcLayer(nullptr);
}
TEST_F(HTMLVideoElementTest, PictureInPictureInterstitial_Reattach) {
scoped_refptr<cc::Layer> layer = cc::Layer::Create();
SetFakeCcLayer(layer.get());
video()->SetBooleanAttribute(html_names::kControlsAttr, true);
video()->SetSrc("http://example.com/foo.mp4");
test::RunPendingTasks();
// Simulate entering Picture-in-Picture.
video()->OnEnteredPictureInPicture();
// Try detaching and reattaching. This should not crash.
GetDocument().body()->removeChild(video());
GetDocument().body()->appendChild(video());
GetDocument().body()->removeChild(video());
}
TEST_F(HTMLVideoElementTest, setPictureInPictureControls) {
EXPECT_FALSE(video()->HasPictureInPictureCustomControls());
std::vector<PictureInPictureControlInfo> test_controls;
test_controls.push_back(PictureInPictureControlInfo());
video()->SetPictureInPictureCustomControls(test_controls);
EXPECT_TRUE(video()->HasPictureInPictureCustomControls());
}
TEST_F(HTMLVideoElementTest, EffectivelyFullscreen_DisplayType) {
EXPECT_EQ(WebMediaPlayer::DisplayType::kInline, video()->DisplayType());
// Vector of data to use for tests. First value is to be set when calling
// SetIsEffectivelyFullscreen(). The second one is the expected DisplayType.
// This is testing all possible values of WebFullscreenVideoStatus and then
// sets the value back to a value that should put the DisplayType back to
// inline.
std::vector<std::pair<WebFullscreenVideoStatus, WebMediaPlayer::DisplayType>>
tests = {
{WebFullscreenVideoStatus::kNotEffectivelyFullscreen,
WebMediaPlayer::DisplayType::kInline},
{WebFullscreenVideoStatus::kFullscreenAndPictureInPictureEnabled,
WebMediaPlayer::DisplayType::kFullscreen},
{WebFullscreenVideoStatus::kFullscreenAndPictureInPictureDisabled,
WebMediaPlayer::DisplayType::kFullscreen},
{WebFullscreenVideoStatus::kNotEffectivelyFullscreen,
WebMediaPlayer::DisplayType::kInline},
};
for (const auto& test : tests) {
EXPECT_CALL(*MockWebMediaPlayer(), SetIsEffectivelyFullscreen(test.first));
EXPECT_CALL(*MockWebMediaPlayer(), OnDisplayTypeChanged(test.second));
video()->SetIsEffectivelyFullscreen(test.first);
EXPECT_EQ(test.second, video()->DisplayType());
}
}
} // namespace blink