Commit 94eb8290 authored by Tarun Bansal's avatar Tarun Bansal Committed by Commit Bot

Optimization guide: Fetch hints from remote service

Fetch hints from remote service at the time of navigation.
Hints are fetched only if connection is slow.

Change-Id: I37e13072b17e1adfe9b3365e2dca04ae9bdfc246
Bug: 933898
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829474
Commit-Queue: Tarun Bansal <tbansal@chromium.org>
Reviewed-by: default avatarSophie Chang <sophiechang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702116}
parent 23301d6f
...@@ -490,6 +490,8 @@ void OptimizationGuideHintsManager::OnHintsFetched( ...@@ -490,6 +490,8 @@ void OptimizationGuideHintsManager::OnHintsFetched(
OnTopHostsHintsFetched(std::move(get_hints_response)); OnTopHostsHintsFetched(std::move(get_hints_response));
return; return;
case optimization_guide::proto::CONTEXT_PAGE_NAVIGATION: case optimization_guide::proto::CONTEXT_PAGE_NAVIGATION:
OnPageNavigationHintsFetched(std::move(get_hints_response));
return;
case optimization_guide::proto::CONTEXT_UNSPECIFIED: case optimization_guide::proto::CONTEXT_UNSPECIFIED:
NOTREACHED(); NOTREACHED();
} }
...@@ -517,6 +519,19 @@ void OptimizationGuideHintsManager::OnTopHostsHintsFetched( ...@@ -517,6 +519,19 @@ void OptimizationGuideHintsManager::OnTopHostsHintsFetched(
} }
} }
void OptimizationGuideHintsManager::OnPageNavigationHintsFetched(
base::Optional<std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response) {
if (!get_hints_response.has_value() || !get_hints_response.value())
return;
hint_cache_->UpdateFetchedHints(
std::move(*get_hints_response), clock_->Now() + kUpdateFetchedHintsDelay,
base::BindOnce(
&OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored,
ui_weak_ptr_factory_.GetWeakPtr()));
}
void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() { void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() {
LOCAL_HISTOGRAM_BOOLEAN("OptimizationGuide.FetchedHints.Stored", true); LOCAL_HISTOGRAM_BOOLEAN("OptimizationGuide.FetchedHints.Stored", true);
...@@ -526,6 +541,11 @@ void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() { ...@@ -526,6 +541,11 @@ void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() {
&OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch); &OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch);
} }
void OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored() {
for (const auto& url : navigation_urls_last_fetched_real_time_)
LoadHintForURL(url, base::DoNothing());
}
base::Time OptimizationGuideHintsManager::GetLastHintsFetchAttemptTime() const { base::Time OptimizationGuideHintsManager::GetLastHintsFetchAttemptTime() const {
return base::Time::FromDeltaSinceWindowsEpoch( return base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(pref_service_->GetInt64( base::TimeDelta::FromMicroseconds(pref_service_->GetInt64(
...@@ -561,6 +581,14 @@ void OptimizationGuideHintsManager::LoadHintForNavigation( ...@@ -561,6 +581,14 @@ void OptimizationGuideHintsManager::LoadHintForNavigation(
} }
} }
LoadHintForURL(url, std::move(callback));
}
void OptimizationGuideHintsManager::LoadHintForURL(const GURL& url,
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(url.has_host());
hint_cache_->LoadHint( hint_cache_->LoadHint(
url.host(), url.host(),
base::BindOnce(&OptimizationGuideHintsManager::OnHintLoaded, base::BindOnce(&OptimizationGuideHintsManager::OnHintLoaded,
...@@ -780,6 +808,58 @@ void OptimizationGuideHintsManager::OnEffectiveConnectionTypeChanged( ...@@ -780,6 +808,58 @@ void OptimizationGuideHintsManager::OnEffectiveConnectionTypeChanged(
current_effective_connection_type_ = effective_connection_type; current_effective_connection_type_ = effective_connection_type;
} }
bool OptimizationGuideHintsManager::IsAllowedToFetchNavigationHints(
const GURL& url) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!IsUserPermittedToFetchHints(profile_))
return false;
if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme))
return false;
base::Optional<net::EffectiveConnectionType> ect_max_threshold =
optimization_guide::features::
GetMaxEffectiveConnectionTypeForNavigationHintsFetch();
// If the threshold is unavailable, return early since there is no safe way to
// proceed.
if (!ect_max_threshold.has_value())
return false;
if (current_effective_connection_type_ <
net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G ||
current_effective_connection_type_ > ect_max_threshold.value()) {
return false;
}
return true;
}
void OptimizationGuideHintsManager::OnNavigationStartOrRedirect(
content::NavigationHandle* navigation_handle,
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (IsAllowedToFetchNavigationHints(navigation_handle->GetURL())) {
std::vector<std::string> hosts{navigation_handle->GetURL().host()};
navigation_urls_last_fetched_real_time_.clear();
navigation_urls_last_fetched_real_time_.push_back(
navigation_handle->GetURL());
if (!hints_fetcher_) {
hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>(
url_loader_factory_,
optimization_guide::features::GetOptimizationGuideServiceURL(),
pref_service_);
}
hints_fetcher_->FetchOptimizationGuideServiceHints(
hosts, optimization_guide::proto::CONTEXT_PAGE_NAVIGATION,
base::BindOnce(&OptimizationGuideHintsManager::OnHintsFetched,
ui_weak_ptr_factory_.GetWeakPtr()));
}
LoadHintForNavigation(navigation_handle, std::move(callback));
}
void OptimizationGuideHintsManager::ClearFetchedHints() { void OptimizationGuideHintsManager::ClearFetchedHints() {
hint_cache_->ClearFetchedHints(); hint_cache_->ClearFetchedHints();
optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched( optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched(
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "components/optimization_guide/hints_component_info.h" #include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/optimization_guide_service_observer.h" #include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/optimization_guide/proto/hints.pb.h" #include "components/optimization_guide/proto/hints.pb.h"
#include "net/nqe/effective_connection_type.h"
#include "services/network/public/cpp/network_quality_tracker.h" #include "services/network/public/cpp/network_quality_tracker.h"
namespace base { namespace base {
...@@ -82,13 +83,6 @@ class OptimizationGuideHintsManager ...@@ -82,13 +83,6 @@ class OptimizationGuideHintsManager
// is called and the corresponding hints have been updated. // is called and the corresponding hints have been updated.
void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure); void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure);
// Loads the hint if available.
// |callback| is run when the request has finished regardless of whether there
// was actually a hint for that load or not. The callback can be used as a
// signal for tests.
void LoadHintForNavigation(content::NavigationHandle* navigation_handle,
base::OnceClosure callback);
// Registers the optimization types that have the potential for hints to be // Registers the optimization types that have the potential for hints to be
// called by consumers of the Optimization Guide. // called by consumers of the Optimization Guide.
void RegisterOptimizationTypes( void RegisterOptimizationTypes(
...@@ -136,6 +130,13 @@ class OptimizationGuideHintsManager ...@@ -136,6 +130,13 @@ class OptimizationGuideHintsManager
void OnEffectiveConnectionTypeChanged( void OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType type) override; net::EffectiveConnectionType type) override;
// Notifies |this| that a navigation with |navigation_handle| has started.
// |callback| is run when the request has finished regardless of whether there
// was actually a hint for that load or not. The callback can be used as a
// signal for tests.
void OnNavigationStartOrRedirect(content::NavigationHandle* navigation_handle,
base::OnceClosure callback);
private: private:
// Processes the hints component. // Processes the hints component.
// //
...@@ -194,16 +195,29 @@ class OptimizationGuideHintsManager ...@@ -194,16 +195,29 @@ class OptimizationGuideHintsManager
get_hints_response); get_hints_response);
// Called when the hints for the top hosts have been fetched from the remote // Called when the hints for the top hosts have been fetched from the remote
// Optimization Guide Service and are ready for parsing. // Optimization Guide Service and are ready for parsing. This is used when
// fetching hints in batch mode.
void OnTopHostsHintsFetched( void OnTopHostsHintsFetched(
base::Optional< base::Optional<
std::unique_ptr<optimization_guide::proto::GetHintsResponse>> std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response); get_hints_response);
// Called when the hints for a navigation have been fetched from the remote
// Optimization Guide Service and are ready for parsing. This is used when
// fetching hints in real-time.
void OnPageNavigationHintsFetched(
base::Optional<
std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response);
// Called when the fetched hints have been stored in |hint_cache| and are // Called when the fetched hints have been stored in |hint_cache| and are
// ready to be used. // ready to be used. This is used when hints were fetched in batch mode.
void OnFetchedTopHostsHintsStored(); void OnFetchedTopHostsHintsStored();
// Called when the fetched hints have been stored in |hint_cache| and are
// ready to be used. This is used when hints were fetched in real-time.
void OnFetchedPageNavigationHintsStored();
// Returns the time when a hints fetch request was last attempted. // Returns the time when a hints fetch request was last attempted.
base::Time GetLastHintsFetchAttemptTime() const; base::Time GetLastHintsFetchAttemptTime() const;
...@@ -214,6 +228,23 @@ class OptimizationGuideHintsManager ...@@ -214,6 +228,23 @@ class OptimizationGuideHintsManager
void OnHintLoaded(base::OnceClosure callback, void OnHintLoaded(base::OnceClosure callback,
const optimization_guide::proto::Hint* loaded_hint) const; const optimization_guide::proto::Hint* loaded_hint) const;
// Returns true if |this| is allowed to fetch hints at the navigation time for
// |url|.
bool IsAllowedToFetchNavigationHints(const GURL& url) const;
// Loads the hint if available.
// |callback| is run when the request has finished regardless of whether there
// was actually a hint for that load or not. The callback can be used as a
// signal for tests.
void LoadHintForNavigation(content::NavigationHandle* navigation_handle,
base::OnceClosure callback);
// Loads the hint for |url| if available.
// |callback| is run when the request has finished regardless of whether there
// was actually a hint for that |url| or not. The callback can be used as a
// signal for tests.
void LoadHintForURL(const GURL& url, base::OnceClosure callback);
// The OptimizationGuideService that this guide is listening to. Not owned. // The OptimizationGuideService that this guide is listening to. Not owned.
optimization_guide::OptimizationGuideService* const optimization_guide::OptimizationGuideService* const
optimization_guide_service_; optimization_guide_service_;
...@@ -282,6 +313,9 @@ class OptimizationGuideHintsManager ...@@ -282,6 +313,9 @@ class OptimizationGuideHintsManager
// Used in testing to subscribe to an update event in this class. // Used in testing to subscribe to an update event in this class.
base::OnceClosure next_update_closure_; base::OnceClosure next_update_closure_;
// URLs for which hints were last fetched in the real-time.
std::vector<GURL> navigation_urls_last_fetched_real_time_;
// Used to get |weak_ptr_| to self on the UI thread. // Used to get |weak_ptr_| to self on the UI thread.
base::WeakPtrFactory<OptimizationGuideHintsManager> ui_weak_ptr_factory_{ base::WeakPtrFactory<OptimizationGuideHintsManager> ui_weak_ptr_factory_{
this}; this};
......
...@@ -143,8 +143,12 @@ void OptimizationGuideKeyedService::Initialize( ...@@ -143,8 +143,12 @@ void OptimizationGuideKeyedService::Initialize(
void OptimizationGuideKeyedService::MaybeLoadHintForNavigation( void OptimizationGuideKeyedService::MaybeLoadHintForNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
if (hints_manager_ && hints_manager_->HasRegisteredOptimizationTypes()) DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
hints_manager_->LoadHintForNavigation(navigation_handle, base::DoNothing());
if (hints_manager_ && hints_manager_->HasRegisteredOptimizationTypes()) {
hints_manager_->OnNavigationStartOrRedirect(navigation_handle,
base::DoNothing());
}
} }
void OptimizationGuideKeyedService::RegisterOptimizationTypes( void OptimizationGuideKeyedService::RegisterOptimizationTypes(
......
...@@ -149,5 +149,18 @@ int MaxServerBloomFilterByteSize() { ...@@ -149,5 +149,18 @@ int MaxServerBloomFilterByteSize() {
250 * 1024 /* 250KB */); 250 * 1024 /* 250KB */);
} }
base::Optional<net::EffectiveConnectionType>
GetMaxEffectiveConnectionTypeForNavigationHintsFetch() {
std::string param_value = base::GetFieldTrialParamValueByFeature(
features::kOptimizationHintsFetching,
"max_effective_connection_type_for_navigation_hints_fetch");
// Use a default value.
if (param_value.empty())
return net::EFFECTIVE_CONNECTION_TYPE_3G;
return net::GetEffectiveConnectionTypeForName(param_value);
}
} // namespace features } // namespace features
} // namespace optimization_guide } // namespace optimization_guide
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include <utility> #include <utility>
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/optional.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "net/nqe/effective_connection_type.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace optimization_guide { namespace optimization_guide {
...@@ -73,6 +75,12 @@ bool IsOptimizationGuideKeyedServiceEnabled(); ...@@ -73,6 +75,12 @@ bool IsOptimizationGuideKeyedServiceEnabled();
// a bloom filter. // a bloom filter.
int MaxServerBloomFilterByteSize(); int MaxServerBloomFilterByteSize();
// Maximum effective connection type at which hints can be fetched for
// navigations in real-time. Returns null if the hints fetching for navigations
// is disabled.
base::Optional<net::EffectiveConnectionType>
GetMaxEffectiveConnectionTypeForNavigationHintsFetch();
} // namespace features } // namespace features
} // namespace optimization_guide } // namespace optimization_guide
......
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