blob: 7527d9891a85cbd4bed5040dec6eb37b980c6ace [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h"
#include <memory>
#include <string>
#include <utility>
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
#include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
#include "content/public/browser/media_player_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/resource_load_info.mojom.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "extensions/buildflags/buildflags.h"
#include "net/base/ip_endpoint.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/constants.h"
#endif
namespace page_load_metrics {
namespace {
class TestPageLoadMetricsEmbedderInterface
: public PageLoadMetricsEmbedderInterface {
public:
explicit TestPageLoadMetricsEmbedderInterface(
PageLoadMetricsObserverTester* test)
: test_(test) {}
bool IsNewTabPageUrl(const GURL& url) override { return false; }
// Forward the registration logic to the test class so that derived classes
// can override the logic there without depending on the embedder interface.
void RegisterObservers(PageLoadTracker* tracker) override {
test_->RegisterObservers(tracker);
}
std::unique_ptr<base::OneShotTimer> CreateTimer() override {
auto timer = std::make_unique<test::WeakMockTimer>();
test_->SetMockTimer(timer->AsWeakPtr());
return std::move(timer);
}
bool IsPrerender(content::WebContents* web_contents) override {
return false;
}
bool IsExtensionUrl(const GURL& url) override { return false; }
private:
PageLoadMetricsObserverTester* test_;
DISALLOW_COPY_AND_ASSIGN(TestPageLoadMetricsEmbedderInterface);
};
} // namespace
PageLoadMetricsObserverTester::PageLoadMetricsObserverTester(
content::WebContents* web_contents,
content::RenderViewHostTestHarness* rfh_test_harness,
const RegisterObserversCallback& callback)
: register_callback_(callback),
web_contents_(web_contents),
rfh_test_harness_(rfh_test_harness),
observer_(MetricsWebContentsObserver::CreateForWebContents(
web_contents,
std::make_unique<TestPageLoadMetricsEmbedderInterface>(this))) {}
PageLoadMetricsObserverTester::~PageLoadMetricsObserverTester() {}
void PageLoadMetricsObserverTester::StartNavigation(const GURL& gurl) {
std::unique_ptr<content::NavigationSimulator> navigation =
content::NavigationSimulator::CreateBrowserInitiated(gurl,
web_contents());
navigation->Start();
}
void PageLoadMetricsObserverTester::NavigateWithPageTransitionAndCommit(
const GURL& url,
ui::PageTransition transition) {
auto simulator = PageTransitionIsWebTriggerable(transition)
? content::NavigationSimulator::CreateRendererInitiated(
url, rfh_test_harness_->main_rfh())
: content::NavigationSimulator::CreateBrowserInitiated(
url, web_contents());
simulator->SetTransition(transition);
simulator->Commit();
}
void PageLoadMetricsObserverTester::NavigateToUntrackedUrl() {
rfh_test_harness_->NavigateAndCommit(GURL(url::kAboutBlankURL));
}
void PageLoadMetricsObserverTester::SimulateTimingUpdate(
const mojom::PageLoadTiming& timing) {
SimulateTimingUpdate(timing, web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateTimingUpdate(
const mojom::PageLoadTiming& timing,
content::RenderFrameHost* rfh) {
SimulatePageLoadTimingUpdate(
timing, mojom::PageLoadMetadata(), mojom::PageLoadFeatures(),
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
mojom::DeferredResourceCounts(), rfh);
}
void PageLoadMetricsObserverTester::SimulateCpuTimingUpdate(
const mojom::CpuTiming& cpu_timing) {
SimulateCpuTimingUpdate(cpu_timing, web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateCpuTimingUpdate(
const mojom::CpuTiming& cpu_timing,
content::RenderFrameHost* rfh) {
auto timing = page_load_metrics::mojom::PageLoadTimingPtr(base::in_place);
page_load_metrics::InitPageLoadTimingForTest(timing.get());
SimulatePageLoadTimingUpdate(*timing, mojom::PageLoadMetadata(),
mojom::PageLoadFeatures(),
mojom::FrameRenderDataUpdate(), cpu_timing,
mojom::DeferredResourceCounts(), rfh);
}
void PageLoadMetricsObserverTester::SimulateTimingAndMetadataUpdate(
const mojom::PageLoadTiming& timing,
const mojom::PageLoadMetadata& metadata) {
SimulatePageLoadTimingUpdate(
timing, metadata, mojom::PageLoadFeatures(),
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
mojom::DeferredResourceCounts(), web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateMetadataUpdate(
const mojom::PageLoadMetadata& metadata,
content::RenderFrameHost* rfh) {
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
SimulatePageLoadTimingUpdate(timing, metadata, mojom::PageLoadFeatures(),
mojom::FrameRenderDataUpdate(),
mojom::CpuTiming(),
mojom::DeferredResourceCounts(), rfh);
}
void PageLoadMetricsObserverTester::SimulateFeaturesUpdate(
const mojom::PageLoadFeatures& new_features) {
SimulatePageLoadTimingUpdate(
mojom::PageLoadTiming(), mojom::PageLoadMetadata(), new_features,
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
mojom::DeferredResourceCounts(), web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateRenderDataUpdate(
const mojom::FrameRenderDataUpdate& render_data) {
SimulateRenderDataUpdate(render_data, web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateRenderDataUpdate(
const mojom::FrameRenderDataUpdate& render_data,
content::RenderFrameHost* rfh) {
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
SimulatePageLoadTimingUpdate(
timing, mojom::PageLoadMetadata(), mojom::PageLoadFeatures(), render_data,
mojom::CpuTiming(), mojom::DeferredResourceCounts(), rfh);
}
void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate(
const mojom::PageLoadTiming& timing,
const mojom::PageLoadMetadata& metadata,
const mojom::PageLoadFeatures& new_features,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTiming& cpu_timing,
const mojom::DeferredResourceCounts& new_deferred_resource_data,
content::RenderFrameHost* rfh) {
observer_->OnTimingUpdated(
rfh, timing.Clone(), metadata.Clone(), new_features.Clone(),
std::vector<mojom::ResourceDataUpdatePtr>(), render_data.Clone(),
cpu_timing.Clone(), new_deferred_resource_data.Clone());
// If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
// schedule a buffering timer, then fire it now so metrics are dispatched to
// observers.
base::MockOneShotTimer* mock_timer = GetMockTimer();
if (mock_timer && mock_timer->IsRunning())
mock_timer->Fire();
}
void PageLoadMetricsObserverTester::SimulateResourceDataUseUpdate(
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
SimulateResourceDataUseUpdate(resources, web_contents()->GetMainFrame());
}
void PageLoadMetricsObserverTester::SimulateResourceDataUseUpdate(
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
content::RenderFrameHost* render_frame_host) {
auto timing = mojom::PageLoadTimingPtr(base::in_place);
InitPageLoadTimingForTest(timing.get());
observer_->OnTimingUpdated(render_frame_host, std::move(timing),
mojom::PageLoadMetadataPtr(base::in_place),
mojom::PageLoadFeaturesPtr(base::in_place),
resources,
mojom::FrameRenderDataUpdatePtr(base::in_place),
mojom::CpuTimingPtr(base::in_place),
mojom::DeferredResourceCountsPtr(base::in_place));
}
void PageLoadMetricsObserverTester::SimulateLoadedResource(
const ExtraRequestCompleteInfo& info) {
SimulateLoadedResource(info, content::GlobalRequestID());
}
void PageLoadMetricsObserverTester::SimulateLoadedResource(
const ExtraRequestCompleteInfo& info,
const content::GlobalRequestID& request_id) {
if (info.resource_type == content::ResourceType::kMainFrame) {
ASSERT_NE(content::GlobalRequestID(), request_id)
<< "Main frame resources must have a GlobalRequestID.";
}
content::mojom::ResourceLoadInfo resource_load_info;
resource_load_info.url = info.url;
resource_load_info.was_cached = info.was_cached;
resource_load_info.raw_body_bytes = info.raw_body_bytes;
resource_load_info.total_received_bytes =
info.original_network_content_length;
resource_load_info.resource_type = info.resource_type;
resource_load_info.net_error = info.net_error;
resource_load_info.network_info = content::mojom::CommonNetworkInfo::New();
resource_load_info.network_info->remote_endpoint = info.remote_endpoint;
if (info.load_timing_info)
resource_load_info.load_timing_info = *info.load_timing_info;
else
resource_load_info.load_timing_info.request_start = base::TimeTicks::Now();
observer_->ResourceLoadComplete(web_contents()->GetMainFrame(), request_id,
resource_load_info);
}
void PageLoadMetricsObserverTester::SimulateFrameReceivedFirstUserActivation(
content::RenderFrameHost* render_frame_host) {
observer_->FrameReceivedFirstUserActivation(render_frame_host);
}
void PageLoadMetricsObserverTester::SimulateInputEvent(
const blink::WebInputEvent& event) {
observer_->OnInputEvent(event);
}
void PageLoadMetricsObserverTester::SimulateAppEnterBackground() {
observer_->FlushMetricsOnAppEnterBackground();
}
void PageLoadMetricsObserverTester::SimulateMediaPlayed() {
content::WebContentsObserver::MediaPlayerInfo video_type(
true /* has_video*/, true /* has_audio */);
content::RenderFrameHost* render_frame_host = web_contents()->GetMainFrame();
observer_->MediaStartedPlaying(video_type,
content::MediaPlayerId(render_frame_host, 0));
}
void PageLoadMetricsObserverTester::SimulateCookiesRead(
const GURL& url,
const GURL& first_party_url,
const net::CookieList& cookie_list,
bool blocked_by_policy) {
observer_->OnCookiesRead(url, first_party_url, cookie_list,
blocked_by_policy);
}
void PageLoadMetricsObserverTester::SimulateCookieChange(
const GURL& url,
const GURL& first_party_url,
const net::CanonicalCookie& cookie,
bool blocked_by_policy) {
observer_->OnCookieChange(url, first_party_url, cookie, blocked_by_policy);
}
void PageLoadMetricsObserverTester::SimulateDomStorageAccess(
const GURL& url,
const GURL& first_party_url,
bool local,
bool blocked_by_policy) {
observer_->OnDomStorageAccessed(url, first_party_url, local,
blocked_by_policy);
}
const PageLoadMetricsObserverDelegate&
PageLoadMetricsObserverTester::GetDelegateForCommittedLoad() const {
return observer_->GetDelegateForCommittedLoad();
}
void PageLoadMetricsObserverTester::RegisterObservers(
PageLoadTracker* tracker) {
if (!register_callback_.is_null())
register_callback_.Run(tracker);
}
} // namespace page_load_metrics