#ifndef CONTENT_BROWSER_BACK_FORWARD_CACHE_BROWSERTEST_H_
#define CONTENT_BROWSER_BACK_FORWARD_CACHE_BROWSERTEST_H_
#include <memory>
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/hash/hash.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_logging_settings.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/browser/back_forward_cache_test_util.h"
#include "content/browser/renderer_host/page_lifecycle_state_manager.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_host_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom-blink.h"
namespace content {
using NotRestoredReasons =
BackForwardCacheCanStoreDocumentResult::NotRestoredReasons;
using NotRestoredReason = BackForwardCacheMetrics::NotRestoredReason;
using ReasonsMatcher = testing::Matcher<
const blink::mojom::BackForwardCacheNotRestoredReasonsPtr&>;
using SameOriginMatcher = testing::Matcher<
const blink::mojom::SameOriginBfcacheNotRestoredDetailsPtr&>;
MATCHER(InBackForwardCache, "") {
return arg->IsInBackForwardCache();
}
MATCHER(Deleted, "") {
return arg->deleted();
}
std::initializer_list<RenderFrameHostImpl*> Elements(
std::initializer_list<RenderFrameHostImpl*> t);
enum class TestFrameType {
kMainFrame,
kSubFrame,
kSubFrameOfSubframe,
};
class BackForwardCacheBrowserTest
: public ContentBrowserTest,
public WebContentsObserver,
public BackForwardCacheMetrics::TestObserver,
public BackForwardCacheMetricsTestMatcher {
public:
BackForwardCacheBrowserTest();
~BackForwardCacheBrowserTest() override;
void NotifyNotRestoredReasons(
std::unique_ptr<BackForwardCacheCanStoreTreeResult> tree_result) override;
protected:
void SetUpCommandLine(base::CommandLine* command_line) override;
void SetUpInProcessBrowserTestFixture() override;
void TearDownInProcessBrowserTestFixture() override;
void SetupFeaturesAndParameters();
void EnableFeatureAndSetParams(const base::Feature& feature,
std::string param_name,
std::string param_value);
void DisableFeature(const base::Feature& feature);
void SetUpOnMainThread() override;
void TearDownOnMainThread() override;
WebContentsImpl* web_contents() const;
RenderFrameHostImpl* current_frame_host();
RenderFrameHostManager* render_frame_host_manager();
std::string DepictFrameTree(FrameTreeNode* node);
bool HistogramContainsIntValue(base::HistogramBase::Sample sample,
std::vector<base::Bucket> histogram_values);
void EvictByJavaScript(RenderFrameHostImpl* rfh);
void StartRecordingEvents(RenderFrameHostImpl* rfh);
void MatchEventList(RenderFrameHostImpl* rfh,
base::Value list,
base::Location location = base::Location::Current());
net::EmbeddedTestServer* CreateHttpsServer();
net::EmbeddedTestServer* https_server();
void DoNotFailForUnexpectedMessagesWhileCached();
RenderFrameHostImpl* NavigateToPageWithImage(const GURL& page_url);
void AcquireKeyboardLock(RenderFrameHostImpl* rfh);
void ReleaseKeyboardLock(RenderFrameHostImpl* rfh);
void NavigateAndBlock(GURL url, int history_offset);
static testing::Matcher<BackForwardCacheCanStoreDocumentResult>
MatchesDocumentResult(testing::Matcher<NotRestoredReasons> not_stored,
BlockListedFeatures block_listed);
ReasonsMatcher MatchesNotRestoredReasons(
const testing::Matcher<blink::mojom::BFCacheBlocked>& blocked,
const absl::optional<testing::Matcher<std::string>>& id,
const absl::optional<testing::Matcher<std::string>>& name,
const absl::optional<testing::Matcher<std::string>>& src,
const absl::optional<SameOriginMatcher>& same_origin_details);
SameOriginMatcher MatchesSameOriginDetails(
const testing::Matcher<std::string>& url,
const std::vector<testing::Matcher<std::string>>& reasons,
const std::vector<ReasonsMatcher>& children);
BackForwardCacheCanStoreTreeResult* GetTreeResult() {
return tree_result_.get();
}
void InstallUnloadHandlerOnMainFrame();
void InstallUnloadHandlerOnSubFrame();
EvalJsResult GetUnloadRunCount();
[[nodiscard]] bool AddBlocklistedFeature(RenderFrameHost* rfh);
void ExpectNotRestoredDueToBlocklistedFeature(base::Location location);
const ukm::TestAutoSetUkmRecorder& ukm_recorder() override;
const base::HistogramTester& histogram_tester() override;
private:
content::ContentMockCertVerifier mock_cert_verifier_;
base::test::ScopedFeatureList feature_list_;
logging::ScopedVmoduleSwitches vmodule_switches_;
FrameTreeVisualizer visualizer_;
std::unique_ptr<net::EmbeddedTestServer> https_server_;
std::map<base::test::FeatureRef, std::map<std::string, std::string>>
features_with_params_;
std::vector<base::test::FeatureRef> disabled_features_;
std::unique_ptr<ukm::TestAutoSetUkmRecorder> ukm_recorder_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
std::unique_ptr<BackForwardCacheCanStoreTreeResult> tree_result_;
bool fail_for_unexpected_messages_while_cached_ = true;
};
[[nodiscard]] bool WaitForDOMContentLoaded(RenderFrameHostImpl* rfh);
class HighCacheSizeBackForwardCacheBrowserTest
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override;
const size_t kBackForwardCacheSize = 5;
};
class BackForwardCacheUnloadBrowserTest : public BackForwardCacheBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
class PageLifecycleStateManagerTestDelegate
: public PageLifecycleStateManager::TestDelegate {
public:
explicit PageLifecycleStateManagerTestDelegate(
PageLifecycleStateManager* manager);
~PageLifecycleStateManagerTestDelegate() override;
[[nodiscard]] bool WaitForInBackForwardCacheAck();
void OnStoreInBackForwardCacheSent(base::OnceClosure cb);
void OnDisableJsEvictionSent(base::OnceClosure cb);
void OnRestoreFromBackForwardCacheSent(base::OnceClosure cb);
private:
void OnLastAcknowledgedStateChanged(
const blink::mojom::PageLifecycleState& old_state,
const blink::mojom::PageLifecycleState& new_state) override;
void OnUpdateSentToRenderer(
const blink::mojom::PageLifecycleState& new_state) override;
void OnDeleted() override;
raw_ptr<PageLifecycleStateManager, DanglingUntriaged> manager_;
base::OnceClosure store_in_back_forward_cache_sent_;
base::OnceClosure store_in_back_forward_cache_ack_received_;
base::OnceClosure restore_from_back_forward_cache_sent_;
base::OnceClosure disable_eviction_sent_;
};
EvalJsResult GetLocalStorage(RenderFrameHostImpl* rfh, std::string key);
}
#endif