blob: 6c464086695340955369b11e5ee7a14f48874355 [file] [log] [blame]
// Copyright 2015 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 "modules/wake_lock/ScreenWakeLock.h"
#include "core/dom/DOMImplementation.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentInit.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "platform/testing/URLTestHelpers.h"
#include "platform/testing/UnitTestHelpers.h"
#include "public/platform/InterfaceProvider.h"
#include "public/platform/Platform.h"
#include "public/platform/WebPageVisibilityState.h"
#include "public/platform/WebURLLoaderMockFactory.h"
#include "public/web/WebCache.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "web/WebLocalFrameImpl.h"
#include "web/tests/FrameTestHelpers.h"
#include <memory>
namespace {
using blink::ScreenWakeLock;
using device::mojom::blink::WakeLockService;
using device::mojom::blink::WakeLockServiceRequest;
// This class allows binding interface requests to a MockWakeLockService.
class MockInterfaceProvider : public blink::InterfaceProvider {
public:
MockInterfaceProvider() : m_wakeLockStatus(false) {}
~MockInterfaceProvider() {}
void getInterface(const char* name, mojo::ScopedMessagePipeHandle) override;
bool wakeLockStatus() const { return m_wakeLockStatus; }
void setWakeLockStatus(bool status) { m_wakeLockStatus = status; }
private:
// A mock WakeLockService used to intercept calls to the mojo methods.
class MockWakeLockService : public WakeLockService {
public:
MockWakeLockService(MockInterfaceProvider* registry,
WakeLockServiceRequest request)
: m_binding(this, std::move(request)), m_registry(registry) {}
~MockWakeLockService() {}
private:
// mojom::WakeLockService
void RequestWakeLock() override { m_registry->setWakeLockStatus(true); }
void CancelWakeLock() override { m_registry->setWakeLockStatus(false); }
mojo::Binding<WakeLockService> m_binding;
MockInterfaceProvider* const m_registry;
};
std::unique_ptr<MockWakeLockService> m_mockWakeLockService;
bool m_wakeLockStatus;
};
void MockInterfaceProvider::getInterface(const char* name,
mojo::ScopedMessagePipeHandle handle) {
m_mockWakeLockService.reset(new MockWakeLockService(
this, mojo::MakeRequest<WakeLockService>(std::move(handle))));
}
// A TestWebFrameClient to allow overriding the interfaceProvider() with a mock.
class TestWebFrameClient : public blink::FrameTestHelpers::TestWebFrameClient {
public:
~TestWebFrameClient() override = default;
blink::InterfaceProvider* interfaceProvider() override {
return &m_interfaceProvider;
}
private:
MockInterfaceProvider m_interfaceProvider;
};
class ScreenWakeLockTest : public testing::Test {
protected:
void SetUp() override {
m_webViewHelper.initialize(true, &m_testWebFrameClient);
blink::URLTestHelpers::registerMockedURLFromBaseURL(
blink::WebString::fromUTF8("http://example.com/"),
blink::WebString::fromUTF8("foo.html"));
loadFrame();
}
void TearDown() override {
blink::Platform::current()->getURLLoaderMockFactory()->unregisterAllURLs();
blink::WebCache::clear();
blink::testing::runPendingTasks();
}
void loadFrame() {
blink::FrameTestHelpers::loadFrame(m_webViewHelper.webView()->mainFrame(),
"http://example.com/foo.html");
m_webViewHelper.webView()->updateAllLifecyclePhases();
}
blink::LocalFrame* frame() {
DCHECK(m_webViewHelper.webView());
DCHECK(m_webViewHelper.webView()->mainFrameImpl());
return m_webViewHelper.webView()->mainFrameImpl()->frame();
}
blink::Screen* screen() {
DCHECK(frame());
DCHECK(frame()->localDOMWindow());
return frame()->localDOMWindow()->screen();
}
bool screenKeepAwake() {
DCHECK(screen());
return ScreenWakeLock::keepAwake(*screen());
}
bool clientKeepScreenAwake() {
return static_cast<MockInterfaceProvider*>(
m_testWebFrameClient.interfaceProvider())
->wakeLockStatus();
}
void setKeepAwake(bool keepAwake) {
DCHECK(screen());
ScreenWakeLock::setKeepAwake(*screen(), keepAwake);
// Let the notification sink through the mojo pipes.
blink::testing::runPendingTasks();
}
void show() {
DCHECK(m_webViewHelper.webView());
m_webViewHelper.webView()->setVisibilityState(
blink::WebPageVisibilityStateVisible, false);
// Let the notification sink through the mojo pipes.
blink::testing::runPendingTasks();
}
void hide() {
DCHECK(m_webViewHelper.webView());
m_webViewHelper.webView()->setVisibilityState(
blink::WebPageVisibilityStateHidden, false);
// Let the notification sink through the mojo pipes.
blink::testing::runPendingTasks();
}
// Order of these members is important as we need to make sure that
// m_testWebFrameClient outlives m_webViewHelper (destruction order)
TestWebFrameClient m_testWebFrameClient;
blink::FrameTestHelpers::WebViewHelper m_webViewHelper;
};
TEST_F(ScreenWakeLockTest, setAndReset) {
ASSERT_FALSE(screenKeepAwake());
ASSERT_FALSE(clientKeepScreenAwake());
setKeepAwake(true);
EXPECT_TRUE(screenKeepAwake());
EXPECT_TRUE(clientKeepScreenAwake());
setKeepAwake(false);
EXPECT_FALSE(screenKeepAwake());
EXPECT_FALSE(clientKeepScreenAwake());
}
TEST_F(ScreenWakeLockTest, hideWhenSet) {
ASSERT_FALSE(screenKeepAwake());
ASSERT_FALSE(clientKeepScreenAwake());
setKeepAwake(true);
hide();
EXPECT_TRUE(screenKeepAwake());
EXPECT_FALSE(clientKeepScreenAwake());
}
TEST_F(ScreenWakeLockTest, setWhenHidden) {
ASSERT_FALSE(screenKeepAwake());
ASSERT_FALSE(clientKeepScreenAwake());
hide();
setKeepAwake(true);
EXPECT_TRUE(screenKeepAwake());
EXPECT_FALSE(clientKeepScreenAwake());
}
TEST_F(ScreenWakeLockTest, showWhenSet) {
ASSERT_FALSE(screenKeepAwake());
ASSERT_FALSE(clientKeepScreenAwake());
hide();
setKeepAwake(true);
show();
EXPECT_TRUE(screenKeepAwake());
EXPECT_TRUE(clientKeepScreenAwake());
}
TEST_F(ScreenWakeLockTest, navigate) {
ASSERT_FALSE(screenKeepAwake());
ASSERT_FALSE(clientKeepScreenAwake());
setKeepAwake(true);
loadFrame();
EXPECT_FALSE(screenKeepAwake());
EXPECT_FALSE(clientKeepScreenAwake());
}
} // namespace