Commit 2f220c33 authored by Hayato Ito's avatar Hayato Ito Committed by Commit Bot

Revert "predictor: Switch to WebContentsObserver to observe resource loads."

This reverts commit e9fcce49.

Reason for revert:
Findit identified the culprit r565609 with confidence 70.0%.
See https://bugs.chromium.org/p/chromium/issues/detail?id=851232


Original change's description:
> predictor: Switch to WebContentsObserver to observe resource loads.
> 
> This CL is needed to make the preconnect predictor work with the Network
> Service. The CL removes the LoadingPredictorObserver class that has been
> notified by the ChromeResourceDispatcherHostDelegate and introduces instead the
> LoadingPredictorTabHelper which implements the WebContentsObserver to notify
> the predictor about resource loads.
> 
> All uses of the net::URLRequest and predictors::URLRequestSummary was replaced
> by using the predictors::NavigationID or the content::mojom::ResourceLoadInfo.
> 
> The WebContentsObserver::ResourceLoadComplete() should work with and
> without the Network Service, so we don't have to keep the old path.
> 
> Bug: 809583
> Change-Id: I05c0aa97cfab1d773285633e6c5c3ef6a91367ca
> Reviewed-on: https://chromium-review.googlesource.com/1039526
> Commit-Queue: Alexandr Ilin <alexilin@chromium.org>
> Reviewed-by: Matt Menke <mmenke@chromium.org>
> Reviewed-by: Lei Zhang <thestig@chromium.org>
> Reviewed-by: Michael Wasserman <msw@chromium.org>
> Reviewed-by: Benoit L <lizeb@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#565609}

