blob: ea3cf9f16b4836dbe7bc49da3e414fe0c97a9460 [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_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_WEB_CONTENTS_OBSERVER_H_
#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_WEB_CONTENTS_OBSERVER_H_
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/optimization_guide/core/hints/insertion_ordered_set.h"
#include "components/optimization_guide/core/hints/optimization_guide_navigation_data.h"
#include "content/public/browser/navigation_handle_user_data.h"
#include "content/public/browser/page_user_data.h"
#include "content/public/browser/web_contents.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 optimization_guide {
class ChromeHintsManager;
class ChromeHintsManagerFetchingTest;
} // namespace optimization_guide
class OptimizationGuideKeyedService;
// Observes navigation events.
class OptimizationGuideWebContentsObserver
: public content::WebContentsObserver,
public content::WebContentsUserData<
OptimizationGuideWebContentsObserver> {
public:
OptimizationGuideWebContentsObserver(
const OptimizationGuideWebContentsObserver&) = delete;
OptimizationGuideWebContentsObserver& operator=(
const OptimizationGuideWebContentsObserver&) = delete;
~OptimizationGuideWebContentsObserver() override;
// Notifies |this| to flush |last_navigation_data| so metrics are recorded.
void FlushLastNavigationData();
// Tell the observer that hints for this URL should be fetched once we reach
// onload in this |web_contents|. Note that |web_contents| must be the
// WebContents being observed by this object.
void AddURLsToBatchFetchBasedOnPrediction(std::vector<GURL> urls,
content::WebContents* web_contents);
private:
friend class content::WebContentsUserData<
OptimizationGuideWebContentsObserver>;
friend class optimization_guide::ChromeHintsManagerFetchingTest;
explicit OptimizationGuideWebContentsObserver(
content::WebContents* web_contents);
// Gets the OptimizationGuideNavigationData associated with the
// |navigation_handle|. If one does not exist already, one will be created for
// it.
OptimizationGuideNavigationData* GetOrCreateOptimizationGuideNavigationData(
content::NavigationHandle* navigation_handle);
// content::WebContentsObserver implementation:
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
void DidRedirectNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void WebContentsDestroyed() override;
void DocumentOnLoadCompletedInPrimaryMainFrame() override;
// Ask |hints_manager| to fetch hints for navigations that were predicted for
// the current page load.
void FetchHintsUsingManager(
optimization_guide::ChromeHintsManager* hints_manager,
base::WeakPtr<content::Page> page);
// Notifies |optimization_guide_keyed_service_| that the navigation has
// finished.
void NotifyNavigationFinish(
std::unique_ptr<OptimizationGuideNavigationData> navigation_data,
const std::vector<GURL>& navigation_redirect_chain);
// Data scoped to a single page. PageData has the same lifetime as the page's
// main document.
class PageData : public content::PageUserData<PageData> {
public:
explicit PageData(content::Page& page);
PageData(const PageData&) = delete;
PageData& operator=(const PageData&) = delete;
~PageData() override;
bool is_sent_batched_hints_request() const {
return sent_batched_hints_request_;
}
void set_sent_batched_hints_request() {
sent_batched_hints_request_ = true;
}
void InsertHintTargetUrls(const std::vector<GURL>& urls);
std::vector<GURL> GetHintsTargetUrls();
void SetNavigationData(
std::unique_ptr<OptimizationGuideNavigationData> navigation_data) {
navigation_data_ = std::move(navigation_data);
}
PAGE_USER_DATA_KEY_DECL();
private:
// List of predicted URLs to fetch hints for once the page reaches onload.
optimization_guide::InsertionOrderedSet<GURL> hints_target_urls_;
// Whether a hints request for predicted URLs has been fired off for this
// page loads. Used to avoid sending more than one predicted URLs hints
// request per page load.
bool sent_batched_hints_request_ = false;
// The navigation data for the completed navigation.
std::unique_ptr<OptimizationGuideNavigationData> navigation_data_;
};
class NavigationHandleData
: public content::NavigationHandleUserData<NavigationHandleData> {
public:
explicit NavigationHandleData(content::NavigationHandle&);
NavigationHandleData(const NavigationHandleData&) = delete;
NavigationHandleData& operator=(const NavigationHandleData&) = delete;
~NavigationHandleData() override;
std::unique_ptr<OptimizationGuideNavigationData>
TakeOptimizationGuideNavigationData() {
return std::move(optimization_guide_navigation_data_);
}
OptimizationGuideNavigationData* GetOptimizationGuideNavigationData() {
return optimization_guide_navigation_data_.get();
}
void SetOptimizationGuideNavigationData(
std::unique_ptr<OptimizationGuideNavigationData> navigation_data) {
optimization_guide_navigation_data_ = std::move(navigation_data);
}
NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
private:
// The data related to a given navigation ID.
std::unique_ptr<OptimizationGuideNavigationData>
optimization_guide_navigation_data_;
};
// Returns the PageData for the specified |page|.
PageData& GetPageData(content::Page& page);
// Initialized in constructor. It may be null if the
// OptimizationGuideKeyedService feature is not enabled.
raw_ptr<OptimizationGuideKeyedService> optimization_guide_keyed_service_ =
nullptr;
base::WeakPtrFactory<OptimizationGuideWebContentsObserver> weak_factory_{
this};
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_WEB_CONTENTS_OBSERVER_H_