// Copyright 2020 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_ASH_FILE_SUGGEST_ITEM_SUGGEST_CACHE_H_
#define CHROME_BROWSER_ASH_FILE_SUGGEST_ITEM_SUGGEST_CACHE_H_
#include "base/callback_list.h"
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
class Profile;
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
} // namespace network
namespace ash {
// Whether or not to override configuration of the cache with an experiment.
BASE_DECLARE_FEATURE(kLauncherItemSuggest);
class ItemSuggestCache {
public:
// Information on a single file suggestion result.
struct Result {
Result(const std::string& id,
const std::string& title,
const std::optional<std::string>& prediction_reason);
Result(const Result& other);
~Result();
std::string id;
std::string title;
std::optional<std::string> prediction_reason;
};
// Information on all file suggestion results returned from an ItemSuggest
// request.
struct Results {
explicit Results(const std::string& suggestion_id);
Results(const Results& other);
~Results();
// |suggestion_id| should be used to link ItemSuggest feedback to a
// particular request.
std::string suggestion_id;
// |results| has the same ordering as the response from ItemSuggest:
// best-to-worst.
std::vector<Result> results;
};
ItemSuggestCache(
const std::string& locale,
Profile* profile,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
virtual ~ItemSuggestCache();
ItemSuggestCache(const ItemSuggestCache&) = delete;
ItemSuggestCache& operator=(const ItemSuggestCache&) = delete;
using OnResultsCallback = base::RepeatingCallback<void()>;
using OnResultsCallbackList = base::RepeatingCallbackList<void()>;
// Registers a callback to be run whenever the results are updated.
base::CallbackListSubscription RegisterCallback(OnResultsCallback callback);
// Returns the results currently in the cache. A null result indicates that
// the cache has not been successfully updated.
std::optional<ItemSuggestCache::Results> GetResults();
// Updates the cache by calling ItemSuggest. Virtual for testing.
virtual void MaybeUpdateCache();
// Updates the cache with a json response.
void UpdateCacheWithJsonForTest(const std::string json_response);
static std::optional<ItemSuggestCache::Results> ConvertJsonForTest(
const base::Value* value);
// Possible outcomes of a call to the ItemSuggest API. These values persist to
// logs. Entries should not be renumbered and numeric values should never be
// reused.
enum class Status {
kOk = 0,
kDisabledByExperiment = 1,
kDisabledByPolicy = 2,
kInvalidServerUrl = 3,
kNoIdentityManager = 4,
kGoogleAuthError = 5,
kNetError = 6,
kResponseTooLarge = 7,
k3xxStatus = 8,
k4xxStatus = 9,
k5xxStatus = 10,
kEmptyResponse = 11,
kNoResultsInResponse = 12,
kJsonParseFailure = 13,
kJsonConversionFailure = 14,
kPostLaunchUpdateIgnored = 15,
kMaxValue = kPostLaunchUpdateIgnored,
};
private:
// Whether or not the ItemSuggestCache is enabled.
static constexpr base::FeatureParam<bool> kEnabled{&kLauncherItemSuggest,
"enabled", true};
// The url of the service that fetches descriptions given image pixels.
static constexpr base::FeatureParam<std::string> kServerUrl{
&kLauncherItemSuggest, "server_url",
"https://appsitemsuggest-pa.googleapis.com/v1/items"};
// Specifies the ItemSuggest backend that should be used to serve our
// requests.
static constexpr base::FeatureParam<std::string> kModelName{
&kLauncherItemSuggest, "model_name", "quick_access"};
// Whether ItemSuggest should be queried more than once per session. Multiple
// queries are issued if either this param is true or the suggested files
// experiment is enabled.
static constexpr base::FeatureParam<bool> kMultipleQueriesPerSession{
&kLauncherItemSuggest, "multiple_queries_per_session", true};
// The minimum time between queries if a short delay is being used.
static constexpr int kShortDelayMinutes = 10;
// The minimum time between queries if a long delay is being used. If not set,
// the short delay value is used as a default instead.
static constexpr base::FeatureParam<int> kLongDelayMinutes{
&kLauncherItemSuggest, "long_delay_minutes", kShortDelayMinutes};
// Returns the body for the itemsuggest request. Affected by
// |kLauncherItemSuggest|.
std::string GetRequestBody();
// Calculates the minimum time required to wait after the previous request.
// Affected by |kLauncherItemSuggest|.
base::TimeDelta GetDelay();
void OnTokenReceived(GoogleServiceAuthError error,
signin::AccessTokenInfo token_info);
void OnSuggestionsReceived(const std::unique_ptr<std::string> json_response);
void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result);
std::unique_ptr<network::SimpleURLLoader> MakeRequestLoader(
const std::string& token);
std::optional<Results> results_;
// Start time for latency metrics.
base::TimeTicks update_start_time_;
// Whether the cache has made at least one request to ItemSuggest this
// session. Used to prevent further updates in some cases.
bool made_request_;
const bool enabled_;
const GURL server_url_;
// Whether we should query item suggest more than once per session.
const bool multiple_queries_per_session_;
const std::string locale_;
// List of callbacks to run when results are updated.
OnResultsCallbackList on_results_callback_list_;
raw_ptr<Profile> profile_;
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<network::SimpleURLLoader> url_loader_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ItemSuggestCache> weak_factory_{this};
};
} // namespace ash
#endif // CHROME_BROWSER_ASH_FILE_SUGGEST_ITEM_SUGGEST_CACHE_H_