Commit 57c1accd authored by Sophie Chang's avatar Sophie Chang Committed by Commit Bot

Parse optimization filters in Opt Guide Keyed Service

This only loads the filter in memory if the type is registered

Bug: 969558
Change-Id: I512b9d14cd41bb20bb5c767ff57b061c0725ca33
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1740890
Commit-Queue: Sophie Chang <sophiechang@chromium.org>
Reviewed-by: default avatarDoug Arnett <dougarnett@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685371}
parent e19f823a
......@@ -13,15 +13,15 @@
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "components/optimization_guide/bloom_filter.h"
#include "components/optimization_guide/hint_cache.h"
#include "components/optimization_guide/hint_cache_store.h"
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/hints_component_util.h"
#include "components/optimization_guide/hints_processing_util.h"
#include "components/optimization_guide/optimization_filter.h"
#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/optimization_guide_service.h"
#include "components/optimization_guide/optimization_guide_switches.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
......@@ -33,27 +33,6 @@ namespace {
// will have a newer version than it.
constexpr char kManualConfigComponentVersion[] = "0.0.0";
std::unique_ptr<optimization_guide::HintUpdateData> ProcessHintsComponent(
const optimization_guide::HintsComponentInfo& info,
std::unique_ptr<optimization_guide::HintUpdateData> update_data) {
optimization_guide::ProcessHintsComponentResult out_result;
std::unique_ptr<optimization_guide::proto::Configuration> config =
optimization_guide::ProcessHintsComponent(info, &out_result);
if (!config) {
optimization_guide::RecordProcessHintsComponentResult(out_result);
return nullptr;
}
bool did_process_hints = optimization_guide::ProcessHints(
config->mutable_hints(), update_data.get());
optimization_guide::RecordProcessHintsComponentResult(
did_process_hints
? optimization_guide::ProcessHintsComponentResult::kSuccess
: optimization_guide::ProcessHintsComponentResult::kProcessedNoHints);
return update_data;
}
void MaybeRunUpdateClosure(base::OnceClosure update_closure) {
if (update_closure)
std::move(update_closure).Run();
......@@ -138,16 +117,6 @@ void OptimizationGuideHintsManager::OnHintsComponentAvailable(
return;
}
std::unique_ptr<optimization_guide::HintUpdateData> update_data =
hint_cache_->MaybeCreateUpdateDataForComponentHints(info.version);
if (!update_data) {
optimization_guide::RecordProcessHintsComponentResult(
optimization_guide::ProcessHintsComponentResult::
kSkippedProcessingHints);
MaybeRunUpdateClosure(std::move(next_update_closure_));
return;
}
if (!CanProcessComponentVersion(pref_service_, info.version)) {
optimization_guide::RecordProcessHintsComponentResult(
optimization_guide::ProcessHintsComponentResult::
......@@ -156,6 +125,9 @@ void OptimizationGuideHintsManager::OnHintsComponentAvailable(
return;
}
std::unique_ptr<optimization_guide::HintUpdateData> update_data =
hint_cache_->MaybeCreateUpdateDataForComponentHints(info.version);
// Processes the hints from the newly available component on a background
// thread, providing a HintUpdateData for component update from the hint
// cache, so that each hint within the component can be moved into it. In the
......@@ -165,10 +137,107 @@ void OptimizationGuideHintsManager::OnHintsComponentAvailable(
// created PreviewsHints, it is initialized in UpdateHints() on the UI thread.
base::PostTaskAndReplyWithResult(
background_task_runner_.get(), FROM_HERE,
base::BindOnce(&ProcessHintsComponent, info, std::move(update_data)),
base::BindOnce(&OptimizationGuideHintsManager::ProcessHintsComponent,
base::Unretained(this), info,
registered_optimization_types_, std::move(update_data)),
base::BindOnce(&OptimizationGuideHintsManager::UpdateComponentHints,
ui_weak_ptr_factory_.GetWeakPtr(),
std::move(next_update_closure_)));
// Only replace hints component info if it is not the same - otherwise we will
// destruct the object and it will be invalid later.
if (!hints_component_info_ ||
hints_component_info_->version.CompareTo(info.version) != 0) {
hints_component_info_.emplace(info.version, info.path);
}
}
std::unique_ptr<optimization_guide::HintUpdateData>
OptimizationGuideHintsManager::ProcessHintsComponent(
const optimization_guide::HintsComponentInfo& info,
const std::unordered_set<optimization_guide::proto::OptimizationType>&
registered_optimization_types,
std::unique_ptr<optimization_guide::HintUpdateData> update_data) {
DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
optimization_guide::ProcessHintsComponentResult out_result;
std::unique_ptr<optimization_guide::proto::Configuration> config =
optimization_guide::ProcessHintsComponent(info, &out_result);
if (!config) {
optimization_guide::RecordProcessHintsComponentResult(out_result);
return nullptr;
}
ProcessOptimizationFilters(config->optimization_blacklists(),
registered_optimization_types);
if (update_data) {
bool did_process_hints = optimization_guide::ProcessHints(
config->mutable_hints(), update_data.get());
optimization_guide::RecordProcessHintsComponentResult(
did_process_hints
? optimization_guide::ProcessHintsComponentResult::kSuccess
: optimization_guide::ProcessHintsComponentResult::
kProcessedNoHints);
} else {
optimization_guide::RecordProcessHintsComponentResult(
optimization_guide::ProcessHintsComponentResult::
kSkippedProcessingHints);
}
return update_data;
}
void OptimizationGuideHintsManager::ProcessOptimizationFilters(
const google::protobuf::RepeatedPtrField<
optimization_guide::proto::OptimizationFilter>&
blacklist_optimization_filters,
const std::unordered_set<optimization_guide::proto::OptimizationType>&
registered_optimization_types) {
DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
base::AutoLock lock(optimization_filters_lock_);
available_optimization_filters_.clear();
blacklist_optimization_filters_.clear();
for (const auto& filter : blacklist_optimization_filters) {
if (filter.optimization_type() !=
optimization_guide::proto::TYPE_UNSPECIFIED) {
available_optimization_filters_.insert(filter.optimization_type());
}
// Do not put anything in memory that we don't have registered.
if (registered_optimization_types.find(filter.optimization_type()) ==
registered_optimization_types.end()) {
continue;
}
optimization_guide::RecordOptimizationFilterStatus(
filter.optimization_type(),
optimization_guide::OptimizationFilterStatus::
kFoundServerBlacklistConfig);
// Do not parse duplicate optimization filters.
if (blacklist_optimization_filters_.find(filter.optimization_type()) !=
blacklist_optimization_filters_.end()) {
optimization_guide::RecordOptimizationFilterStatus(
filter.optimization_type(),
optimization_guide::OptimizationFilterStatus::
kFailedServerBlacklistDuplicateConfig);
continue;
}
// Parse optimization filter.
optimization_guide::OptimizationFilterStatus status;
std::unique_ptr<optimization_guide::OptimizationFilter>
optimization_filter =
optimization_guide::ProcessOptimizationFilter(filter, &status);
if (optimization_filter) {
blacklist_optimization_filters_.insert(
{filter.optimization_type(), std::move(optimization_filter)});
}
optimization_guide::RecordOptimizationFilterStatus(
filter.optimization_type(), status);
}
}
void OptimizationGuideHintsManager::OnHintCacheInitialized() {
......@@ -266,3 +335,43 @@ void OptimizationGuideHintsManager::OnHintLoaded(
// tests.
std::move(callback).Run();
}
void OptimizationGuideHintsManager::RegisterOptimizationTypes(
std::vector<optimization_guide::proto::OptimizationType>
optimization_types) {
bool should_load_new_optimization_filter = false;
for (const auto optimization_type : optimization_types) {
if (optimization_type == optimization_guide::proto::TYPE_UNSPECIFIED)
continue;
if (registered_optimization_types_.find(optimization_type) !=
registered_optimization_types_.end()) {
continue;
}
registered_optimization_types_.insert(optimization_type);
if (!should_load_new_optimization_filter) {
base::AutoLock lock(optimization_filters_lock_);
if (available_optimization_filters_.find(optimization_type) !=
available_optimization_filters_.end()) {
should_load_new_optimization_filter = true;
}
}
}
if (should_load_new_optimization_filter) {
DCHECK(hints_component_info_);
OnHintsComponentAvailable(*hints_component_info_);
} else {
MaybeRunUpdateClosure(std::move(next_update_closure_));
}
}
bool OptimizationGuideHintsManager::HasLoadedOptimizationFilter(
optimization_guide::proto::OptimizationType optimization_type) {
base::AutoLock lock(optimization_filters_lock_);
return blacklist_optimization_filters_.find(optimization_type) !=
blacklist_optimization_filters_.end();
}
......@@ -6,11 +6,18 @@
#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_HINTS_MANAGER_H_
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/optimization_guide/proto/hints.pb.h"
namespace base {
class FilePath;
......@@ -25,12 +32,9 @@ class ProtoDatabaseProvider;
} // namespace leveldb_proto
namespace optimization_guide {
namespace proto {
class Hint;
} // namespace proto
class HintCache;
class HintUpdateData;
struct HintsComponentInfo;
class OptimizationFilter;
class OptimizationGuideService;
} // namespace optimization_guide
......@@ -65,7 +69,44 @@ class OptimizationGuideHintsManager
void LoadHintForNavigation(content::NavigationHandle* navigation_handle,
base::OnceClosure callback);
// Registers the optimization types that have the potential for hints to be
// called by consumers of the Optimization Guide.
void RegisterOptimizationTypes(
std::vector<optimization_guide::proto::OptimizationType>
optimization_types);
// Returns whether there have been any optimization types registered.
bool HasRegisteredOptimizationTypes() const {
return !registered_optimization_types_.empty();
}
// Returns whether there is an optimization filter loaded for
// |optimization_type|.
bool HasLoadedOptimizationFilter(
optimization_guide::proto::OptimizationType optimization_type);
private:
// Processes the hints component.
//
// Should always be called on the thread that belongs to
// |background_task_runner_|.
std::unique_ptr<optimization_guide::HintUpdateData> ProcessHintsComponent(
const optimization_guide::HintsComponentInfo& info,
const std::unordered_set<optimization_guide::proto::OptimizationType>&
registered_optimization_types,
std::unique_ptr<optimization_guide::HintUpdateData> update_data);
// Processes the optimization filters contained in the hints component.
//
// Should always be called on the thread that belongs to
// |background_task_runner_|.
void ProcessOptimizationFilters(
const google::protobuf::RepeatedPtrField<
optimization_guide::proto::OptimizationFilter>&
blacklist_optimization_filters,
const std::unordered_set<optimization_guide::proto::OptimizationType>&
registered_optimization_types);
// Callback run after the hint cache is fully initialized. At this point, the
// OptimizationGuideHintsManager is ready to process hints.
void OnHintCacheInitialized();
......@@ -88,6 +129,31 @@ class OptimizationGuideHintsManager
optimization_guide::OptimizationGuideService* const
optimization_guide_service_;
// The information of the latest component delivered by
// |optimization_guide_service_|.
base::Optional<optimization_guide::HintsComponentInfo> hints_component_info_;
// The set of optimization types that have been registered with the hints
// manager.
//
// Should only be read and modified on the UI thread.
std::unordered_set<optimization_guide::proto::OptimizationType>
registered_optimization_types_;
// Synchronizes access to member variables related to optimization filters.
base::Lock optimization_filters_lock_;
// The set of optimization types that the component specified by
// |component_info_| has optimization filters for.
std::unordered_set<optimization_guide::proto::OptimizationType>
available_optimization_filters_ GUARDED_BY(optimization_filters_lock_);
// A map from optimization type to the host filter that holds the blacklist
// for that type.
std::unordered_map<optimization_guide::proto::OptimizationType,
std::unique_ptr<optimization_guide::OptimizationFilter>>
blacklist_optimization_filters_ GUARDED_BY(optimization_filters_lock_);
// Background thread where hints processing should be performed.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
......
......@@ -41,17 +41,15 @@ void OptimizationGuideKeyedService::Initialize(
void OptimizationGuideKeyedService::RegisterOptimizationTypes(
std::vector<optimization_guide::proto::OptimizationType>
optimization_types) {
for (const auto optimization_type : optimization_types) {
registered_optimization_types_.insert(optimization_type);
}
DCHECK(hints_manager_);
hints_manager_->RegisterOptimizationTypes(optimization_types);
}
void OptimizationGuideKeyedService::MaybeLoadHintForNavigation(
content::NavigationHandle* navigation_handle) {
if (!hints_manager_ || registered_optimization_types_.empty())
return;
hints_manager_->LoadHintForNavigation(navigation_handle, base::DoNothing());
if (hints_manager_ && hints_manager_->HasRegisteredOptimizationTypes())
hints_manager_->LoadHintForNavigation(navigation_handle, base::DoNothing());
}
void OptimizationGuideKeyedService::Shutdown() {
......
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