blob: 2d9ab7336104021bf40c5fa30301c8dcea46c48f [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 "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "net/base/filename_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "weblayer/browser/browser_impl.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/public/navigation.h"
#include "weblayer/public/navigation_controller.h"
#include "weblayer/public/tab.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/test_navigation_observer.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
class MinimalBrowserPersisterTest : public WebLayerBrowserTest {
public:
MinimalBrowserPersisterTest() = default;
~MinimalBrowserPersisterTest() override = default;
// WebLayerBrowserTest:
void SetUpOnMainThread() override {
WebLayerBrowserTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
browser_ = Browser::Create(GetProfile(), nullptr);
tab_ = static_cast<TabImpl*>(browser_->CreateTab());
browser_->SetActiveTab(tab_);
}
void PostRunTestOnMainThread() override {
tab_ = nullptr;
browser_.reset();
WebLayerBrowserTest::PostRunTestOnMainThread();
}
GURL url1() { return embedded_test_server()->GetURL("/simple_page.html"); }
GURL url2() { return embedded_test_server()->GetURL("/simple_page2.html"); }
// Persists the current state, then recreates the browser. See
// BrowserImpl::GetMinimalPersistenceState() for details on
// |max_size_in_bytes|, 0 means use the default value.
void RecreateBrowserFromCurrentState(int max_size_in_bytes = 0) {
Browser::PersistenceInfo persistence_info;
persistence_info.minimal_state =
browser_impl()->GetMinimalPersistenceState(max_size_in_bytes);
tab_ = nullptr;
browser_ = Browser::Create(GetProfile(), &persistence_info);
// There is always at least one tab created (even if restore fails).
ASSERT_GE(browser_->GetTabs().size(), 1u);
tab_ = static_cast<TabImpl*>(browser_->GetTabs()[0]);
}
protected:
BrowserImpl* browser_impl() {
return static_cast<BrowserImpl*>(browser_.get());
}
std::unique_ptr<Browser> browser_;
TabImpl* tab_ = nullptr;
};
IN_PROC_BROWSER_TEST_F(MinimalBrowserPersisterTest, SingleTab) {
NavigateAndWaitForCompletion(url1(), tab_);
ASSERT_NO_FATAL_FAILURE(RecreateBrowserFromCurrentState());
EXPECT_EQ(tab_, browser_->GetActiveTab());
TestNavigationObserver observer(
url1(), TestNavigationObserver::NavigationEvent::kCompletion,
browser_->GetActiveTab());
observer.Wait();
EXPECT_EQ(1, tab_->GetNavigationController()->GetNavigationListSize());
}
IN_PROC_BROWSER_TEST_F(MinimalBrowserPersisterTest, TwoTabs) {
NavigateAndWaitForCompletion(url1(), tab_);
Tab* tab2 = browser_->CreateTab();
NavigateAndWaitForCompletion(url2(), tab2);
browser_->SetActiveTab(tab2);
// Shutdown the service and run the assertions twice to ensure we handle
// correctly storing state of tabs that need to be reloaded.
for (int i = 0; i < 2; ++i) {
ASSERT_NO_FATAL_FAILURE(RecreateBrowserFromCurrentState());
tab2 = nullptr;
ASSERT_EQ(2u, browser_->GetTabs().size()) << "iteration " << i;
tab2 = browser_->GetTabs()[1];
EXPECT_EQ(tab2, browser_->GetActiveTab()) << "iteration " << i;
// The first tab shouldn't have loaded yet, as it's not active.
EXPECT_TRUE(tab_->web_contents()->GetController().NeedsReload())
<< "iteration " << i;
EXPECT_EQ(1, tab2->GetNavigationController()->GetNavigationListSize())
<< "iteration " << i;
TestNavigationObserver observer(
url2(), TestNavigationObserver::NavigationEvent::kCompletion, tab2);
}
}
IN_PROC_BROWSER_TEST_F(MinimalBrowserPersisterTest, PendingSkipped) {
NavigateAndWaitForCompletion(url1(), tab_);
tab_->GetNavigationController()->Navigate(url2());
ASSERT_NO_FATAL_FAILURE(RecreateBrowserFromCurrentState());
EXPECT_EQ(tab_, browser_->GetActiveTab());
TestNavigationObserver observer(
url1(), TestNavigationObserver::NavigationEvent::kCompletion,
browser_->GetActiveTab());
observer.Wait();
ASSERT_EQ(1, tab_->GetNavigationController()->GetNavigationListSize());
}
IN_PROC_BROWSER_TEST_F(MinimalBrowserPersisterTest, TwoNavs) {
NavigateAndWaitForCompletion(url1(), tab_);
NavigateAndWaitForCompletion(url2(), tab_);
ASSERT_NO_FATAL_FAILURE(RecreateBrowserFromCurrentState());
TabImpl* restored_tab = tab_;
EXPECT_EQ(restored_tab, browser_->GetActiveTab());
TestNavigationObserver observer(
url2(), TestNavigationObserver::NavigationEvent::kCompletion,
restored_tab);
observer.Wait();
ASSERT_EQ(2,
restored_tab->GetNavigationController()->GetNavigationListSize());
content::NavigationController& nav_controller =
restored_tab->web_contents()->GetController();
EXPECT_EQ(1, nav_controller.GetCurrentEntryIndex());
EXPECT_EQ(url1(), nav_controller.GetEntryAtIndex(0)->GetURL());
EXPECT_EQ(url2(), nav_controller.GetEntryAtIndex(1)->GetURL());
}
IN_PROC_BROWSER_TEST_F(MinimalBrowserPersisterTest, Overflow) {
std::string url_string(2048, 'a');
const std::string data = "data:,";
url_string.replace(0, data.size(), data);
NavigateAndWaitForCompletion(GURL(url_string), tab_);
ASSERT_NO_FATAL_FAILURE(RecreateBrowserFromCurrentState(2048));
TabImpl* restored_tab = tab_;
EXPECT_EQ(restored_tab, browser_->GetActiveTab());
EXPECT_EQ(0, restored_tab->web_contents()->GetController().GetEntryCount());
EXPECT_TRUE(restored_tab->web_contents()->GetController().GetPendingEntry() ==
nullptr);
}
} // namespace weblayer