TBR=msw@chromium.org,thestig@chromium.org,mmenke@chromium.org,lizeb@chromium.org,alexilin@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 809583
Change-Id: If1bf3e4b6e98fbd716b9b994b0ee0c69cafc7036
Reviewed-on: https://chromium-review.googlesource.com/1094955Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Commit-Queue: Hayato Ito <hayato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565945}
parent b8771c71
......@@ -786,6 +786,8 @@ jumbo_split_static_library("browser") {
"net/dns_probe_service.h",
"net/file_downloader.cc",
"net/file_downloader.h",
"net/loading_predictor_observer.cc",
"net/loading_predictor_observer.h",
"net/net_error_diagnostics_dialog.h",
"net/net_error_diagnostics_dialog_win.cc",
"net/net_error_tab_helper.cc",
......@@ -1090,8 +1092,6 @@ jumbo_split_static_library("browser") {
"predictors/loading_predictor_config.h",
"predictors/loading_predictor_factory.cc",
"predictors/loading_predictor_factory.h",
"predictors/loading_predictor_tab_helper.cc",
"predictors/loading_predictor_tab_helper.h",
"predictors/loading_stats_collector.cc",
"predictors/loading_stats_collector.h",
"predictors/preconnect_manager.cc",
......@@ -1106,6 +1106,8 @@ jumbo_split_static_library("browser") {
"predictors/resource_prefetch_common.h",
"predictors/resource_prefetch_predictor.cc",
"predictors/resource_prefetch_predictor.h",
"predictors/resource_prefetch_predictor_tab_helper.cc",
"predictors/resource_prefetch_predictor_tab_helper.h",
"predictors/resource_prefetch_predictor_tables.cc",
"predictors/resource_prefetch_predictor_tables.h",
"prefs/browser_prefs.cc",
......
......@@ -25,6 +25,7 @@
#include "chrome/browser/loader/chrome_navigation_data.h"
#include "chrome/browser/loader/predictor_resource_throttle.h"
#include "chrome/browser/loader/safe_browsing_resource_throttle.h"
#include "chrome/browser/net/loading_predictor_observer.h"
#include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/plugins/plugin_utils.h"
......@@ -374,9 +375,7 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning(
ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
client_hints::RequestBeginning(request, io_data->GetCookieSettings());
#if BUILDFLAG(ENABLE_OFFLINE_PAGES) || BUILDFLAG(ENABLE_NACL)
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
#endif
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
// TODO(petewil): Unify the safe browsing request and the metrics observer
......@@ -441,6 +440,11 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning(
AppendComponentUpdaterThrottles(request, *info, resource_context,
resource_type, throttles);
#endif // BUILDFLAG(ENABLE_NACL)
if (io_data->loading_predictor_observer()) {
io_data->loading_predictor_observer()->OnRequestStarted(
request, resource_type, info->GetWebContentsGetterForRequest());
}
}
void ChromeResourceDispatcherHostDelegate::DownloadStarting(
......@@ -618,6 +622,10 @@ void ChromeResourceDispatcherHostDelegate::OnResponseStarted(
}
#endif
if (io_data->loading_predictor_observer())
io_data->loading_predictor_observer()->OnResponseStarted(
request, info->GetWebContentsGetterForRequest());
// Update the PreviewsState for main frame response if needed.
if (previews::HasEnabledPreviews(response->head.previews_state) &&
info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME &&
......@@ -680,6 +688,12 @@ void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
signin::ProcessAccountConsistencyResponseHeaders(request, redirect_url,
io_data->IsOffTheRecord());
if (io_data->loading_predictor_observer()) {
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
io_data->loading_predictor_observer()->OnRequestRedirected(
request, redirect_url, info->GetWebContentsGetterForRequest());
}
if (io_data->policy_header_helper())
io_data->policy_header_helper()->AddPolicyHeaders(redirect_url, request);
}
......
// 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/net/loading_predictor_observer.h"
#include <memory>
#include <string>
#include <utility>
#include "base/metrics/histogram_macros.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
namespace content {
class WebContents;
}
using content::BrowserThread;
using predictors::LoadingPredictor;
using predictors::LoadingDataCollector;
using predictors::URLRequestSummary;
namespace {
// Enum for measuring statistics pertaining to observed request, responses and
// redirects.
enum RequestStats {
REQUEST_STATS_TOTAL_RESPONSES = 0,
REQUEST_STATS_TOTAL_PROCESSED_RESPONSES = 1,
REQUEST_STATS_NO_RESOURCE_REQUEST_INFO = 2, // Not recorded (never was).
REQUEST_STATS_NO_RENDER_FRAME_ID_FROM_REQUEST_INFO = 3, // Not recorded.
REQUEST_STATS_MAX = 4,
};
// Specific to main frame requests.
enum MainFrameRequestStats {
MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS = 0,
MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS = 1,
MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS = 2,
MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS = 3,
MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES = 4,
MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES = 5,
MAIN_FRAME_REQUEST_STATS_MAX = 6,
};
void ReportRequestStats(RequestStats stat) {
UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.RequestStats", stat,
REQUEST_STATS_MAX);
}
void ReportMainFrameRequestStats(MainFrameRequestStats stat) {
UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.MainFrameRequestStats",
stat, MAIN_FRAME_REQUEST_STATS_MAX);
}
bool TryToFillNavigationID(
predictors::NavigationID* navigation_id,
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* web_contents = web_contents_getter.Run();
if (!web_contents)
return false;
*navigation_id =
predictors::NavigationID(web_contents, main_frame_url, creation_time);
// A WebContents might be associated with something that is not a tab.
// In this case tab_id will be -1 and is_valid() will return false.
return navigation_id->is_valid();
}
} // namespace
namespace chrome_browser_net {
LoadingPredictorObserver::LoadingPredictorObserver(LoadingPredictor* predictor)
: predictor_(predictor->GetWeakPtr()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
LoadingPredictorObserver::~LoadingPredictorObserver() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::IO));
}
void LoadingPredictorObserver::OnRequestStarted(
net::URLRequest* request,
content::ResourceType resource_type,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS);
if (!LoadingDataCollector::ShouldRecordRequest(request, resource_type))
return;
auto summary = std::make_unique<URLRequestSummary>();
summary->resource_type = resource_type;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&LoadingPredictorObserver::OnRequestStartedOnUIThread,
base::Unretained(this), std::move(summary),
web_contents_getter, request->site_for_cookies(),
request->creation_time()));
if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS);
}
void LoadingPredictorObserver::OnRequestRedirected(
net::URLRequest* request,
const GURL& redirect_url,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
if (request_info &&
request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS);
}
if (!LoadingDataCollector::ShouldRecordRedirect(request))
return;
auto summary = std::make_unique<URLRequestSummary>();
if (!URLRequestSummary::SummarizeResponse(*request, summary.get())) {
return;
}
summary->redirect_url = redirect_url;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&LoadingPredictorObserver::OnRequestRedirectedOnUIThread,
base::Unretained(this), std::move(summary),
web_contents_getter, request->site_for_cookies(),
request->creation_time()));
if (request_info &&
request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS);
}
}
void LoadingPredictorObserver::OnResponseStarted(
net::URLRequest* request,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ReportRequestStats(REQUEST_STATS_TOTAL_RESPONSES);
const content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
if (request_info &&
request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES);
}
if (!LoadingDataCollector::ShouldRecordResponse(request))
return;
auto summary = std::make_unique<URLRequestSummary>();
if (!URLRequestSummary::SummarizeResponse(*request, summary.get())) {
return;
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&LoadingPredictorObserver::OnResponseStartedOnUIThread,
base::Unretained(this), std::move(summary),
web_contents_getter, request->site_for_cookies(),
request->creation_time()));
ReportRequestStats(REQUEST_STATS_TOTAL_PROCESSED_RESPONSES);
if (request_info &&
request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES);
}
}
void LoadingPredictorObserver::OnRequestStartedOnUIThread(
std::unique_ptr<URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter,
main_frame_url, creation_time)) {
return;
}
if (summary->resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
predictor_->OnMainFrameRequest(*summary);
predictor_->loading_data_collector()->RecordURLRequest(*summary);
}
void LoadingPredictorObserver::OnRequestRedirectedOnUIThread(
std::unique_ptr<URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter,
main_frame_url, creation_time)) {
return;
}
if (summary->resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
predictor_->OnMainFrameRedirect(*summary);
predictor_->loading_data_collector()->RecordURLRedirect(*summary);
}
void LoadingPredictorObserver::OnResponseStartedOnUIThread(
std::unique_ptr<URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter,
main_frame_url, creation_time)) {
return;
}
if (summary->resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
predictor_->OnMainFrameResponse(*summary);
predictor_->loading_data_collector()->RecordURLResponse(*summary);
}
} // namespace chrome_browser_net
// 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.
#ifndef CHROME_BROWSER_NET_LOADING_PREDICTOR_OBSERVER_H_
#define CHROME_BROWSER_NET_LOADING_PREDICTOR_OBSERVER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/resource_prefetch_predictor.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_type.h"
namespace net {
class URLRequest;
}
class GURL;
namespace chrome_browser_net {
// Observes resource requests in the ResourceDispatcherHostDelegate and notifies
// the LoadingPredictor about the ones it is interested in.
// - Has an instance per profile, and is owned by the corresponding
// ProfileIOData.
// - Needs to be constructed on UI thread. Can be destroyed on UI or IO thread.
// As for member functions, public members are meant to be called on the IO
// thread and private members from the UI thread.
class LoadingPredictorObserver {
public:
explicit LoadingPredictorObserver(predictors::LoadingPredictor* predictor);
~LoadingPredictorObserver();
// Parts of the ResourceDispatcherHostDelegate that we want to observe.
void OnRequestStarted(net::URLRequest* request,
content::ResourceType resource_type,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter);
void OnRequestRedirected(
net::URLRequest* request,
const GURL& redirect_url,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter);
void OnResponseStarted(net::URLRequest* request,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter);
private:
void OnRequestStartedOnUIThread(
std::unique_ptr<predictors::URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const;
void OnRequestRedirectedOnUIThread(
std::unique_ptr<predictors::URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const;
void OnResponseStartedOnUIThread(
std::unique_ptr<predictors::URLRequestSummary> summary,
const content::ResourceRequestInfo::WebContentsGetter&
web_contents_getter,
const GURL& main_frame_url,
const base::TimeTicks& creation_time) const;
// Owned by profile.
base::WeakPtr<predictors::LoadingPredictor> predictor_;
DISALLOW_COPY_AND_ASSIGN(LoadingPredictorObserver);
};
} // namespace chrome_browser_net
#endif // CHROME_BROWSER_NET_LOADING_PREDICTOR_OBSERVER_H_
......@@ -12,10 +12,13 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/predictors/loading_predictor_config.h"
#include "chrome/browser/predictors/resource_prefetch_common.h"
#include "content/public/common/resource_load_info.mojom.h"
#include "content/public/common/resource_type.h"
#include "url/gurl.h"
namespace net {
class URLRequest;
}
namespace predictors {
class LoadingStatsCollector;
......@@ -34,13 +37,34 @@ struct OriginRequestSummary {
int first_occurrence = 0;
};
// Stores the data that we need to get from the URLRequest.
struct URLRequestSummary {
URLRequestSummary();
URLRequestSummary(const URLRequestSummary& other);
~URLRequestSummary();
NavigationID navigation_id;
GURL request_url; // URL after all redirects.
GURL redirect_url; // Empty unless request was redirected to a valid url.
content::ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
bool always_revalidate = false;
bool is_no_store = false;
bool network_accessed = false;
// Initializes a |URLRequestSummary| from a |URLRequest| response.
// Returns true for success. Note: NavigationID is NOT initialized
// by this function.
static bool SummarizeResponse(const net::URLRequest& request,
URLRequestSummary* summary);
};
// Stores the data learned from a single navigation.
struct PageRequestSummary {
explicit PageRequestSummary(const GURL& main_frame_url);
PageRequestSummary(const PageRequestSummary& other);
void UpdateOrAddToOrigins(const URLRequestSummary& request_summary);
~PageRequestSummary();
void UpdateOrAddToOrigins(
const content::mojom::ResourceLoadInfo& resource_load_info);
GURL main_frame_url;
GURL initial_url;
......@@ -49,11 +73,6 @@ struct PageRequestSummary {
// Map of origin -> OriginRequestSummary. Only one instance of each origin
// is kept per navigation, but the summary is updated several times.
std::map<GURL, OriginRequestSummary> origins;
private:
void UpdateOrAddToOrigins(
const GURL& url,
const content::mojom::CommonNetworkInfoPtr& network_info);
};
// Records navigation events as reported by various observers to the database
......@@ -65,25 +84,39 @@ class LoadingDataCollector {
predictors::ResourcePrefetchPredictor* predictor,
predictors::LoadingStatsCollector* stats_collector,
const LoadingPredictorConfig& config);
virtual ~LoadingDataCollector();
// |LoadingPredictorTabHelper| calls the below functions to inform the
// collector of navigation and resource load events.
virtual void RecordStartNavigation(const NavigationID& navigation_id);
virtual void RecordFinishNavigation(const NavigationID& old_navigation_id,
const NavigationID& new_navigation_id,
bool is_error_page);
virtual void RecordResourceLoadComplete(
const NavigationID& navigation_id,
const content::mojom::ResourceLoadInfo& resource_load_info);
~LoadingDataCollector();
// Determines the resource type from the declared one, falling back to MIME
// type detection when it is not explicit.
static content::ResourceType GetResourceType(
content::ResourceType resource_type,
const std::string& mime_type);
// Thread safe.
static bool ShouldRecordRequest(net::URLRequest* request,
content::ResourceType resource_type);
static bool ShouldRecordResponse(net::URLRequest* response);
static bool ShouldRecordRedirect(net::URLRequest* response);
static bool ShouldRecordResourceFromMemoryCache(
const GURL& url,
content::ResourceType resource_type,
const std::string& mime_type);
// 'LoadingPredictorObserver' and 'ResourcePrefetchPredictorTabHelper' call
// the below functions to inform the collector of main frame and resource
// requests. Should only be called if the corresponding Should* functions
// return true.
void RecordURLRequest(const URLRequestSummary& request);
void RecordURLResponse(const URLRequestSummary& response);
void RecordURLRedirect(const URLRequestSummary& response);
// Called when the main frame of a page completes loading. We treat this point
// as the "completion" of the navigation. The resources requested by the page
// up to this point are the only ones considered.
virtual void RecordMainFrameLoadComplete(const NavigationID& navigation_id);
void RecordMainFrameLoadComplete(const NavigationID& navigation_id);
// Called after the main frame's first contentful paint.
virtual void RecordFirstContentfulPaint(
void RecordFirstContentfulPaint(
const NavigationID& navigation_id,
const base::TimeTicks& first_contentful_paint);
......@@ -92,29 +125,44 @@ class LoadingDataCollector {
std::map<NavigationID, std::unique_ptr<PageRequestSummary>>;
friend class LoadingDataCollectorTest;
friend class ResourcePrefetchPredictorBrowserTest;
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, HandledResourceTypes);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ShouldRecordMainFrameLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
ShouldRecordSubresourceLoad);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, SimpleNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, SimpleRedirect);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, OnMainFrameRequest);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, OnMainFrameRedirect);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, OnSubresourceResponse);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordStartNavigationMissing);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, RecordFailedNavigation);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest, ManyNavigations);
FRIEND_TEST_ALL_PREFIXES(LoadingDataCollectorTest,
RecordResourceLoadComplete);
TestRecordFirstContentfulPaint);
static void SetAllowPortInUrlsForTesting(bool state);
// Determines the ResourceType from the mime type, defaulting to the
// |fallback| if the ResourceType could not be determined.
static content::ResourceType GetResourceTypeFromMimeType(
const std::string& mime_type,
content::ResourceType fallback);
// Returns true if the main page request is supported for prediction.
static bool IsHandledMainPage(net::URLRequest* request);
static bool ShouldRecordResourceLoad(
const content::mojom::ResourceLoadInfo& resource_load_info);
// Returns true if the subresource request is supported for prediction.
static bool IsHandledSubresource(net::URLRequest* request,
content::ResourceType resource_type);
// Returns true if the subresource has a supported type.
static bool IsHandledResourceType(content::ResourceType resource_type,
const std::string& mime_type);
// Returns true if the url could be written into the database.
static bool IsHandledUrl(const GURL& url);
static void SetAllowPortInUrlsForTesting(bool state);
// Functions called on different network events pertaining to the loading of
// main frame resource or sub resources.
void OnMainFrameRedirect(const URLRequestSummary& response);
void OnSubresourceRedirect(const URLRequestSummary& response);
// Cleanup inflight_navigations_ and call a cleanup for stats_collector_.
void CleanupAbandonedNavigations(const NavigationID& navigation_id);
......
......@@ -145,27 +145,47 @@ void LoadingPredictor::Shutdown() {
shutdown_ = true;
}
void LoadingPredictor::OnNavigationStarted(const NavigationID& navigation_id) {
void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) {
DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME);
if (shutdown_)
return;
loading_data_collector()->RecordStartNavigation(navigation_id);
const NavigationID& navigation_id = summary.navigation_id;
CleanupAbandonedHintsAndNavigations(navigation_id);
active_navigations_.emplace(navigation_id);
active_navigations_.emplace(navigation_id, navigation_id.main_frame_url);
PrepareForPageLoad(navigation_id.main_frame_url, HintOrigin::NAVIGATION);
}
void LoadingPredictor::OnNavigationFinished(
const NavigationID& old_navigation_id,
const NavigationID& new_navigation_id,
bool is_error_page) {
void LoadingPredictor::OnMainFrameRedirect(const URLRequestSummary& summary) {
DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME);
if (shutdown_)
return;
loading_data_collector()->RecordFinishNavigation(
old_navigation_id, new_navigation_id, is_error_page);
active_navigations_.erase(old_navigation_id);
CancelPageLoadHint(old_navigation_id.main_frame_url);
auto it = active_navigations_.find(summary.navigation_id);
if (it != active_navigations_.end()) {
if (summary.navigation_id.main_frame_url == summary.redirect_url)
return;
NavigationID navigation_id = summary.navigation_id;
navigation_id.main_frame_url = summary.redirect_url;
active_navigations_.emplace(navigation_id, it->second);
active_navigations_.erase(it);
}
}
void LoadingPredictor::OnMainFrameResponse(const URLRequestSummary& summary) {
DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME);
if (shutdown_)
return;
const NavigationID& navigation_id = summary.navigation_id;
auto it = active_navigations_.find(navigation_id);
if (it != active_navigations_.end()) {
const GURL& initial_url = it->second;
CancelPageLoadHint(initial_url);
active_navigations_.erase(it);
} else {
CancelPageLoadHint(navigation_id.main_frame_url);
}
}
std::map<GURL, base::TimeTicks>::iterator LoadingPredictor::CancelActiveHint(
......@@ -202,9 +222,10 @@ void LoadingPredictor::CleanupAbandonedHintsAndNavigations(
// Navigations.
for (auto it = active_navigations_.begin();
it != active_navigations_.end();) {
if ((it->tab_id == navigation_id.tab_id) ||
(time_now - it->creation_time > max_navigation_age)) {
CancelActiveHint(active_hints_.find(it->main_frame_url));
if ((it->first.tab_id == navigation_id.tab_id) ||
(time_now - it->first.creation_time > max_navigation_age)) {
const GURL& initial_url = it->second;
CancelActiveHint(active_hints_.find(initial_url));
it = active_navigations_.erase(it);
} else {
++it;
......
......@@ -7,7 +7,6 @@
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
......@@ -67,10 +66,9 @@ class LoadingPredictor : public KeyedService,
// KeyedService:
void Shutdown() override;
void OnNavigationStarted(const NavigationID& navigation_id);
void OnNavigationFinished(const NavigationID& old_navigation_id,
const NavigationID& new_navigation_id,
bool is_error_page);
void OnMainFrameRequest(const URLRequestSummary& summary);
void OnMainFrameRedirect(const URLRequestSummary& summary);
void OnMainFrameResponse(const URLRequestSummary& summary);
base::WeakPtr<LoadingPredictor> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
......@@ -111,12 +109,6 @@ class LoadingPredictor : public KeyedService,
preconnect_manager_ = std::move(preconnect_manager);
}
// For testing.
void set_mock_loading_data_collector(
std::unique_ptr<LoadingDataCollector> loading_data_collector) {
loading_data_collector_ = std::move(loading_data_collector);
}
LoadingPredictorConfig config_;
Profile* profile_;
std::unique_ptr<ResourcePrefetchPredictor> resource_prefetch_predictor_;
......@@ -124,7 +116,8 @@ class LoadingPredictor : public KeyedService,
std::unique_ptr<LoadingDataCollector> loading_data_collector_;
std::unique_ptr<PreconnectManager> preconnect_manager_;
std::map<GURL, base::TimeTicks> active_hints_;
std::set<NavigationID> active_navigations_;
// Initial URL.
std::map<NavigationID, GURL> active_navigations_;
bool shutdown_ = false;
GURL last_omnibox_origin_;
......@@ -133,7 +126,6 @@ class LoadingPredictor : public KeyedService,
friend class LoadingPredictorTest;
friend class LoadingPredictorPreconnectTest;
friend class LoadingPredictorTabHelperTest;
FRIEND_TEST_ALL_PREFIXES(LoadingPredictorTest,
TestMainFrameResponseCancelsHint);
FRIEND_TEST_ALL_PREFIXES(LoadingPredictorTest,
......
// Copyright 2018 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/predictors/loading_predictor_tab_helper.h"
#include <string>
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(predictors::LoadingPredictorTabHelper);
using content::BrowserThread;
namespace predictors {
namespace {
bool IsHandledNavigation(content::NavigationHandle* navigation_handle) {
return navigation_handle->IsInMainFrame() &&
!navigation_handle->IsSameDocument() &&
navigation_handle->GetURL().SchemeIsHTTPOrHTTPS();
}
} // namespace
LoadingPredictorTabHelper::LoadingPredictorTabHelper(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
auto* predictor = LoadingPredictorFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()));
if (predictor)
predictor_ = predictor->GetWeakPtr();
}
LoadingPredictorTabHelper::~LoadingPredictorTabHelper() = default;
void LoadingPredictorTabHelper::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!predictor_)
return;
if (!IsHandledNavigation(navigation_handle))
return;
auto navigation_id = NavigationID(web_contents(), navigation_handle->GetURL(),
navigation_handle->NavigationStart());
if (!navigation_id.is_valid())
return;
predictor_->OnNavigationStarted(navigation_id);
}
void LoadingPredictorTabHelper::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!predictor_)
return;
if (!IsHandledNavigation(navigation_handle))
return;
auto old_navigation_id = NavigationID(
web_contents(), navigation_handle->GetRedirectChain().front(),
navigation_handle->NavigationStart());
auto new_navigation_id =
NavigationID(web_contents(), navigation_handle->GetURL(),
navigation_handle->NavigationStart());
if (!old_navigation_id.is_valid() || !new_navigation_id.is_valid())
return;
predictor_->OnNavigationFinished(old_navigation_id, new_navigation_id,
navigation_handle->IsErrorPage());
}
void LoadingPredictorTabHelper::ResourceLoadComplete(
content::RenderFrameHost* render_frame_host,
const content::mojom::ResourceLoadInfo& resource_load_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!predictor_)
return;
bool is_main_frame = render_frame_host->GetParent() == nullptr;
if (!is_main_frame)
return;
auto navigation_id = NavigationID(web_contents());
if (!navigation_id.is_valid())
return;
predictor_->loading_data_collector()->RecordResourceLoadComplete(
navigation_id, resource_load_info);
}
void LoadingPredictorTabHelper::DidLoadResourceFromMemoryCache(
const GURL& url,
const std::string& mime_type,
content::ResourceType resource_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!predictor_)
return;
auto navigation_id = NavigationID(web_contents());
if (!navigation_id.is_valid())
return;
content::mojom::ResourceLoadInfo resource_load_info;
resource_load_info.url = url;
resource_load_info.mime_type = mime_type;
resource_load_info.resource_type = resource_type;
resource_load_info.method = "GET";
resource_load_info.network_info =
content::mojom::CommonNetworkInfo::New(false, false, base::nullopt);
predictor_->loading_data_collector()->RecordResourceLoadComplete(
navigation_id, resource_load_info);
}
void LoadingPredictorTabHelper::DocumentOnLoadCompletedInMainFrame() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!predictor_)
return;
auto navigation_id = NavigationID(web_contents());
if (!navigation_id.is_valid())
return;
predictor_->loading_data_collector()->RecordMainFrameLoadComplete(
navigation_id);
}
} // namespace predictors
// Copyright 2018 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/predictors/loading_predictor_tab_helper.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_test_util.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/navigation_simulator.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::ByRef;
using ::testing::Eq;
using ::testing::Mock;
using ::testing::StrictMock;
namespace predictors {
class MockLoadingDataCollector : public LoadingDataCollector {
public:
explicit MockLoadingDataCollector(const LoadingPredictorConfig& config);
MOCK_METHOD1(RecordStartNavigation, void(const NavigationID&));
MOCK_METHOD3(RecordFinishNavigation,
void(const NavigationID&, const NavigationID&, bool));
MOCK_METHOD2(RecordResourceLoadComplete,
void(const NavigationID&,
const content::mojom::ResourceLoadInfo&));
MOCK_METHOD1(RecordMainFrameLoadComplete, void(const NavigationID&));
MOCK_METHOD2(RecordFirstContentfulPaint,
void(const NavigationID&, const base::TimeTicks&));
};
MockLoadingDataCollector::MockLoadingDataCollector(
const LoadingPredictorConfig& config)
: LoadingDataCollector(nullptr, nullptr, config) {}
class LoadingPredictorTabHelperTest : public ChromeRenderViewHostTestHarness {
public:
void SetUp() override;
void TearDown() override;
void ExpectRecordNavigation(const std::string& url);
SessionID GetTabID();
void NavigateAndCommitInFrame(const std::string& url,
content::RenderFrameHost* rfh);
protected:
std::unique_ptr<LoadingPredictor> loading_predictor_;
// Owned by |loading_predictor_|.
StrictMock<MockLoadingDataCollector>* mock_collector_;
// Owned by |web_contents()|.
LoadingPredictorTabHelper* tab_helper_;
};
void LoadingPredictorTabHelperTest::SetUp() {
ChromeRenderViewHostTestHarness::SetUp();
SessionTabHelper::CreateForWebContents(web_contents());
LoadingPredictorTabHelper::CreateForWebContents(web_contents());
tab_helper_ = LoadingPredictorTabHelper::FromWebContents(web_contents());
LoadingPredictorConfig config;
PopulateTestConfig(&config);
loading_predictor_ = std::make_unique<LoadingPredictor>(config, profile());
auto mock_collector =
std::make_unique<StrictMock<MockLoadingDataCollector>>(config);
mock_collector_ = mock_collector.get();
loading_predictor_->set_mock_loading_data_collector(
std::move(mock_collector));
tab_helper_->SetLoadingPredictorForTesting(loading_predictor_->GetWeakPtr());
}
void LoadingPredictorTabHelperTest::TearDown() {
loading_predictor_->Shutdown();
ChromeRenderViewHostTestHarness::TearDown();
}
void LoadingPredictorTabHelperTest::ExpectRecordNavigation(
const std::string& url) {
auto navigation_id = CreateNavigationID(GetTabID(), url);
EXPECT_CALL(*mock_collector_, RecordStartNavigation(navigation_id));
EXPECT_CALL(*mock_collector_,
RecordFinishNavigation(navigation_id, navigation_id,
/* is_error_page */ false));
}
SessionID LoadingPredictorTabHelperTest::GetTabID() {
return SessionTabHelper::IdForTab(web_contents());
}
void LoadingPredictorTabHelperTest::NavigateAndCommitInFrame(
const std::string& url,
content::RenderFrameHost* rfh) {
auto navigation =
content::NavigationSimulator::CreateRendererInitiated(GURL(url), rfh);
navigation->Start();
navigation->Commit();
}
// Tests that a main frame navigation is correctly recorded by the
// LoadingDataCollector.
TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigation) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
}
// Tests that an old and new navigation ids are correctly set if a navigation
// has redirects.
TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationWithRedirects) {
auto navigation = content::NavigationSimulator::CreateRendererInitiated(
GURL("http://test.org"), main_rfh());
auto navigation_id = CreateNavigationID(GetTabID(), "http://test.org");
EXPECT_CALL(*mock_collector_, RecordStartNavigation(navigation_id));
navigation->Start();
navigation->Redirect(GURL("http://test2.org"));
navigation->Redirect(GURL("http://test3.org"));
auto new_navigation_id = CreateNavigationID(GetTabID(), "http://test3.org");
EXPECT_CALL(*mock_collector_,
RecordFinishNavigation(navigation_id, new_navigation_id,
/* is_error_page */ false));
navigation->Commit();
}
// Tests that a subframe navigation is not recorded.
TEST_F(LoadingPredictorTabHelperTest, SubframeNavigation) {
// We need to have a committed main frame navigation before navigating in sub
// frames.
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
auto* subframe =
content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe");
// Subframe navigation shouldn't be recorded.
NavigateAndCommitInFrame("http://sub.test.org", subframe);
}
// Tests that a failed navigation is correctly recorded.
TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationFailed) {
auto navigation = content::NavigationSimulator::CreateRendererInitiated(
GURL("http://test.org"), main_rfh());
auto navigation_id = CreateNavigationID(GetTabID(), "http://test.org");
EXPECT_CALL(*mock_collector_, RecordStartNavigation(navigation_id));
EXPECT_CALL(*mock_collector_,
RecordFinishNavigation(navigation_id, navigation_id,
/* is_error_page */ true));
navigation->Start();
navigation->Fail(net::ERR_TIMED_OUT);
navigation->CommitErrorPage();
}
// Tests that a same document navigation is not recorded.
TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationSameDocument) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
// Same document navigation shouldn't be recorded.
content::NavigationSimulator::CreateRendererInitiated(GURL("http://test.org"),
main_rfh())
->CommitSameDocument();
}
// Tests that document on load completed is recorded with correct navigation
// id.
TEST_F(LoadingPredictorTabHelperTest, DocumentOnLoadCompleted) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
// Adding subframe navigation to ensure that the commited main frame url will
// be used.
auto* subframe =
content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe");
NavigateAndCommitInFrame("http://sub.test.org", subframe);
auto navigation_id = CreateNavigationID(GetTabID(), "http://test.org");
EXPECT_CALL(*mock_collector_, RecordMainFrameLoadComplete(navigation_id));
tab_helper_->DocumentOnLoadCompletedInMainFrame();
}
// Tests that a resource load is correctly recorded.
TEST_F(LoadingPredictorTabHelperTest, ResourceLoadComplete) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
auto navigation_id = CreateNavigationID(GetTabID(), "http://test.org");
auto resource_load_info = CreateResourceLoadInfo(
"http://test.org/script.js", content::RESOURCE_TYPE_SCRIPT);
EXPECT_CALL(*mock_collector_,
RecordResourceLoadComplete(navigation_id,
Eq(ByRef(*resource_load_info))));
tab_helper_->ResourceLoadComplete(main_rfh(), *resource_load_info);
}
// Tests that a resource loaded in a subframe is not recorded.
TEST_F(LoadingPredictorTabHelperTest, ResourceLoadCompleteInSubFrame) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
auto* subframe =
content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe");
NavigateAndCommitInFrame("http://sub.test.org", subframe);
// Resource loaded in subframe shouldn't be recorded.
auto resource_load_info = CreateResourceLoadInfo(
"http://sub.test.org/script.js", content::RESOURCE_TYPE_SCRIPT);
tab_helper_->ResourceLoadComplete(subframe, *resource_load_info);
}
// Tests that a resource load from the memory cache is correctly recorded.
TEST_F(LoadingPredictorTabHelperTest, LoadResourceFromMemoryCache) {
ExpectRecordNavigation("http://test.org");
NavigateAndCommitInFrame("http://test.org", main_rfh());
auto navigation_id = CreateNavigationID(GetTabID(), "http://test.org");
auto resource_load_info = CreateResourceLoadInfo(
"http://test.org/script.js", content::RESOURCE_TYPE_SCRIPT, false);
resource_load_info->mime_type = "application/javascript";
resource_load_info->network_info->network_accessed = false;
EXPECT_CALL(*mock_collector_,
RecordResourceLoadComplete(navigation_id,
Eq(ByRef(*resource_load_info))));
tab_helper_->DidLoadResourceFromMemoryCache(
GURL("http://test.org/script.js"), "application/javascript",
content::ResourceType::RESOURCE_TYPE_SCRIPT);
}
} // namespace predictors
......@@ -15,7 +15,6 @@
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -177,9 +176,9 @@ TEST_F(LoadingPredictorTest, TestMainFrameResponseCancelsHint) {
predictor_->PrepareForPageLoad(url, HintOrigin::EXTERNAL);
EXPECT_EQ(1UL, predictor_->active_hints_.size());
auto navigation_id =
CreateNavigationID(SessionID::FromSerializedValue(12), url.spec());
predictor_->OnNavigationFinished(navigation_id, navigation_id, false);
auto summary =
CreateURLRequestSummary(SessionID::FromSerializedValue(12), url.spec());
predictor_->OnMainFrameResponse(summary);
EXPECT_TRUE(predictor_->active_hints_.empty());
}
......@@ -190,17 +189,19 @@ TEST_F(LoadingPredictorTest, TestMainFrameRequestCancelsStaleNavigations) {
const auto& active_navigations = predictor_->active_navigations_;
const auto& active_hints = predictor_->active_hints_;
auto summary = CreateURLRequestSummary(tab_id, url);
auto navigation_id = CreateNavigationID(tab_id, url);
predictor_->OnNavigationStarted(navigation_id);
predictor_->OnMainFrameRequest(summary);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_NE(active_hints.find(GURL(url)), active_hints.end());
auto navigation_id2 = CreateNavigationID(tab_id, url2);
predictor_->OnNavigationStarted(navigation_id2);
summary = CreateURLRequestSummary(tab_id, url2);
predictor_->OnMainFrameRequest(summary);
EXPECT_EQ(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_EQ(active_hints.find(GURL(url)), active_hints.end());
auto navigation_id2 = CreateNavigationID(tab_id, url2);
EXPECT_NE(active_navigations.find(navigation_id2), active_navigations.end());
}
......@@ -211,23 +212,29 @@ TEST_F(LoadingPredictorTest, TestMainFrameResponseClearsNavigations) {
const auto& active_navigations = predictor_->active_navigations_;
const auto& active_hints = predictor_->active_hints_;
auto summary = CreateURLRequestSummary(tab_id, url);
auto navigation_id = CreateNavigationID(tab_id, url);
predictor_->OnNavigationStarted(navigation_id);
predictor_->OnMainFrameRequest(summary);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_FALSE(active_hints.empty());
predictor_->OnNavigationFinished(navigation_id, navigation_id, false);
predictor_->OnMainFrameResponse(summary);
EXPECT_TRUE(active_navigations.empty());
EXPECT_TRUE(active_hints.empty());
// With redirects.
predictor_->OnNavigationStarted(navigation_id);
predictor_->OnMainFrameRequest(summary);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
EXPECT_FALSE(active_hints.empty());
auto new_navigation_id = CreateNavigationID(tab_id, redirected);
predictor_->OnNavigationFinished(navigation_id, new_navigation_id, false);
summary.redirect_url = GURL(redirected);
predictor_->OnMainFrameRedirect(summary);
EXPECT_FALSE(active_navigations.empty());
EXPECT_FALSE(active_hints.empty());
summary.navigation_id.main_frame_url = GURL(redirected);
predictor_->OnMainFrameResponse(summary);
EXPECT_TRUE(active_navigations.empty());
EXPECT_TRUE(active_hints.empty());
}
......@@ -248,9 +255,10 @@ TEST_F(LoadingPredictorTest, TestMainFrameRequestDoesntCancelExternalHint) {
base::TimeTicks start_time = it->second - base::TimeDelta::FromSeconds(10);
it->second = start_time;
auto navigation_id = CreateNavigationID(tab_id, url.spec());
predictor_->OnNavigationStarted(navigation_id);
EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end());
auto summary = CreateURLRequestSummary(tab_id, url.spec());
predictor_->OnMainFrameRequest(summary);
EXPECT_NE(active_navigations.find(summary.navigation_id),
active_navigations.end());
it = active_hints.find(url);
EXPECT_NE(it, active_hints.end());
EXPECT_EQ(start_time, it->second);
......
......@@ -81,13 +81,11 @@ void LoadingStatsCollectorTest::TestRedirectStatusHistogram(
.WillOnce(DoAll(SetArgPointee<1>(prediction), Return(true)));
// Navigation simulation.
std::vector<content::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(
CreateResourceLoadInfoWithRedirects({initial_url, navigation_url}));
resources.push_back(
CreateResourceLoadInfo(script_url, content::RESOURCE_TYPE_SCRIPT));
URLRequestSummary script =
CreateURLRequestSummary(SessionID::FromSerializedValue(1), navigation_url,
script_url, content::RESOURCE_TYPE_SCRIPT);
PageRequestSummary summary =
CreatePageRequestSummary(navigation_url, initial_url, resources);
CreatePageRequestSummary(navigation_url, initial_url, {script});
stats_collector_->RecordPageRequestSummary(summary);
......@@ -116,14 +114,14 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectPrecisionRecallHistograms) {
// Simulate a page load with 2 resources, one we know, one we don't, plus we
// know the main frame origin.
std::vector<content::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(CreateResourceLoadInfo(main_frame_url));
resources.push_back(
CreateResourceLoadInfo(gen(1), content::RESOURCE_TYPE_SCRIPT));
resources.push_back(
CreateResourceLoadInfo(gen(100), content::RESOURCE_TYPE_SCRIPT));
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources);
URLRequestSummary script =
CreateURLRequestSummary(SessionID::FromSerializedValue(1), main_frame_url,
gen(1), content::RESOURCE_TYPE_SCRIPT);
URLRequestSummary new_script =
CreateURLRequestSummary(SessionID::FromSerializedValue(1), main_frame_url,
gen(100), content::RESOURCE_TYPE_SCRIPT);
PageRequestSummary summary = CreatePageRequestSummary(
main_frame_url, main_frame_url, {script, new_script});
stats_collector_->RecordPageRequestSummary(summary);
......@@ -163,6 +161,7 @@ TEST_F(LoadingStatsCollectorTest,
TEST_F(LoadingStatsCollectorTest, TestPreconnectHistograms) {
const std::string main_frame_url("http://google.com/?query=cats");
const SessionID kTabId = SessionID::FromSerializedValue(1);
auto gen = [](int index) {
return base::StringPrintf("http://cdn%d.google.com/script.js", index);
};
......@@ -188,16 +187,14 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectHistograms) {
{
// Simulate a page load with 3 origins.
std::vector<content::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(CreateResourceLoadInfo(main_frame_url));
resources.push_back(
CreateResourceLoadInfo(gen(1), content::RESOURCE_TYPE_SCRIPT));
resources.push_back(
CreateResourceLoadInfo(gen(2), content::RESOURCE_TYPE_SCRIPT));
resources.push_back(
CreateResourceLoadInfo(gen(100), content::RESOURCE_TYPE_SCRIPT));
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources);
URLRequestSummary script1 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(1), content::RESOURCE_TYPE_SCRIPT);
URLRequestSummary script2 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(2), content::RESOURCE_TYPE_SCRIPT);
URLRequestSummary script100 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(100), content::RESOURCE_TYPE_SCRIPT);
PageRequestSummary summary = CreatePageRequestSummary(
main_frame_url, main_frame_url, {script1, script2, script100});
stats_collector_->RecordPageRequestSummary(summary);
}
......@@ -216,6 +213,7 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectHistograms) {
// empty.
TEST_F(LoadingStatsCollectorTest, TestPreconnectHistogramsEmpty) {
const std::string main_frame_url = "http://google.com";
const SessionID kTabId = SessionID::FromSerializedValue(1);
auto stats = std::make_unique<PreconnectStats>(GURL(main_frame_url));
stats_collector_->RecordPreconnectStats(std::move(stats));
......@@ -223,12 +221,11 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectHistogramsEmpty) {
PredictPreconnectOrigins(GURL(main_frame_url), _))
.WillOnce(Return(false));
std::vector<content::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(CreateResourceLoadInfo(main_frame_url));
resources.push_back(CreateResourceLoadInfo("http://cdn.google.com/script.js",
content::RESOURCE_TYPE_SCRIPT));
URLRequestSummary script = CreateURLRequestSummary(
kTabId, main_frame_url, "http://cdn.google.com/script.js",
content::RESOURCE_TYPE_SCRIPT);
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources);
CreatePageRequestSummary(main_frame_url, main_frame_url, {script});
stats_collector_->RecordPageRequestSummary(summary);
// No histograms should be recorded.
......@@ -246,6 +243,7 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectHistogramsEmpty) {
// preresolve attempts only.
TEST_F(LoadingStatsCollectorTest, TestPreconnectHistogramsPreresolvesOnly) {
const std::string main_frame_url("http://google.com/?query=cats");
const SessionID kTabId = SessionID::FromSerializedValue(1);
auto gen = [](int index) {
return base::StringPrintf("http://cdn%d.google.com/script.js", index);
};
......@@ -271,16 +269,14 @@ TEST_F(LoadingStatsCollectorTest, TestPreconnectHistogramsPreresolvesOnly) {
{
// Simulate a page load with 3 origins.
std::vector<content::mojom::ResourceLoadInfoPtr> resources;
resources.push_back(CreateResourceLoadInfo(main_frame_url));
resources.push_back(
CreateResourceLoadInfo(gen(1), content::RESOURCE_TYPE_SCRIPT));
resources.push_back(
CreateResourceLoadInfo(gen(2), content::RESOURCE_TYPE_SCRIPT));
resources.push_back(
CreateResourceLoadInfo(gen(100), content::RESOURCE_TYPE_SCRIPT));
PageRequestSummary summary =
CreatePageRequestSummary(main_frame_url, main_frame_url, resources);
URLRequestSummary script1 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(1), content::RESOURCE_TYPE_SCRIPT);
URLRequestSummary script2 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(2), content::RESOURCE_TYPE_SCRIPT);
URLRequestSummary script100 = CreateURLRequestSummary(
kTabId, main_frame_url, gen(100), content::RESOURCE_TYPE_SCRIPT);
PageRequestSummary summary = CreatePageRequestSummary(
main_frame_url, main_frame_url, {script1, script2, script100});
stats_collector_->RecordPageRequestSummary(summary);
}
......
......@@ -15,6 +15,13 @@
namespace {
class EmptyURLRequestDelegate : public net::URLRequest::Delegate {
void OnResponseStarted(net::URLRequest* request, int net_error) override {}
void OnReadCompleted(net::URLRequest* request, int bytes_read) override {}
};
EmptyURLRequestDelegate g_empty_url_request_delegate;
bool AlmostEqual(const double x, const double y) {
return std::fabs(x - y) <= 1e-6; // Arbitrary but close enough.
}
......@@ -85,47 +92,44 @@ NavigationID CreateNavigationID(SessionID tab_id,
PageRequestSummary CreatePageRequestSummary(
const std::string& main_frame_url,
const std::string& initial_url,
const std::vector<content::mojom::ResourceLoadInfoPtr>&
resource_load_infos) {
const std::vector<URLRequestSummary>& subresource_requests) {
GURL main_frame_gurl(main_frame_url);
PageRequestSummary summary(main_frame_gurl);
summary.initial_url = GURL(initial_url);
for (const auto& resource_load_info : resource_load_infos)
summary.UpdateOrAddToOrigins(*resource_load_info);
summary.UpdateOrAddToOrigins(CreateURLRequestSummary(
SessionID::FromSerializedValue(1), main_frame_url));
for (auto& request_summary : subresource_requests)
summary.UpdateOrAddToOrigins(request_summary);
return summary;
}
content::mojom::ResourceLoadInfoPtr CreateResourceLoadInfo(
const std::string& url,
content::ResourceType resource_type,
bool always_access_network) {
auto resource_load_info = content::mojom::ResourceLoadInfo::New();
resource_load_info->url = GURL(url);
resource_load_info->original_url = GURL(url);
resource_load_info->method = "GET";
resource_load_info->resource_type = resource_type;
resource_load_info->network_info = content::mojom::CommonNetworkInfo::New(
true, always_access_network, base::nullopt);
return resource_load_info;
}
content::mojom::ResourceLoadInfoPtr CreateResourceLoadInfoWithRedirects(
const std::vector<std::string>& redirect_chain,
content::ResourceType resource_type) {
auto resource_load_info = content::mojom::ResourceLoadInfo::New();
resource_load_info->url = GURL(redirect_chain.back());
resource_load_info->original_url = GURL(redirect_chain.front());
resource_load_info->method = "GET";
resource_load_info->resource_type = resource_type;
auto common_network_info =
content::mojom::CommonNetworkInfo::New(true, false, base::nullopt);
resource_load_info->network_info = common_network_info.Clone();
for (size_t i = 0; i + 1 < redirect_chain.size(); ++i) {
resource_load_info->redirect_info_chain.push_back(
content::mojom::RedirectInfo::New(GURL(redirect_chain[i]),
common_network_info.Clone()));
}
return resource_load_info;
URLRequestSummary CreateURLRequestSummary(SessionID tab_id,
const std::string& main_frame_url,
const std::string& request_url,
content::ResourceType resource_type,
const std::string& redirect_url,
bool always_revalidate) {
URLRequestSummary summary;
summary.navigation_id = CreateNavigationID(tab_id, main_frame_url);
summary.request_url =
request_url.empty() ? GURL(main_frame_url) : GURL(request_url);
if (!redirect_url.empty())
summary.redirect_url = GURL(redirect_url);
summary.resource_type = resource_type;
summary.always_revalidate = always_revalidate;
summary.is_no_store = false;
summary.network_accessed = true;
return summary;
}
URLRequestSummary CreateRedirectRequestSummary(
SessionID session_id,
const std::string& main_frame_url,
const std::string& redirect_url) {
URLRequestSummary summary =
CreateURLRequestSummary(session_id, main_frame_url);
summary.redirect_url = GURL(redirect_url);
return summary;
}
PreconnectPrediction CreatePreconnectPrediction(
......@@ -151,6 +155,95 @@ void PopulateTestConfig(LoadingPredictorConfig* config, bool small_db) {
config->flush_data_to_disk_delay_seconds = 0;
}
scoped_refptr<net::HttpResponseHeaders> MakeResponseHeaders(
const char* headers) {
return base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(headers, strlen(headers)));
}
MockURLRequestJob::MockURLRequestJob(
net::URLRequest* request,
const net::HttpResponseInfo& response_info,
const net::LoadTimingInfo& load_timing_info,
const std::string& mime_type)
: net::URLRequestJob(request, nullptr),
response_info_(response_info),
load_timing_info_(load_timing_info),
mime_type_(mime_type) {}
bool MockURLRequestJob::GetMimeType(std::string* mime_type) const {
*mime_type = mime_type_;
return true;
}
void MockURLRequestJob::Start() {
NotifyHeadersComplete();
}
void MockURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
*info = response_info_;
}
void MockURLRequestJob::GetLoadTimingInfo(net::LoadTimingInfo* info) const {
*info = load_timing_info_;
}
MockURLRequestJobFactory::MockURLRequestJobFactory() {}
MockURLRequestJobFactory::~MockURLRequestJobFactory() {}
void MockURLRequestJobFactory::Reset() {
response_info_ = net::HttpResponseInfo();
mime_type_ = std::string();
}
net::URLRequestJob* MockURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const {
return new MockURLRequestJob(request, response_info_, load_timing_info_,
mime_type_);
}
net::URLRequestJob* MockURLRequestJobFactory::MaybeInterceptRedirect(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const GURL& location) const {
return nullptr;
}
net::URLRequestJob* MockURLRequestJobFactory::MaybeInterceptResponse(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const {
return nullptr;
}
bool MockURLRequestJobFactory::IsHandledProtocol(
const std::string& scheme) const {
return true;
}
bool MockURLRequestJobFactory::IsSafeRedirectTarget(
const GURL& location) const {
return true;
}
std::unique_ptr<net::URLRequest> CreateURLRequest(
const net::TestURLRequestContext& url_request_context,
const GURL& url,
net::RequestPriority priority,
content::ResourceType resource_type,
bool is_main_frame) {
std::unique_ptr<net::URLRequest> request = url_request_context.CreateRequest(
url, priority, &g_empty_url_request_delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
request->set_site_for_cookies(url);
content::ResourceRequestInfo::AllocateForTesting(
request.get(), resource_type, nullptr, -1, -1, -1, is_main_frame, false,
true, content::PREVIEWS_OFF, nullptr);
request->Start();
return request;
}
std::ostream& operator<<(std::ostream& os, const RedirectData& data) {
os << "[" << data.primary_key() << "," << data.last_visit_time() << "]"
<< std::endl;
......@@ -195,6 +288,13 @@ std::ostream& operator<<(std::ostream& os, const PageRequestSummary& summary) {
return os;
}
std::ostream& operator<<(std::ostream& os, const URLRequestSummary& summary) {
return os << "[" << summary.navigation_id << "," << summary.request_url << ","
<< summary.redirect_url << "," << summary.resource_type << ","
<< summary.always_revalidate << "," << summary.is_no_store << ","
<< summary.network_accessed << "]";
}
std::ostream& operator<<(std::ostream& os, const NavigationID& navigation_id) {
return os << navigation_id.tab_id << "," << navigation_id.main_frame_url;
}
......@@ -241,6 +341,16 @@ bool operator==(const PageRequestSummary& lhs, const PageRequestSummary& rhs) {
lhs.origins == rhs.origins;
}
bool operator==(const URLRequestSummary& lhs, const URLRequestSummary& rhs) {
return lhs.navigation_id == rhs.navigation_id &&
lhs.request_url == rhs.request_url &&
lhs.redirect_url == rhs.redirect_url &&
lhs.resource_type == rhs.resource_type &&
lhs.always_revalidate == rhs.always_revalidate &&
lhs.is_no_store == rhs.is_no_store &&
lhs.network_accessed == rhs.network_accessed;
}
bool operator==(const OriginRequestSummary& lhs,
const OriginRequestSummary& rhs) {
return lhs.origin == rhs.origin &&
......@@ -283,31 +393,3 @@ bool operator==(const PreconnectPrediction& lhs,
}
} // namespace predictors
namespace content {
namespace mojom {
std::ostream& operator<<(std::ostream& os, const CommonNetworkInfo& info) {
return os << "[" << info.network_accessed << "," << info.always_access_network
<< "]";
}
std::ostream& operator<<(std::ostream& os, const ResourceLoadInfo& info) {
return os << "[" << info.url.spec() << "," << info.resource_type << ","
<< info.mime_type << "," << info.method << "," << *info.network_info
<< "]";
}
bool operator==(const CommonNetworkInfo& lhs, const CommonNetworkInfo& rhs) {
return lhs.network_accessed == rhs.network_accessed &&
lhs.always_access_network == rhs.always_access_network;
}
bool operator==(const ResourceLoadInfo& lhs, const ResourceLoadInfo& rhs) {
return lhs.url == rhs.url && lhs.resource_type == rhs.resource_type &&
lhs.mime_type == rhs.mime_type && lhs.method == rhs.method &&
*lhs.network_info == *rhs.network_info;
}
} // namespace mojom
} // namespace content
......@@ -14,6 +14,10 @@
#include "chrome/browser/predictors/resource_prefetch_predictor.h"
#include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
#include "components/sessions/core/session_id.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace predictors {
......@@ -61,17 +65,20 @@ NavigationID CreateNavigationID(SessionID tab_id,
PageRequestSummary CreatePageRequestSummary(
const std::string& main_frame_url,
const std::string& initial_url,
const std::vector<content::mojom::ResourceLoadInfoPtr>&
resource_load_infos);
const std::vector<URLRequestSummary>& subresource_requests);
content::mojom::ResourceLoadInfoPtr CreateResourceLoadInfo(
const std::string& url,
URLRequestSummary CreateURLRequestSummary(
SessionID tab_id,
const std::string& main_frame_url,
const std::string& request_url = std::string(),
content::ResourceType resource_type = content::RESOURCE_TYPE_MAIN_FRAME,
bool always_access_network = false);
const std::string& redirect_url = std::string(),
bool always_revalidate = false);
content::mojom::ResourceLoadInfoPtr CreateResourceLoadInfoWithRedirects(
const std::vector<std::string>& redirect_chain,
content::ResourceType resource_type = content::RESOURCE_TYPE_MAIN_FRAME);
URLRequestSummary CreateRedirectRequestSummary(
SessionID session_id,
const std::string& main_frame_url,
const std::string& redirect_url);
PreconnectPrediction CreatePreconnectPrediction(
std::string host,
......@@ -80,11 +87,84 @@ PreconnectPrediction CreatePreconnectPrediction(
void PopulateTestConfig(LoadingPredictorConfig* config, bool small_db = true);
scoped_refptr<net::HttpResponseHeaders> MakeResponseHeaders(
const char* headers);
class MockURLRequestJob : public net::URLRequestJob {
public:
MockURLRequestJob(net::URLRequest* request,
const net::HttpResponseInfo& response_info,
const net::LoadTimingInfo& load_timing_info,
const std::string& mime_type);
bool GetMimeType(std::string* mime_type) const override;
protected:
void Start() override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
void GetLoadTimingInfo(net::LoadTimingInfo* info) const override;
private:
net::HttpResponseInfo response_info_;
net::LoadTimingInfo load_timing_info_;
std::string mime_type_;
};
class MockURLRequestJobFactory : public net::URLRequestJobFactory {
public:
MockURLRequestJobFactory();
~MockURLRequestJobFactory() override;
void Reset();
net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override;
net::URLRequestJob* MaybeInterceptRedirect(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const GURL& location) const override;
net::URLRequestJob* MaybeInterceptResponse(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override;
bool IsHandledProtocol(const std::string& scheme) const override;
bool IsSafeRedirectTarget(const GURL& location) const override;
void set_response_info(const net::HttpResponseInfo& response_info) {
response_info_ = response_info;
}
void set_load_timing_info(const net::LoadTimingInfo& load_timing_info) {
load_timing_info_ = load_timing_info;
}
void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; }
private:
net::HttpResponseInfo response_info_;
net::LoadTimingInfo load_timing_info_;
std::string mime_type_;
};
std::unique_ptr<net::URLRequest> CreateURLRequest(
const net::TestURLRequestContext& url_request_context,
const GURL& url,
net::RequestPriority priority,
content::ResourceType resource_type,
bool is_main_frame);
// For printing failures nicely.
std::ostream& operator<<(std::ostream& stream, const RedirectData& data);
std::ostream& operator<<(std::ostream& stream, const RedirectStat& redirect);
std::ostream& operator<<(std::ostream& stream,
const PageRequestSummary& summary);
std::ostream& operator<<(std::ostream& stream,
const URLRequestSummary& summary);
std::ostream& operator<<(std::ostream& stream, const NavigationID& id);
std::ostream& operator<<(std::ostream& os, const OriginData& data);
......@@ -96,6 +176,7 @@ std::ostream& operator<<(std::ostream& os,
bool operator==(const RedirectData& lhs, const RedirectData& rhs);
bool operator==(const RedirectStat& lhs, const RedirectStat& rhs);
bool operator==(const PageRequestSummary& lhs, const PageRequestSummary& rhs);
bool operator==(const URLRequestSummary& lhs, const URLRequestSummary& rhs);
bool operator==(const OriginRequestSummary& lhs,
const OriginRequestSummary& rhs);
bool operator==(const OriginData& lhs, const OriginData& rhs);
......@@ -106,16 +187,4 @@ bool operator==(const PreconnectPrediction& lhs,
} // namespace predictors
namespace content {
namespace mojom {
std::ostream& operator<<(std::ostream& os, const CommonNetworkInfo& info);
std::ostream& operator<<(std::ostream& os, const ResourceLoadInfo& info);
bool operator==(const CommonNetworkInfo& lhs, const CommonNetworkInfo& rhs);
bool operator==(const ResourceLoadInfo& lhs, const ResourceLoadInfo& rhs);
} // namespace mojom
} // namespace content
#endif // CHROME_BROWSER_PREDICTORS_LOADING_TEST_UTIL_H_
// Copyright 2014 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/predictors/resource_prefetch_predictor_tab_helper.h"
#include <string>
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(
predictors::ResourcePrefetchPredictorTabHelper);
using content::BrowserThread;
namespace predictors {
ResourcePrefetchPredictorTabHelper::ResourcePrefetchPredictorTabHelper(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
}
ResourcePrefetchPredictorTabHelper::~ResourcePrefetchPredictorTabHelper() {
}
void ResourcePrefetchPredictorTabHelper::DocumentOnLoadCompletedInMainFrame() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* loading_predictor = LoadingPredictorFactory::GetForProfile(
Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
if (!loading_predictor)
return;
auto* collector = loading_predictor->loading_data_collector();
NavigationID navigation_id(web_contents());
collector->RecordMainFrameLoadComplete(navigation_id);
}
void ResourcePrefetchPredictorTabHelper::DidLoadResourceFromMemoryCache(
const GURL& url,
const std::string& mime_type,
content::ResourceType resource_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* loading_predictor = LoadingPredictorFactory::GetForProfile(
Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
if (!loading_predictor)
return;
if (!LoadingDataCollector::ShouldRecordResourceFromMemoryCache(
url, resource_type, mime_type)) {
return;
}
URLRequestSummary summary;
summary.navigation_id = NavigationID(web_contents());
summary.request_url = url;
summary.resource_type =
LoadingDataCollector::GetResourceType(resource_type, mime_type);
auto* collector = loading_predictor->loading_data_collector();
collector->RecordURLResponse(summary);
}
} // namespace predictors
// Copyright 2018 The Chromium Authors. All rights reserved.
// Copyright 2014 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.
#ifndef CHROME_BROWSER_PREDICTORS_LOADING_PREDICTOR_TAB_HELPER_H_
#define CHROME_BROWSER_PREDICTORS_LOADING_PREDICTOR_TAB_HELPER_H_
#ifndef CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCH_PREDICTOR_TAB_HELPER_H_
#define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCH_PREDICTOR_TAB_HELPER_H_
#include "base/macros.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
namespace content {
class NavigationHandle;
} // namespace content
namespace predictors {
class LoadingPredictor;
// Observes various page load events from the navigation start to onload
// completed and notifies the LoadingPredictor associated with the current
// profile.
//
// All methods must be called from the UI thread.
class LoadingPredictorTabHelper
class ResourcePrefetchPredictorTabHelper
: public content::WebContentsObserver,
public content::WebContentsUserData<LoadingPredictorTabHelper> {
public content::WebContentsUserData<ResourcePrefetchPredictorTabHelper> {
public:
~LoadingPredictorTabHelper() override;
~ResourcePrefetchPredictorTabHelper() override;
// content::WebContentsObserver implementation
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void ResourceLoadComplete(
content::RenderFrameHost* render_frame_host,
const content::mojom::ResourceLoadInfo& resource_load_info) override;
void DocumentOnLoadCompletedInMainFrame() override;
void DidLoadResourceFromMemoryCache(
const GURL& url,
const std::string& mime_type,
content::ResourceType resource_type) override;
void DocumentOnLoadCompletedInMainFrame() override;
void SetLoadingPredictorForTesting(
base::WeakPtr<LoadingPredictor> predictor) {
predictor_ = predictor;
}
private:
explicit LoadingPredictorTabHelper(content::WebContents* web_contents);
friend class content::WebContentsUserData<LoadingPredictorTabHelper>;
// Owned by profile.
base::WeakPtr<LoadingPredictor> predictor_;
explicit ResourcePrefetchPredictorTabHelper(
content::WebContents* web_contents);
friend class content::WebContentsUserData<ResourcePrefetchPredictorTabHelper>;
DISALLOW_COPY_AND_ASSIGN(LoadingPredictorTabHelper);
DISALLOW_COPY_AND_ASSIGN(ResourcePrefetchPredictorTabHelper);
};
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_LOADING_PREDICTOR_TAB_HELPER_H_
#endif // CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCH_PREDICTOR_TAB_HELPER_H_
......@@ -34,10 +34,13 @@
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/chrome_network_delegate.h"
#include "chrome/browser/net/chrome_url_request_context_getter.h"
#include "chrome/browser/net/loading_predictor_observer.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/policy/cloud/policy_header_service_factory.h"
#include "chrome/browser/policy/policy_helpers.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ssl/chrome_expect_ct_reporter.h"
......@@ -433,6 +436,13 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
extensions::ExtensionSystem::Get(profile)->info_map();
#endif
if (auto* loading_predictor =
predictors::LoadingPredictorFactory::GetForProfile(profile)) {
loading_predictor_observer_ =
std::make_unique<chrome_browser_net::LoadingPredictorObserver>(
loading_predictor);
}
ProtocolHandlerRegistry* protocol_handler_registry =
ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
DCHECK(protocol_handler_registry);
......@@ -1086,6 +1096,11 @@ void ProfileIOData::Init(
extension_info_map_ = profile_params_->extension_info_map;
#endif
if (profile_params_->loading_predictor_observer_) {
loading_predictor_observer_ =
std::move(profile_params_->loading_predictor_observer_);
}
#if defined(OS_CHROMEOS)
username_hash_ = profile_params_->username_hash;
system_key_slot_use_type_ = profile_params_->system_key_slot_use_type;
......
......@@ -49,6 +49,10 @@ namespace chromeos {
class CertificateProvider;
}
namespace chrome_browser_net {
class LoadingPredictorObserver;
}
namespace content_settings {
class CookieSettings;
}
......@@ -215,6 +219,11 @@ class ProfileIOData {
}
#endif
chrome_browser_net::LoadingPredictorObserver* loading_predictor_observer()
const {
return loading_predictor_observer_.get();
}
policy::PolicyHeaderIOHelper* policy_header_helper() const {
return policy_header_helper_.get();
}
......@@ -338,6 +347,8 @@ class ProfileIOData {
#if BUILDFLAG(ENABLE_EXTENSIONS)
scoped_refptr<extensions::InfoMap> extension_info_map;
#endif
std::unique_ptr<chrome_browser_net::LoadingPredictorObserver>
loading_predictor_observer_;
// This pointer exists only as a means of conveying a url job factory
// pointer from the protocol handler registry on the UI thread to the
......@@ -614,6 +625,9 @@ class ProfileIOData {
mutable scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
mutable std::unique_ptr<chrome_browser_net::LoadingPredictorObserver>
loading_predictor_observer_;
#if BUILDFLAG(ENABLE_EXTENSIONS)
// Is NULL if switches::kDisableExtensionsHttpThrottling is on.
mutable std::unique_ptr<extensions::ExtensionThrottleManager>
......
......@@ -769,10 +769,10 @@ IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBarDangerous) {
}
ASSERT_TRUE(https_server()->Start());
cert_verifier()->set_default_result(net::ERR_CERT_DATE_INVALID);
const GURL app_url = https_server()->GetURL("app.com", "/simple.html");
SetupAppWithURL(app_url);
cert_verifier()->set_default_result(net::ERR_CERT_DATE_INVALID);
// When DesktopPWAWindowing is enabled, proceeding through an interstitial
// results in the navigation being redirected to a regular tab. So we need
......
......@@ -39,7 +39,7 @@
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/plugins/pdf_plugin_placeholder_observer.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/predictors/loading_predictor_tab_helper.h"
#include "chrome/browser/predictors/resource_prefetch_predictor_tab_helper.h"
#include "chrome/browser/prerender/prerender_tab_helper.h"
#include "chrome/browser/previews/previews_infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
......@@ -336,8 +336,10 @@ offline_pages::RecentTabHelper::CreateForWebContents(web_contents);
web_contents);
}
if (predictors::LoadingPredictorFactory::GetForProfile(profile))
predictors::LoadingPredictorTabHelper::CreateForWebContents(web_contents);
if (predictors::LoadingPredictorFactory::GetForProfile(profile)) {
predictors::ResourcePrefetchPredictorTabHelper::CreateForWebContents(
web_contents);
}
if (tracing::NavigationTracingObserver::IsEnabled())
tracing::NavigationTracingObserver::CreateForWebContents(web_contents);
......
......@@ -2516,7 +2516,6 @@ test("unit_tests") {
"../browser/predictors/autocomplete_action_predictor_unittest.cc",
"../browser/predictors/loading_data_collector_unittest.cc",
"../browser/predictors/loading_predictor_config_unittest.cc",
"../browser/predictors/loading_predictor_tab_helper_unittest.cc",
"../browser/predictors/loading_predictor_unittest.cc",
"../browser/predictors/loading_stats_collector_unittest.cc",
"../browser/predictors/preconnect_manager_unittest.cc",
......
......@@ -29,7 +29,6 @@
#include "chrome/browser/lifetime/termination_notification.h"
#include "chrome/browser/net/chrome_network_delegate.h"
#include "chrome/browser/net/net_error_tab_helper.h"
#include "chrome/browser/predictors/loading_predictor_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
......@@ -173,12 +172,9 @@ void InProcessBrowserTest::SetUp() {
// here.
command_line->AppendSwitch(switches::kDisableOfflineAutoReload);
// Turn off preconnects because it breaks some browser tests, see
// http://crbug.com/60035.
std::vector<base::Feature> enabled_features = {};
std::vector<base::Feature> disabled_features = {
features::kNetworkPrediction, predictors::kSpeculativePreconnectFeature};
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
// Turn off preconnects because they break the brittle python webserver;
// see http://crbug.com/60035.
scoped_feature_list_.InitAndDisableFeature(features::kNetworkPrediction);
// Allow subclasses to change the command line before running any tests.
SetUpCommandLine(command_line);
......
......@@ -6,7 +6,7 @@
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event.h"
#include "content/public/browser/browser_thread.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/resource_hints.h"
#include "net/base/address_list.h"
#include "net/base/load_flags.h"
......@@ -38,7 +38,9 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
const GURL& site_for_cookies,
int count,
bool allow_credentials) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(ResourceDispatcherHostImpl::Get()
->io_thread_task_runner()
->BelongsToCurrentThread());
DCHECK(getter);
TRACE_EVENT2("net", "PreconnectUrl", "url", url.spec(), "count", count);
......@@ -60,9 +62,6 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
user_agent);
net::NetworkDelegate* delegate = request_context->network_delegate();
// NetworkDelegate is not set in tests.
if (!delegate)
return;
if (delegate->CanEnablePrivacyMode(url, site_for_cookies))
request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
......@@ -84,7 +83,9 @@ int PreresolveUrl(net::URLRequestContextGetter* getter,
const GURL& url,
const net::CompletionCallback& callback,
std::unique_ptr<net::HostResolver::Request>* out_request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(ResourceDispatcherHostImpl::Get()
->io_thread_task_runner()
->BelongsToCurrentThread());
DCHECK(getter);
TRACE_EVENT1("net", "PreresolveUrl", "url", url.spec());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment