blob: 6150ec14b1898ed73288c323ba93f2028fdda83c [file] [log] [blame]
// Copyright 2025 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_CONTEXTUAL_CUEING_CONTEXTUAL_CUEING_SERVICE_H_
#define CHROME_BROWSER_CONTEXTUAL_CUEING_CONTEXTUAL_CUEING_SERVICE_H_
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/containers/queue.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "chrome/browser/contextual_cueing/contextual_cueing_enums.h"
#include "chrome/browser/contextual_cueing/nudge_cap_tracker.h"
#include "chrome/browser/contextual_cueing/zero_state_suggestions_page_data.h"
#include "chrome/browser/page_content_annotations/page_content_extraction_service.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/origin.h"
class GURL;
class OptimizationGuideKeyedService;
class PrefService;
class TemplateURLService;
namespace content {
class WebContents;
} // namespace content
namespace predictors {
class LoadingPredictor;
} // namespace predictors
namespace tabs {
enum class GlicNudgeActivity;
} // namespace tabs
namespace contextual_cueing {
class ContextualCueingService
: public KeyedService,
page_content_annotations::PageContentExtractionService::Observer {
public:
ContextualCueingService(
page_content_annotations::PageContentExtractionService*
page_content_extraction_service,
OptimizationGuideKeyedService* optimization_guide_keyed_service,
predictors::LoadingPredictor* loading_predictor,
PrefService* pref_service,
TemplateURLService* template_url_service);
~ContextualCueingService() override;
// Reports a page load happened to `url`, and is used to keep track of quiet
// page loads requirement after a cueing UI is shown.
void ReportPageLoad();
// Called when cueing nudge activity happens.
void OnNudgeActivity(content::WebContents* web_contents,
base::TimeTicks document_available_time,
tabs::GlicNudgeActivity activity);
// Should be called when the cueing UI is shown for the tab with `url`.
void CueingNudgeShown(const GURL& url);
// Should be called when the cueing UI is dismissed by the user.
void CueingNudgeDismissed();
// Should be called when the nudge is clicked on by the user.
void CueingNudgeClicked();
// Returns if a nudge should be shown and is not blocked by feature
// engagement constraints for navigation to `url`, and if not, why.
NudgeDecision CanShowNudge(const GURL& url);
base::WeakPtr<ContextualCueingService> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
// Informs `this` to prepare fetching for zero state suggestions for GLIC.
// Note that this *will not* actually do the fetch and it is intended for the
// caller to call `GetContextualGlicZeroStateSuggestions` to actually fetch
// the suggestions.
void PrepareToFetchContextualGlicZeroStateSuggestions(
content::WebContents* web_contents);
// Returns zero state suggestions for GLIC. Virtual for testing.
virtual void GetContextualGlicZeroStateSuggestions(
content::WebContents* web_contents,
bool is_fre,
GlicSuggestionsCallback callback);
private:
// page_content_annotations::PageContentExtractionService::Observer:
void OnPageContentExtracted(
content::Page& page,
const optimization_guide::proto::AnnotatedPageContent& page_content)
override;
// Called when suggestions are received. Cleans up after suggestions
// generation.
void OnSuggestionsReceived(
base::TimeTicks fetch_begin_time,
GlicSuggestionsCallback callback,
std::optional<std::vector<std::string>> suggestions);
// Returns true if nudge should not be shown due to the backoff rule.
bool IsNudgeBlockedByBackoffRule() const;
// Returns true if the given url is of a page type eligible for contextual
// suggestions.
bool IsPageTypeEligibleForContextualSuggestions(GURL url) const;
// Tracker to limit the number of nudges shown over a certain duration.
NudgeCapTracker recent_nudge_tracker_;
// Number of times the cueing nudge has been dismissed (i.e. closed by the
// user). This count resets to 0 if nudge is clicked on by the user.
int dismiss_count_ = 0;
// The end of the backoff period triggered by the last nudge dismissal.
std::optional<base::TimeTicks> dismiss_backoff_end_time_;
// The end of the backoff period triggered by the last shown nudge.
std::optional<base::TimeTicks> shown_backoff_end_time_;
// A counter for how many subsequent page load events will be prevented from
// showing a nudge. This is to limit the frequency at which consecutive page
// loads can trigger nudges.
size_t remaining_quiet_loads_ = 0;
// Maintains the recently visited origins along with their nudge cap tracking.
base::LRUCache<url::Origin, NudgeCapTracker> recent_visited_origins_;
raw_ptr<page_content_annotations::PageContentExtractionService>
page_content_extraction_service_ = nullptr;
raw_ptr<OptimizationGuideKeyedService> optimization_guide_keyed_service_ =
nullptr;
raw_ptr<predictors::LoadingPredictor> loading_predictor_ = nullptr;
raw_ptr<PrefService> pref_service_ = nullptr;
raw_ptr<TemplateURLService> template_url_service_ = nullptr;
// Stores model execution url to save look up time.
GURL mes_url_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ContextualCueingService> weak_ptr_factory_{this};
};
} // namespace contextual_cueing
#endif // CHROME_BROWSER_CONTEXTUAL_CUEING_CONTEXTUAL_CUEING_SERVICE_H_