blob: b36b65bd3ccb3bc902bbf98a2b5994d50a028a1a [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_
#define COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/time/clock.h"
#include "base/timer/timer.h"
#include "components/optimization_guide/hint_cache.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/previews/content/previews_optimization_guide.h"
#include "components/previews/core/previews_experiments.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "url/gurl.h"
class PrefService;
namespace base {
class FilePath;
} // namespace base
namespace content {
class NavigationHandle;
} // namespace content
namespace network {
class SharedURLLoaderFactory;
} // namespace network
namespace optimization_guide {
struct HintsComponentInfo;
class HintsFetcher;
class OptimizationGuideService;
class TopHostProvider;
namespace proto {
class Hint;
} // namespace proto
} // namespace optimization_guide
namespace previews {
class PreviewsHints;
class PreviewsUserData;
// A Previews optimization guide that makes decisions guided by hints received
// from the OptimizationGuideService.
class PreviewsOptimizationGuideImpl
: public PreviewsOptimizationGuide,
public optimization_guide::OptimizationGuideServiceObserver,
public network::NetworkQualityTracker::EffectiveConnectionTypeObserver {
public:
// The embedder guarantees |optimization_guide_service| outlives |this|.
// The embedder guarantees that |previews_top_host_provider_| outlives |this|.
PreviewsOptimizationGuideImpl(
optimization_guide::OptimizationGuideService* optimization_guide_service,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
const base::FilePath& profile_path,
PrefService* pref_service,
leveldb_proto::ProtoDatabaseProvider* database_provider,
optimization_guide::TopHostProvider* top_host_provider,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
network::NetworkQualityTracker* network_quality_tracker);
~PreviewsOptimizationGuideImpl() override;
// PreviewsOptimizationGuide implementation:
bool IsReady() const override;
bool CanApplyPreview(PreviewsUserData* previews_data,
content::NavigationHandle* navigation_handle,
PreviewsType type) override;
bool MaybeLoadOptimizationHints(content::NavigationHandle* navigation_handle,
base::OnceClosure callback) override;
bool GetResourceLoadingHints(
const GURL& url,
std::vector<std::string>* out_resource_patterns_to_block) override;
void LogHintCacheMatch(const GURL& url, bool is_committed) const override;
void ClearFetchedHints() override;
// optimization_guide::OptimizationGuideServiceObserver implementation:
// Called by OptimizationGuideService when a new component is available for
// processing.
void OnHintsComponentAvailable(
const optimization_guide::HintsComponentInfo& info) override;
// network::NetworkQualityTracker::EffectiveConnectionTypeObserver
// implementation:
void OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType effective_connection_type) override;
PreviewsHints* GetHintsForTesting() { return hints_.get(); }
// |next_update_closure| is called the next time OnHintsComponentAvailable is
// called and the corresponding hints have been updated.
void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure);
// Set |time_clock_| for testing.
void SetTimeClockForTesting(const base::Clock* time_clock);
// Set |hints_fetcher_| for testing.
void SetHintsFetcherForTesting(
std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher);
optimization_guide::HintsFetcher* GetHintsFetcherForTesting();
// Called when the hints store is initialized to determine when hints
// should be fetched and schedules the |hints_fetch_timer_| to fire based on:
// 1. The update time for the fetched hints in the store and
// 2. The last time a fetch attempt was made, |last_fetch_attempt_|.
void ScheduleHintsFetch();
protected:
// Callback executed after remote hints have been fetched and returned from
// the remote Optimization Guide Service. At this point, the hints response
// is ready to be processed and stored for use. Virtual to be mocked in
// testing.
virtual void OnHintsFetched(
base::Optional<
std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response);
// Callback executed after the Hints have been successfully stored in the
// store. Virtual to be mocked in tests.
virtual void OnFetchedHintsStored();
private:
// Callback run after the hint cache is fully initialized. At this point, the
// PreviewsOptimizationGuide is ready to process components from the
// OptimizationGuideService and registers as an observer with it.
void OnHintCacheInitialized();
// Updates the hints to the latest hints sent by the Component Updater.
// |update_closure| is called once the hints are updated.
void UpdateHints(base::OnceClosure update_closure,
std::unique_ptr<PreviewsHints> hints);
// Called when the hints have been fully updated with the latest hints from
// the Component Updater. This is used as a signal during tests.
// |update_closure| is called immediately if not null.
void OnHintsUpdated(base::OnceClosure update_closure);
// Callback when a hint is loaded.
void OnLoadedHint(base::OnceClosure callback,
const GURL& document_url,
const optimization_guide::proto::Hint* loaded_hint) const;
// Method to request new hints for user's sites based on
// engagement scores using |hints_fetcher_|.
void FetchHints();
// Return the time when a hints fetch request was last attempted.
base::Time GetLastHintsFetchAttemptTime() const;
// Set the time when a hints fetch was last attempted to |last_attempt_time|.
void SetLastHintsFetchAttemptTime(base::Time last_attempt_time);
// The OptimizationGuideService that this guide is listening to. Not owned.
optimization_guide::OptimizationGuideService* optimization_guide_service_;
// Runner for UI thread tasks.
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
// Background thread where hints processing should be performed.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
// The hint cache used by PreviewsHints. It is owned by
// PreviewsOptimizationGuide so that the existing hint cache can be reused on
// component updates. Otherwise, a new cache and store would need to be
// created during each component update.
std::unique_ptr<optimization_guide::HintCache> hint_cache_;
// The current hints used for this optimization guide.
std::unique_ptr<PreviewsHints> hints_;
// Used in testing to subscribe to an update event in this class.
base::OnceClosure next_update_closure_;
// HintsFetcher handles making the request for updated hints from the remote
// Optimization Guide Service.
std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher_;
// Timer to schedule when to fetch hints from the remote Optimization Guide
// Service.
base::OneShotTimer hints_fetch_timer_;
// TopHostProvider that this guide can query. Not owned.
optimization_guide::TopHostProvider* top_host_provider_ = nullptr;
// Clock used for scheduling the |hints_fetch_timer_|.
const base::Clock* time_clock_;
// A reference to the PrefService for this profile. Not owned.
PrefService* pref_service_ = nullptr;
// Used for fetching Hints by the Hints Fetcher.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// The network quality tracker that this guide is listening to. Not owned.
network::NetworkQualityTracker* network_quality_tracker_;
// The current estimate of the effective connection type.
net::EffectiveConnectionType current_effective_connection_type_ =
net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
// Used to get |weak_ptr_| to self on the UI thread.
base::WeakPtrFactory<PreviewsOptimizationGuideImpl> ui_weak_ptr_factory_{
this};
DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuideImpl);
};
} // namespace previews
#endif // COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_