blob: f3205c234e4688d284c27d5a08140edd15dd0633 [file] [log] [blame]
// Copyright 2020 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 "android_webview/browser/aw_contents_lifecycle_notifier.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace android_webview {
class TestWebViewAppObserver : public WebViewAppStateObserver {
public:
TestWebViewAppObserver() = default;
~TestWebViewAppObserver() override = default;
// WebViewAppStateObserver.
void OnAppStateChanged(State state) override { state_ = state; }
WebViewAppStateObserver::State state() const { return state_; }
private:
WebViewAppStateObserver::State state_;
};
class TestAwContentsLifecycleNotifier : public AwContentsLifecycleNotifier {
public:
TestAwContentsLifecycleNotifier() = default;
~TestAwContentsLifecycleNotifier() override = default;
size_t GetAwContentsStateCount(AwContentsState state) const {
return state_count_[ToIndex(state)];
}
bool HasAwContentsInstanceForTesting() const {
return this->HasAwContentsInstance();
}
};
class AwContentsLifecycleNotifierTest : public testing::Test {
public:
WebViewAppStateObserver::State GetState() const { return observer_->state(); }
size_t GetAwContentsStateCount(
AwContentsLifecycleNotifier::AwContentsState state) const {
return notifier_->GetAwContentsStateCount(state);
}
bool HasAwContentsInstance() const {
return notifier_->HasAwContentsInstanceForTesting();
}
bool HasAwContentsEverCreated() const {
return notifier_->has_aw_contents_ever_created();
}
AwContentsLifecycleNotifier* notifier() { return notifier_.get(); }
void VerifyAwContentsStateCount(size_t unknown_count,
size_t foreground_count,
size_t background_count) {
ASSERT_EQ(GetAwContentsStateCount(
AwContentsLifecycleNotifier::AwContentsState::kDetached),
unknown_count);
ASSERT_EQ(GetAwContentsStateCount(
AwContentsLifecycleNotifier::AwContentsState::kForeground),
foreground_count);
ASSERT_EQ(GetAwContentsStateCount(
AwContentsLifecycleNotifier::AwContentsState::kBackground),
background_count);
}
protected:
// testing::Test.
void SetUp() override {
observer_ = std::make_unique<TestWebViewAppObserver>();
notifier_ = std::make_unique<TestAwContentsLifecycleNotifier>();
notifier_->AddObserver(observer_.get());
}
void TearDown() override { notifier_->RemoveObserver(observer_.get()); }
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestWebViewAppObserver> observer_;
std::unique_ptr<TestAwContentsLifecycleNotifier> notifier_;
};
TEST_F(AwContentsLifecycleNotifierTest, Created) {
const AwContents* fake_aw_contents = reinterpret_cast<const AwContents*>(1);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
ASSERT_FALSE(HasAwContentsEverCreated());
ASSERT_FALSE(HasAwContentsInstance());
notifier()->OnWebViewCreated(fake_aw_contents);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
ASSERT_TRUE(HasAwContentsInstance());
ASSERT_TRUE(HasAwContentsEverCreated());
notifier()->OnWebViewDestroyed(fake_aw_contents);
VerifyAwContentsStateCount(0, 0, 0);
ASSERT_FALSE(HasAwContentsInstance());
ASSERT_TRUE(HasAwContentsEverCreated());
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
}
TEST_F(AwContentsLifecycleNotifierTest, AttachToAndDetachFromWindow) {
const AwContents* fake_aw_contents = reinterpret_cast<const AwContents*>(1);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
ASSERT_FALSE(HasAwContentsEverCreated());
ASSERT_FALSE(HasAwContentsInstance());
notifier()->OnWebViewCreated(fake_aw_contents);
notifier()->OnWebViewAttachedToWindow(fake_aw_contents);
VerifyAwContentsStateCount(0, 0, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
ASSERT_TRUE(HasAwContentsInstance());
ASSERT_TRUE(HasAwContentsEverCreated());
notifier()->OnWebViewDetachedFromWindow(fake_aw_contents);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
ASSERT_TRUE(HasAwContentsInstance());
ASSERT_TRUE(HasAwContentsEverCreated());
notifier()->OnWebViewDestroyed(fake_aw_contents);
VerifyAwContentsStateCount(0, 0, 0);
ASSERT_FALSE(HasAwContentsInstance());
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
}
TEST_F(AwContentsLifecycleNotifierTest, WindowVisibleAndInvisible) {
const AwContents* fake_aw_contents = reinterpret_cast<const AwContents*>(1);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
ASSERT_FALSE(HasAwContentsEverCreated());
notifier()->OnWebViewCreated(fake_aw_contents);
notifier()->OnWebViewAttachedToWindow(fake_aw_contents);
notifier()->OnWebViewWindowBeVisible(fake_aw_contents);
VerifyAwContentsStateCount(0, 1u, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kForeground);
ASSERT_TRUE(HasAwContentsEverCreated());
notifier()->OnWebViewWindowBeInvisible(fake_aw_contents);
VerifyAwContentsStateCount(0, 0, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
notifier()->OnWebViewDetachedFromWindow(fake_aw_contents);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
notifier()->OnWebViewDestroyed(fake_aw_contents);
VerifyAwContentsStateCount(0, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
ASSERT_TRUE(HasAwContentsEverCreated());
}
TEST_F(AwContentsLifecycleNotifierTest, MultipleAwContents) {
const AwContents* fake_aw_contents1 = reinterpret_cast<const AwContents*>(1);
const AwContents* fake_aw_contents2 = reinterpret_cast<const AwContents*>(2);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
ASSERT_FALSE(HasAwContentsEverCreated());
notifier()->OnWebViewCreated(fake_aw_contents1);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
ASSERT_TRUE(HasAwContentsEverCreated());
notifier()->OnWebViewAttachedToWindow(fake_aw_contents1);
VerifyAwContentsStateCount(0, 0, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
notifier()->OnWebViewCreated(fake_aw_contents2);
VerifyAwContentsStateCount(1u, 0, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
notifier()->OnWebViewAttachedToWindow(fake_aw_contents2);
VerifyAwContentsStateCount(0, 0, 2u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
notifier()->OnWebViewWindowBeVisible(fake_aw_contents2);
VerifyAwContentsStateCount(0, 1u, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kForeground);
notifier()->OnWebViewWindowBeVisible(fake_aw_contents1);
VerifyAwContentsStateCount(0, 2u, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kForeground);
notifier()->OnWebViewDestroyed(fake_aw_contents2);
VerifyAwContentsStateCount(0, 1u, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kForeground);
notifier()->OnWebViewWindowBeInvisible(fake_aw_contents1);
VerifyAwContentsStateCount(0, 0, 1u);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kBackground);
notifier()->OnWebViewDetachedFromWindow(fake_aw_contents1);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
notifier()->OnWebViewDestroyed(fake_aw_contents1);
VerifyAwContentsStateCount(0, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kDestroyed);
notifier()->OnWebViewCreated(fake_aw_contents1);
VerifyAwContentsStateCount(1u, 0, 0);
ASSERT_EQ(GetState(), WebViewAppStateObserver::State::kUnknown);
ASSERT_TRUE(HasAwContentsEverCreated());
}
} // namespace android_webview