blob: 0fc415af9276a60e9e9f1a5c0b8e34345ef19784 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_
#define CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_
#include <memory>
#include <unordered_set>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/navigation_predictor/search_engine_preconnector.h"
#include "components/keyed_service/core/keyed_service.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
class WebContents;
} // namespace content
// Keyed service that can be used to receive notifications about the URLs for
// the next predicted navigation.
class NavigationPredictorKeyedService : public KeyedService {
public:
// Indicates how the set of next navigation URLs were predicted.
enum class PredictionSource {
// Next navigation URLs were predicted by navigation predictor by parsing
// the anchor element metrics on a webpage.
kAnchorElementsParsedFromWebPage = 0,
};
// Stores the next set of URLs that the user is expected to navigate to.
class Prediction {
public:
Prediction(content::WebContents* web_contents,
const absl::optional<GURL>& source_document_url,
PredictionSource prediction_source,
const std::vector<GURL>& sorted_predicted_urls);
Prediction(const Prediction& other);
Prediction& operator=(const Prediction& other);
~Prediction();
const absl::optional<GURL>& source_document_url() const;
PredictionSource prediction_source() const { return prediction_source_; }
const std::vector<GURL>& sorted_predicted_urls() const;
// Null if the prediction source is kExternalAndroidApp.
content::WebContents* web_contents() const;
private:
// The WebContents from where the navigation may happen. Do not use this
// pointer outside the observer's call stack unless its destruction is also
// observed.
content::WebContents* web_contents_;
// TODO(spelchat): this no longer needs to be optional. Optionality was
// required because external app predictions didn't provide this field, but
// external predictions are no longer supported.
// Current URL of the document from where the navigtion may happen.
absl::optional<GURL> source_document_url_;
// |prediction_source_| indicates how the prediction was generated and
// affects how the prediction should be consumed. If the
// |prediction_source_| is kAnchorElementsParsedFromWebPage, then
// |source_document_url_| is the webpage from where the predictions were
// generated.
PredictionSource prediction_source_;
// Ordered set of URLs that the user is expected to navigate to next. The
// URLs are in the decreasing order of click probability.
std::vector<GURL> sorted_predicted_urls_;
};
// Observer class can be implemented to receive notifications about the
// predicted URLs for the next navigation. OnPredictionUpdated() is called
// every time a new prediction is available. Prediction includes the source
// document as well as the ordered list of URLs that the user may navigate to
// next. OnPredictionUpdated() may be called multiple times for the same
// source document URL.
//
// Observers must follow relevant privacy guidelines when consuming the
// notifications.
class Observer {
public:
virtual void OnPredictionUpdated(
const absl::optional<Prediction> prediction) = 0;
protected:
Observer() {}
virtual ~Observer() {}
};
explicit NavigationPredictorKeyedService(
content::BrowserContext* browser_context);
NavigationPredictorKeyedService(const NavigationPredictorKeyedService&) =
delete;
NavigationPredictorKeyedService& operator=(
const NavigationPredictorKeyedService&) = delete;
~NavigationPredictorKeyedService() override;
SearchEnginePreconnector* search_engine_preconnector();
// |document_url| may be invalid. Called by navigation predictor.
void OnPredictionUpdated(content::WebContents* web_contents,
const GURL& document_url,
PredictionSource prediction_source,
const std::vector<GURL>& sorted_predicted_urls);
// Adds |observer| as the observer for next predicted navigation. When
// |observer| is added via AddObserver, it's immediately notified of the last
// known prediction. Observers must follow relevant privacy guidelines when
// consuming the notifications.
void AddObserver(Observer* observer);
// Removes |observer| as the observer for next predicted navigation.
void RemoveObserver(Observer* observer);
// Notifies |this| that the visibility of web contents tracked by |client| has
// changed or if user starts a new navigation corresponding to |web_contents|.
// Might be called more than once with the same |is_in_foreground| and
// |web_contents| in case user starts a new navigation with same
// |web_contents|.
void OnWebContentsVisibilityChanged(content::WebContents* web_contents,
bool is_in_foreground);
// Notifies |this| that the web contents tracked by |client| has destroyed.
void OnWebContentsDestroyed(content::WebContents* web_contents);
// Overrides the tick clock used by |this| for testing.
void SetTickClockForTesting(const base::TickClock* tick_clock);
// Returns true if the browser app is likely to be in foreground and being
// interacted by the user. This is heuristically computed by observing loading
// and visibility of web contents.
bool IsBrowserAppLikelyInForeground() const;
private:
// List of observers are currently registered to receive notifications for the
// next predicted navigations.
base::ObserverList<Observer>::Unchecked observer_list_;
// Last known prediction.
absl::optional<Prediction> last_prediction_;
// Manages preconnecting to the user's default search engine.
SearchEnginePreconnector search_engine_preconnector_;
std::unordered_set<content::WebContents*> visible_web_contents_;
base::TimeTicks last_web_contents_state_change_time_;
raw_ptr<const base::TickClock> tick_clock_;
};
#endif // CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_