blob: a4b0c9ab12f289d96f600a4aa40c799929fb84eb [file] [log] [blame]
// Copyright 2017 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 "content/browser/screen_orientation/screen_orientation_provider.h"
#include "base/bind.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/screen_orientation_delegate.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
using device::mojom::ScreenOrientationLockResult;
namespace {
class FakeScreenOrientationDelegate : public ScreenOrientationDelegate {
public:
FakeScreenOrientationDelegate(bool supported, bool full_screen_required)
: supported_(supported), full_screen_required_(full_screen_required) {
ScreenOrientationProvider::SetDelegate(this);
}
~FakeScreenOrientationDelegate() override = default;
bool FullScreenRequired(WebContents* web_contents) override {
return full_screen_required_;
}
bool ScreenOrientationProviderSupported() override { return supported_; }
void Lock(WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) override {
lock_count_++;
}
void Unlock(WebContents* web_contents) override { unlock_count_++; }
int lock_count() const { return lock_count_; }
int unlock_count() const { return unlock_count_; }
private:
bool supported_ = true;
bool full_screen_required_ = false;
int lock_count_ = 0;
int unlock_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(FakeScreenOrientationDelegate);
};
class FakeWebContentsDelegate : public WebContentsDelegate {
public:
FakeWebContentsDelegate() = default;
~FakeWebContentsDelegate() override = default;
void EnterFullscreenModeForTab(
WebContents* web_contents,
const GURL& origin,
const blink::WebFullscreenOptions& options) override {
fullscreened_contents_ = web_contents;
}
void ExitFullscreenModeForTab(WebContents* web_contents) override {
fullscreened_contents_ = nullptr;
}
bool IsFullscreenForTabOrPending(const WebContents* web_contents) override {
return fullscreened_contents_ && web_contents == fullscreened_contents_;
}
private:
WebContents* fullscreened_contents_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeWebContentsDelegate);
};
void LockResultCallback(base::Optional<ScreenOrientationLockResult>* out_result,
ScreenOrientationLockResult result) {
*out_result = result;
}
} // namespace
class ScreenOrientationProviderTest : public RenderViewHostImplTestHarness {
public:
ScreenOrientationProviderTest() = default;
void SetUp() override {
content::RenderViewHostImplTestHarness::SetUp();
contents()->SetDelegate(&wc_delegate_);
}
// Helpers for testing ScreenOrientationProvider methods.
void CallLockAndGetResult(
blink::WebScreenOrientationLockType orientation,
base::Optional<ScreenOrientationLockResult>* out_result) {
contents()->GetScreenOrientationProviderForTesting()->LockOrientation(
orientation, base::BindOnce(&LockResultCallback, out_result));
base::RunLoop().RunUntilIdle();
}
void CallUnlock() {
contents()->GetScreenOrientationProviderForTesting()->UnlockOrientation();
}
private:
FakeWebContentsDelegate wc_delegate_;
};
// Lock operation is not available.
TEST_F(ScreenOrientationProviderTest, DelegateNotAvailableLockOnce) {
// No ScreenOrientationDelegate.
base::Optional<ScreenOrientationLockResult> result_1;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_1);
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_NOT_AVAILABLE,
*result_1);
// ScreenOrientationDelegate not supported.
FakeScreenOrientationDelegate delegate(false, false);
base::Optional<ScreenOrientationLockResult> result_2;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_2);
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_NOT_AVAILABLE,
*result_2);
}
// Full screen is not required by delegate, normally lock once.
TEST_F(ScreenOrientationProviderTest, DelegateLockOnce) {
// ScreenOrientationDelegate does not require full screen.
FakeScreenOrientationDelegate delegate(true, false);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
base::Optional<ScreenOrientationLockResult> result_1;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_1);
// Lock request is pending.
EXPECT_FALSE(result_1.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
}
// Full screen is required by delegate.
TEST_F(ScreenOrientationProviderTest, DelegateRequireFullScreenLockOnce) {
// ScreenOrientationDelegate requires full screen.
FakeScreenOrientationDelegate delegate(true, true);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
// Current web contents is not in full screen.
ASSERT_FALSE(contents()->IsFullscreenForCurrentTab());
base::Optional<ScreenOrientationLockResult> result_1;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_1);
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_FULLSCREEN_REQUIRED,
*result_1);
// Delegate did not apply any lock.
EXPECT_EQ(0, delegate.lock_count());
// Simulates entering full screen.
main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
base::Optional<ScreenOrientationLockResult> result_2;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_2);
// Lock request is pending.
EXPECT_FALSE(result_2.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
}
// Lock once, then unlock once, the pending lock request will be cancelled.
TEST_F(ScreenOrientationProviderTest, DelegateLockThenUnlock) {
FakeScreenOrientationDelegate delegate(true, false);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
base::Optional<ScreenOrientationLockResult> result_1;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_1);
// The lock request will be pending.
EXPECT_FALSE(result_1.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
EXPECT_EQ(0, delegate.unlock_count());
CallUnlock();
// The pending lock request is cancelled.
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_CANCELED,
result_1);
// Delegate did apply unlock once.
EXPECT_EQ(1, delegate.unlock_count());
}
// Lock twice, the first lock request will be cancelled by the second one.
TEST_F(ScreenOrientationProviderTest, DelegateLockThenLock) {
FakeScreenOrientationDelegate delegate(true, false);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
base::Optional<ScreenOrientationLockResult> result_1;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_1);
// The lock request will be pending.
EXPECT_FALSE(result_1.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
EXPECT_EQ(0, delegate.unlock_count());
base::Optional<ScreenOrientationLockResult> result_2;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result_2);
// The pending lock request is cancelled.
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_CANCELED,
result_1);
// The second one became pending.
EXPECT_FALSE(result_2.has_value());
// Delegate did apply lock once more.
EXPECT_EQ(2, delegate.lock_count());
EXPECT_EQ(0, delegate.unlock_count());
}
// Unlock won't be applied if no lock has been applied previously.
TEST_F(ScreenOrientationProviderTest, NoUnlockWithoutLock) {
FakeScreenOrientationDelegate delegate(true, false);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
CallUnlock();
// Delegate did not apply any unlock.
EXPECT_EQ(0, delegate.unlock_count());
}
// If lock already applied once in full screen, then unlock should be triggered
// once automatically when exiting full screen, and previous pending lock
// request will be cancelled.
TEST_F(ScreenOrientationProviderTest, UnlockWhenExitingFullScreen) {
// ScreenOrientationDelegate requires full screen.
FakeScreenOrientationDelegate delegate(true, true);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
// Simulates entering full screen.
main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
base::Optional<ScreenOrientationLockResult> result;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result);
// The lock request will be pending.
EXPECT_FALSE(result.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
EXPECT_EQ(0, delegate.unlock_count());
// Simulates exiting full screen.
main_test_rfh()->OnMessageReceived(
FrameHostMsg_ExitFullscreen(main_test_rfh()->GetRoutingID()));
ASSERT_FALSE(contents()->IsFullscreenForCurrentTab());
// The pending lock request is cancelled.
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_CANCELED,
result);
// Delegate did apply unlock once.
EXPECT_EQ(1, delegate.unlock_count());
}
// If lock already applied once, then unlock should be triggered once
// automatically when navigating to other web page, and previous pending lock
// request will be cancelled.
TEST_F(ScreenOrientationProviderTest, UnlockWhenNavigation) {
FakeScreenOrientationDelegate delegate(true, false);
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
base::Optional<ScreenOrientationLockResult> result;
CallLockAndGetResult(blink::WebScreenOrientationLockType::
kWebScreenOrientationLockLandscapeSecondary,
&result);
// The lock request will be pending.
EXPECT_FALSE(result.has_value());
// Delegate did apply lock once.
EXPECT_EQ(1, delegate.lock_count());
EXPECT_EQ(0, delegate.unlock_count());
// Navigate to another site.
const GURL another_url("http://www.google.com/abc.html");
contents()->NavigateAndCommit(another_url);
// The pending lock request is cancelled.
EXPECT_EQ(ScreenOrientationLockResult::
SCREEN_ORIENTATION_LOCK_RESULT_ERROR_CANCELED,
result);
// Delegate did apply unlock once.
EXPECT_EQ(1, delegate.unlock_count());
}
} // namespace content