blob: 33c7965c0de090a4075ff0d379e57a7dadde52bd [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/bind.h"
#include "content/public/browser/navigation_handle_user_data.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/web_contents_observer_test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
namespace content {
namespace {
class Data : public NavigationHandleUserData<Data> {
public:
~Data() override = default;
base::WeakPtr<Data> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
const std::string& value() const { return value_; }
private:
Data(NavigationHandle& navigation, std::string value) : value_(value) {}
friend class NavigationHandleUserData<Data>;
std::string value_;
base::WeakPtrFactory<Data> weak_ptr_factory_{this};
NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
};
NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(Data);
} // namespace
class NavigationHandleUserDataBrowserTest : public ContentBrowserTest {
public:
~NavigationHandleUserDataBrowserTest() override = default;
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
ContentBrowserTest::SetUpOnMainThread();
}
WebContentsImpl* web_contents() const {
return static_cast<WebContentsImpl*>(shell()->web_contents());
}
RenderFrameHostImpl* top_frame_host() {
return web_contents()->GetPrimaryFrameTree().root()->current_frame_host();
}
};
IN_PROC_BROWSER_TEST_F(NavigationHandleUserDataBrowserTest,
SuccessfulNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
TestNavigationManager navigation_manager(web_contents(), url);
// Start a navigation.
shell()->LoadURL(url);
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
// Attach some data to the navigation.
Data::CreateForNavigationHandle(*navigation_manager.GetNavigationHandle(),
"data");
// Check that we can retrieve the data.
base::WeakPtr<Data> data =
Data::GetForNavigationHandle(*navigation_manager.GetNavigationHandle())
->GetWeakPtr();
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
// Wait for the navigation to finish.
bool did_finish_navigation = false;
NavigationFinishObserver dfn(
web_contents(),
base::BindLambdaForTesting([&](NavigationHandle* navigation) {
EXPECT_TRUE(navigation->HasCommitted());
ASSERT_TRUE(Data::GetForNavigationHandle(*navigation));
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
did_finish_navigation = true;
}));
ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
EXPECT_TRUE(did_finish_navigation);
// Ensure that the data is deleted after navigation finished.
EXPECT_FALSE(data);
}
IN_PROC_BROWSER_TEST_F(NavigationHandleUserDataBrowserTest, FailedNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
TestNavigationManager navigation_manager(web_contents(), url);
// Start a navigation.
shell()->LoadURL(url);
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
// Attach some data to the navigation.
Data::CreateForNavigationHandle(*navigation_manager.GetNavigationHandle(),
"data");
// Check that we can retrieve the data.
base::WeakPtr<Data> data =
Data::GetForNavigationHandle(*navigation_manager.GetNavigationHandle())
->GetWeakPtr();
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
// Wait for DidFinishNavigation event.
bool did_finish_navigation = false;
NavigationFinishObserver dfn(
web_contents(),
base::BindLambdaForTesting([&](NavigationHandle* navigation) {
EXPECT_TRUE(!navigation->HasCommitted());
ASSERT_TRUE(Data::GetForNavigationHandle(*navigation));
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
did_finish_navigation = true;
}));
shell()->Stop();
EXPECT_TRUE(did_finish_navigation);
// Ensure that the data is deleted after navigation finished.
EXPECT_FALSE(data);
}
IN_PROC_BROWSER_TEST_F(NavigationHandleUserDataBrowserTest, VeryEarlyAttach) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
TestNavigationManager navigation_manager(web_contents(), url);
int64_t navigation_id;
base::WeakPtr<Data> data;
// Expect that the data will be available inside DidStartNavigation and
// DidFinishNavigation.
bool did_start_navigation = false;
NavigationStartObserver dsn(
web_contents(),
base::BindLambdaForTesting([&](NavigationHandle* navigation) {
// Attach some data to the navigation.
Data::CreateForNavigationHandle(*navigation, "data");
ASSERT_TRUE(Data::GetForNavigationHandle(*navigation));
EXPECT_EQ(Data::GetForNavigationHandle(*navigation)->value(), "data");
did_start_navigation = true;
}));
bool did_finish_navigation = false;
NavigationFinishObserver dfn(
web_contents(),
base::BindLambdaForTesting([&](NavigationHandle* navigation) {
EXPECT_EQ(navigation_id, navigation->GetNavigationId());
ASSERT_TRUE(Data::GetForNavigationHandle(*navigation));
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
did_finish_navigation = true;
}));
// Start a navigation.
auto* web_contents_impl =
static_cast<WebContentsImpl*>(shell()->web_contents());
web_contents_impl->GetController().LoadURLWithParams(
NavigationController::LoadURLParams(url));
auto* navigation =
web_contents_impl->GetPrimaryFrameTree().root()->navigation_request();
ASSERT_TRUE(navigation);
navigation_id = navigation->GetNavigationId();
// Check that we can retrieve the data.
data = Data::GetForNavigationHandle(*navigation_manager.GetNavigationHandle())
->GetWeakPtr();
ASSERT_TRUE(data);
EXPECT_EQ(data->value(), "data");
// Wait for the navigation to finish.
ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
EXPECT_TRUE(did_start_navigation);
EXPECT_TRUE(did_finish_navigation);
// Ensure that the data is deleted after navigation finished.
EXPECT_FALSE(data);
}
} // namespace content