Clean up the arc reinstall provider.
We don't have plans to enable this feature, and it seems to be failing
in Arc.
This also involves deleting a pref as per
chrome/browser/prefs/README.md, and marking histograms as obsolete.
Bug: 1272887, 1274647
Change-Id: I45d6862e23194433a7576b920f1f41ba37f2c295
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3307860
Reviewed-by: Rob Schonberger <[email protected]>
Reviewed-by: Gabriel Charette <[email protected]>
Reviewed-by: Xiyuan Xia <[email protected]>
Reviewed-by: Nancy Wang <[email protected]>
Reviewed-by: Muhammad Hasan Khan <[email protected]>
Commit-Queue: Rachel Wong <[email protected]>
Cr-Commit-Position: refs/heads/main@{#951309}
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_active_window_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_active_window_throttle_observer_unittest.cc
index 8c8a4f5..e78f44c 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_active_window_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_active_window_throttle_observer_unittest.cc
@@ -7,7 +7,6 @@
#include "ash/constants/app_types.h"
#include "base/bind.h"
#include "base/test/task_environment.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_window_delegate.h"
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 91647ee8..32f9a9b 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -366,7 +366,6 @@
#include "chrome/browser/metrics/chromeos_metrics_provider.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
#include "chrome/browser/ui/ash/shelf/chrome_shelf_prefs.h"
#include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
@@ -689,11 +688,12 @@
// Deprecated 12/2021.
const char kEduCoexistenceSecondaryAccountsInvalidationVersion[] =
"account_manager.edu_coexistence_secondary_accounts_invalidation_version";
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
-#if BUILDFLAG(IS_CHROMEOS_ASH)
// Deprecated 12/2021.
const char kSyncFirstRunCompleted[] = "sync.first_run_completed";
+
+// Deprecated 12/2021.
+const char kArcAppReinstallState[] = "arc_app_reinstall_state";
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Register local state used only for migration (clearing or moving to a new
@@ -900,6 +900,8 @@
kEduCoexistenceSecondaryAccountsInvalidationVersion, std::string());
registry->RegisterBooleanPref(kSyncFirstRunCompleted, false);
+
+ registry->RegisterDictionaryPref(kArcAppReinstallState);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
}
@@ -1330,7 +1332,6 @@
#if BUILDFLAG(IS_CHROMEOS_ASH)
app_list::AppListSyncableService::RegisterProfilePrefs(registry);
- app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry);
apps::AppPlatformMetricsService::RegisterProfilePrefs(registry);
apps::webapk_prefs::RegisterProfilePrefs(registry);
arc::prefs::RegisterProfilePrefs(registry);
@@ -1769,6 +1770,9 @@
// Added 12/2021
profile_prefs->ClearPref(kSyncFirstRunCompleted);
+
+ // Added 12/2021.
+ profile_prefs->ClearPref(kArcAppReinstallState);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Please don't delete the following line. It is used by PRESUBMIT.py.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 4372e29..2276ff0 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1920,10 +1920,6 @@
"app_list/search/app_search_provider.h",
"app_list/search/app_service_app_result.cc",
"app_list/search/app_service_app_result.h",
- "app_list/search/arc/arc_app_reinstall_app_result.cc",
- "app_list/search/arc/arc_app_reinstall_app_result.h",
- "app_list/search/arc/arc_app_reinstall_search_provider.cc",
- "app_list/search/arc/arc_app_reinstall_search_provider.h",
"app_list/search/arc/arc_app_shortcut_search_result.cc",
"app_list/search/arc/arc_app_shortcut_search_result.h",
"app_list/search/arc/arc_app_shortcuts_search_provider.cc",
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
deleted file mode 100644
index 2ca76d1..0000000
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2018 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.
-
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h"
-
-#include <utility>
-
-#include "ash/public/cpp/app_list/app_list_config.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
-#include "chrome/browser/apps/app_service/app_service_proxy.h"
-#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "chromeos/ui/vector_icons/vector_icons.h"
-#include "components/vector_icons/vector_icons.h"
-#include "ui/base/models/image_model.h"
-#include "ui/color/color_id.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/paint_vector_icon.h"
-
-namespace app_list {
-
-namespace {
-constexpr char kPlayStoreAppUrlPrefix[] =
- "https://play.google.com/store/apps/details?id=";
-
-// We choose a default app reinstallation relevance; This ranks app reinstall
-// app result as a top result typically.
-constexpr float kAppReinstallRelevance = 0.7;
-
-// Apply background and mask to make the icon similar to the icon of
-// ArcPlaystoreSearchResult.
-gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image) {
- return gfx::ImageSkiaOperations::CreateResizedImage(
- apps::ApplyBackgroundAndMask(image),
- skia::ImageOperations::RESIZE_LANCZOS3,
- gfx::Size(
- ash::SharedAppListConfig::instance().search_tile_icon_dimension(),
- ash::SharedAppListConfig::instance().search_tile_icon_dimension()));
-}
-} // namespace
-
-ArcAppReinstallAppResult::ArcAppReinstallAppResult(
- const arc::mojom::AppReinstallCandidatePtr& mojom_data,
- const gfx::ImageSkia& app_icon,
- Observer* observer)
- : observer_(observer), package_name_(mojom_data->package_name) {
- DCHECK(observer_);
- set_id(kPlayStoreAppUrlPrefix + mojom_data->package_name);
- SetCategory(Category::kPlayStore);
- SetResultType(ash::AppListSearchResultType::kPlayStoreReinstallApp);
- SetTitle(base::UTF8ToUTF16(mojom_data->title));
- SetDisplayType(ash::SearchResultDisplayType::kTile);
- SetMetricsType(ash::PLAY_STORE_REINSTALL_APP);
- SetDisplayIndex(ash::SearchResultDisplayIndex::kSixthIndex);
- SetIsRecommendation(true);
- set_relevance(kAppReinstallRelevance);
- SetNotifyVisibilityChange(true);
- const gfx::ImageSkia masked_app_icon(ApplyBackgroundAndMask(app_icon));
- SetIcon(IconInfo(masked_app_icon));
- SetChipIcon(masked_app_icon);
- SetBadgeIcon(ui::ImageModel::FromVectorIcon(
- vector_icons::kCloudDownloadIcon, ui::kColorIcon,
- ash::SharedAppListConfig::instance().search_tile_badge_icon_dimension()));
- SetUseBadgeIconBackground(true);
- SetNotifyVisibilityChange(true);
-
- if (mojom_data->star_rating != 0.0f) {
- SetRating(mojom_data->star_rating);
- }
-}
-
-ArcAppReinstallAppResult::~ArcAppReinstallAppResult() = default;
-
-void ArcAppReinstallAppResult::Open(int /*event_flags*/) {
- RecordAction(base::UserMetricsAction("ArcAppReinstall_Clicked"));
-
- DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
- ProfileManager::GetPrimaryUserProfile()));
- apps::AppServiceProxyFactory::GetForProfile(
- ProfileManager::GetPrimaryUserProfile())
- ->LaunchAppWithUrl(arc::kPlayStoreAppId, ui::EF_NONE, GURL(id()),
- apps::mojom::LaunchSource::kFromChromeInternal);
-
- observer_->OnOpened(package_name_);
-}
-
-void ArcAppReinstallAppResult::OnVisibilityChanged(bool visibility) {
- ChromeSearchResult::OnVisibilityChanged(visibility);
- observer_->OnVisibilityChanged(package_name_, visibility);
-}
-
-} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h
deleted file mode 100644
index f134fe1c..0000000
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2018 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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_APP_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_APP_RESULT_H_
-
-#include <string>
-
-#include "ash/components/arc/mojom/app.mojom.h"
-#include "ash/public/cpp/app_list/app_list_metrics.h"
-#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace app_list {
-
-// A ChromeSearchResult that shows an App Reinstall candidate result. These are
-// Arc++ apps that can be installed on this device. Opens the app in the play
-// store when Open is called.
-class ArcAppReinstallAppResult : public ChromeSearchResult {
- public:
- class Observer {
- public:
- virtual void OnOpened(const std::string& package_name) = 0;
- virtual void OnVisibilityChanged(const std::string& package_name,
- bool visibility) = 0;
-
- protected:
- virtual ~Observer() = default;
- };
-
- ArcAppReinstallAppResult(
- const arc::mojom::AppReinstallCandidatePtr& mojom_data,
- const gfx::ImageSkia& skia_icon,
- ArcAppReinstallAppResult::Observer* observer);
-
- ArcAppReinstallAppResult(const ArcAppReinstallAppResult&) = delete;
- ArcAppReinstallAppResult& operator=(const ArcAppReinstallAppResult&) = delete;
-
- ~ArcAppReinstallAppResult() override;
-
- // ChromeSearchResult:
- void Open(int event_flags) override;
- void OnVisibilityChanged(bool visibility) override;
-
- private:
- // Observer passed in constructor. not owned.
- Observer* const observer_;
- const std::string package_name_;
-};
-
-} // namespace app_list
-
-#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_APP_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
deleted file mode 100644
index b21092f..0000000
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
+++ /dev/null
@@ -1,706 +0,0 @@
-// Copyright 2018 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.
-
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
-
-#include <algorithm>
-#include <unordered_set>
-#include <utility>
-
-#include "ash/components/arc/session/arc_bridge_service.h"
-#include "ash/components/arc/session/arc_service_manager.h"
-#include "ash/constants/ash_features.h"
-#include "ash/constants/ash_pref_names.h"
-#include "ash/public/cpp/app_list/app_list_config.h"
-#include "ash/public/cpp/app_list/app_list_features.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h"
-#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/url_icon_source.h"
-#include "chrome/common/pref_names.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "extensions/grit/extensions_browser_resources.h"
-
-namespace {
-// Seconds in between refreshes;
-constexpr base::TimeDelta kRefresh = base::Minutes(30);
-
-constexpr char kAppListLatency[] = "Apps.AppListRecommendedResponse.Latency";
-constexpr char kAppListCounts[] = "Apps.AppListRecommendedResponse.Count";
-constexpr char kAppListImpressionsBeforeOpen[] =
- "Apps.AppListRecommendedImpResultCountAfterOpen";
-
-// If uninstalled in this time, do not recommend.
-constexpr base::FeatureParam<int> kUninstallGrace(
- &app_list_features::kEnableAppReinstallZeroState,
- "uninstall_time_hours",
- 24 * 90);
-
-// If install start triggered within this many days, do not recommend.
-constexpr base::FeatureParam<int> kInstallStartGrace(
- &app_list_features::kEnableAppReinstallZeroState,
- "install_start_hours",
- 24);
-
-// If install impression older than this age, reset impressions.
-constexpr base::FeatureParam<int> kResetImpressionGrace(
- &app_list_features::kEnableAppReinstallZeroState,
- "reset_impression_hours",
- 30 * 24);
-
-// Count an impression as new if it's more than this much away from the
-// previous.
-constexpr base::FeatureParam<int> kNewImpressionTime(
- &app_list_features::kEnableAppReinstallZeroState,
- "new_impression_seconds",
- 30);
-
-// Maximum number of impressions to show an item.
-constexpr base::FeatureParam<int> kImpressionLimit(
- &app_list_features::kEnableAppReinstallZeroState,
- "impression_count_limit",
- 5);
-
-// If a user has meaningfully interacted with this feature within this grace
-// period, do not show anything. If set to 0, ignored.
-constexpr base::FeatureParam<int> kInteractionGrace(
- &app_list_features::kEnableAppReinstallZeroState,
- "interaction_grace_hours",
- 0);
-
-// TODO(thanhdng): This is used to guard the new http endpoint before it's
-// launched. Remove this when it happens.
-constexpr bool kUseHttpEndpoint = false;
-
-void SetStateInt64(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- const int64_t value) {
- const std::string int64_str = base::NumberToString(value);
- DictionaryPrefUpdate update(
- profile->GetPrefs(), app_list::ArcAppReinstallSearchProvider::kAppState);
- base::DictionaryValue* const dictionary = update.Get();
- base::Value* package_item =
- dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
- if (!package_item) {
- package_item = dictionary->SetKey(
- package_name, base::Value(base::Value::Type::DICTIONARY));
- }
-
- package_item->SetKey(key, base::Value(int64_str));
-}
-
-void UpdateStateRemoveKey(Profile* profile,
- const std::string& package_name,
- const std::string& key) {
- DictionaryPrefUpdate update(
- profile->GetPrefs(), app_list::ArcAppReinstallSearchProvider::kAppState);
- base::DictionaryValue* const dictionary = update.Get();
- base::Value* package_item =
- dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
- if (!package_item) {
- return;
- }
- package_item->RemoveKey(key);
-}
-
-void UpdateStateTime(Profile* profile,
- const std::string& package_name,
- const std::string& key) {
- const int64_t timestamp =
- base::Time::Now().ToDeltaSinceWindowsEpoch().InMilliseconds();
- SetStateInt64(profile, package_name, key, timestamp);
-}
-
-bool GetStateInt64(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- int64_t* value) {
- const base::DictionaryValue* dictionary = profile->GetPrefs()->GetDictionary(
- app_list::ArcAppReinstallSearchProvider::kAppState);
- if (!dictionary)
- return false;
- const base::Value* package_item =
- dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
- if (!package_item)
- return false;
- const std::string* value_str = package_item->FindStringKey(key);
- if (!value_str)
- return false;
-
- if (!base::StringToInt64(*value_str, value)) {
- LOG(ERROR) << "Failed conversion " << *value_str;
- return false;
- }
-
- return true;
-}
-
-bool GetStateTime(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- base::TimeDelta* time_delta) {
- int64_t value;
- if (!GetStateInt64(profile, package_name, key, &value))
- return false;
-
- *time_delta = base::Milliseconds(value);
- return true;
-}
-
-bool GetKnownPackageNames(Profile* profile,
- std::unordered_set<std::string>* package_names) {
- const base::DictionaryValue* dictionary = profile->GetPrefs()->GetDictionary(
- app_list::ArcAppReinstallSearchProvider::kAppState);
- for (const auto it : dictionary->DictItems()) {
- if (it.second.is_dict()) {
- package_names->insert(it.first);
- }
- }
- return true;
-}
-
-void RecordUmaResponseParseResult(arc::mojom::AppReinstallState result) {
- UMA_HISTOGRAM_ENUMERATION("Apps.AppListRecommendedResponse", result);
-}
-
-// Limits icon size to be downloaded with FIFE. The input |icon_dimension| is in
-// dip and the FIFE requires pixel value. Thus, we need to multiply
-// |icon_dimension| with the maximum device scale factor to avoid potential
-// issues.
-std::string LimitIconSizeWithFife(const std::string& icon_url,
- int icon_dimension) {
- DCHECK_GT(icon_dimension, 0);
- // Maximum device scale factor (DSF).
- static const int kMaxDeviceScaleFactor = 3;
- // We append a suffix to icon url
- return base::StrCat(
- {icon_url, "=s",
- base::NumberToString(icon_dimension * kMaxDeviceScaleFactor)});
-}
-
-} // namespace
-
-namespace app_list {
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kInstallTime[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kAppState[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kImpressionCount[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kImpressionTime[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kUninstallTime[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kOpenTime[];
-
-// static
-constexpr char ArcAppReinstallSearchProvider::kInstallStartTime[];
-
-ArcAppReinstallSearchProvider::ArcAppReinstallSearchProvider(
- Profile* profile,
- unsigned int max_result_count)
- : profile_(profile),
- max_result_count_(max_result_count),
- icon_dimension_(
- ash::SharedAppListConfig::instance().GetPreferredIconDimension(
- ash::SearchResultDisplayType::kTile)),
- app_fetch_timer_(std::make_unique<base::RepeatingTimer>()) {
- DCHECK(profile_);
- if (kUseHttpEndpoint)
- recommend_apps_fetcher_ = RecommendAppsFetcher::Create(this);
- ArcAppListPrefs::Get(profile_)->AddObserver(this);
- MaybeUpdateFetching();
-}
-
-ArcAppReinstallSearchProvider::~ArcAppReinstallSearchProvider() {
- ArcAppListPrefs::Get(profile_)->RemoveObserver(this);
-}
-
-void ArcAppReinstallSearchProvider::BeginRepeatingFetch() {
- // If already running, do not re-start.
- if (app_fetch_timer_->IsRunning())
- return;
-
- app_fetch_timer_->Start(FROM_HERE, kRefresh, this,
- &ArcAppReinstallSearchProvider::StartFetch);
- StartFetch();
-}
-
-void ArcAppReinstallSearchProvider::StopRepeatingFetch() {
- weak_ptr_factory_.InvalidateWeakPtrs();
- app_fetch_timer_->AbandonAndStop();
- loaded_value_.clear();
- icon_urls_.clear();
- loading_icon_urls_.clear();
- UpdateResults();
-}
-
-ash::AppListSearchResultType ArcAppReinstallSearchProvider::ResultType() {
- return ash::AppListSearchResultType::kPlayStoreReinstallApp;
-}
-
-void ArcAppReinstallSearchProvider::Start(const std::u16string& query) {
- query_is_empty_ = query.empty();
- if (!query_is_empty_) {
- ClearResults();
- return;
- }
-
- // Always check if suggested content is enabled before searching for
- // reinstall recommendations.
- bool should_show_arc_app_reinstall_result = true;
- PrefService* pref_service = profile_->GetPrefs();
- if (pref_service &&
- !pref_service->GetBoolean(chromeos::prefs::kSuggestedContentEnabled))
- should_show_arc_app_reinstall_result = false;
-
- if (!should_show_arc_app_reinstall_result) {
- ClearResults();
- return;
- }
-
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::StartFetch() {
- if (profile_->GetPrefs()->IsManagedPreference(
- prefs::kAppReinstallRecommendationEnabled) &&
- !profile_->GetPrefs()->GetBoolean(
- prefs::kAppReinstallRecommendationEnabled)) {
- // This user profile is managed, and the app reinstall recommendation is
- // switched off. This is updated dynamically, usually, so we need to update
- // the loaded value and return.
- OnGetAppReinstallCandidates(base::Time::UnixEpoch(),
- arc::mojom::AppReinstallState::REQUEST_SUCCESS,
- {});
- return;
- }
-
- if (kUseHttpEndpoint) {
- recommend_apps_fetcher_->StartDownload();
- return;
- }
-
- arc::mojom::AppInstance* app_instance =
- arc::ArcServiceManager::Get()
- ? ARC_GET_INSTANCE_FOR_METHOD(
- arc::ArcServiceManager::Get()->arc_bridge_service()->app(),
- GetAppReinstallCandidates)
- : nullptr;
- if (app_instance == nullptr)
- return;
-
- app_instance->GetAppReinstallCandidates(base::BindOnce(
- &ArcAppReinstallSearchProvider::OnGetAppReinstallCandidates,
- weak_ptr_factory_.GetWeakPtr(), base::Time::Now()));
-}
-
-void ArcAppReinstallSearchProvider::OnGetAppReinstallCandidates(
- base::Time start_time,
- arc::mojom::AppReinstallState state,
- std::vector<arc::mojom::AppReinstallCandidatePtr> results) {
- RecordUmaResponseParseResult(state);
-
- // fake result insertion is indicated by unix epoch start time.
- if (start_time != base::Time::UnixEpoch()) {
- UMA_HISTOGRAM_TIMES(kAppListLatency, base::Time::Now() - start_time);
- UMA_HISTOGRAM_COUNTS_100(kAppListCounts, results.size());
- }
- if (state != arc::mojom::AppReinstallState::REQUEST_SUCCESS) {
- LOG(ERROR) << "Failed to get reinstall candidates: " << state;
- return;
- }
- loaded_value_.clear();
-
- for (const auto& candidate : results) {
- // only keep candidates with icons.
- if (candidate->icon_url != absl::nullopt) {
- loaded_value_.push_back(candidate.Clone());
- }
- }
-
- MaybeyResetOldImpressionCounts();
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::UpdateResults() {
- // We clear results if there are none from the server, or the user has entered
- // a non-zero query.
- if (loaded_value_.empty() || !query_is_empty_) {
- if (loaded_value_.empty())
- icon_urls_.clear();
- ClearResults();
- return;
- }
-
- ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_);
- DCHECK(prefs);
-
- std::vector<std::unique_ptr<ChromeSearchResult>> new_results;
- std::unordered_set<std::string> used_icon_urls;
-
- // Lock over the whole list.
- if (ShouldShowAnything()) {
- for (size_t i = 0, processed = 0;
- i < loaded_value_.size() && processed < max_result_count_; ++i) {
- // Any packages that are installing or installed and not in sync with the
- // server are removed with IsUnknownPackage.
- if (!prefs->IsUnknownPackage(loaded_value_[i]->package_name))
- continue;
- // Should we filter this ?
- if (!ShouldShowPackage(loaded_value_[i]->package_name)) {
- continue;
- }
- processed++;
-
- // From this point, we believe that this item should be in the result
- // list. We try to find this icon, and if it is not available, we load it.
- const std::string& icon_url = loaded_value_[i]->icon_url.value();
- // All the icons we are showing.
- used_icon_urls.insert(icon_url);
-
- const auto icon_it = icon_urls_.find(icon_url);
- const auto loading_icon_it = loading_icon_urls_.find(icon_url);
- if (icon_it == icon_urls_.end() &&
- loading_icon_it == loading_icon_urls_.end()) {
- // this icon is not loaded, nor is it in the loading set. Add it.
- loading_icon_urls_[icon_url] = gfx::ImageSkia(
- std::make_unique<UrlIconSource>(
- base::BindOnce(&ArcAppReinstallSearchProvider::OnIconLoaded,
- weak_ptr_factory_.GetWeakPtr(), icon_url),
- profile_,
- GURL(LimitIconSizeWithFife(icon_url, icon_dimension_)),
- icon_dimension_, IDR_APP_DEFAULT_ICON),
- gfx::Size(icon_dimension_, icon_dimension_));
- loading_icon_urls_[icon_url].GetRepresentation(1.0f);
- } else if (icon_it != icon_urls_.end()) {
- // Icon is loaded, add it to the results.
- new_results.emplace_back(std::make_unique<ArcAppReinstallAppResult>(
- loaded_value_[i], icon_it->second, this));
- }
- }
- }
-
- // Remove unused icons.
- std::unordered_set<std::string> unused_icon_urls;
- for (const auto& it : icon_urls_) {
- if (used_icon_urls.find(it.first) == used_icon_urls.end()) {
- // This url is used, remove.
- unused_icon_urls.insert(it.first);
- }
- }
-
- for (const std::string& url : unused_icon_urls) {
- icon_urls_.erase(url);
- loading_icon_urls_.erase(url);
- }
-
- // Now we are ready with new_results. do we actually need to replace things on
- // screen?
- if (!ResultsIdentical(results(), new_results)) {
- SwapResults(&new_results);
- }
-}
-
-void ArcAppReinstallSearchProvider::MaybeyResetOldImpressionCounts() {
- const base::TimeDelta now = base::Time::Now().ToDeltaSinceWindowsEpoch();
- // Remove stale impressions from state.
- std::unordered_set<std::string> package_names;
- GetKnownPackageNames(profile_, &package_names);
- for (const std::string& package_name : package_names) {
- base::TimeDelta latest_impression;
- if (!GetStateTime(profile_, package_name, kImpressionTime,
- &latest_impression)) {
- continue;
- }
- if (now - latest_impression > base::Hours(kResetImpressionGrace.Get())) {
- SetStateInt64(profile_, package_name, kImpressionCount, 0);
- UpdateStateRemoveKey(profile_, package_name, kImpressionTime);
- }
- }
-}
-
-void ArcAppReinstallSearchProvider::MaybeUpdateFetching() {
- ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_);
- std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
- prefs->GetApp(arc::kPlayStoreAppId);
- if (app_info && app_info->ready)
- BeginRepeatingFetch();
- else
- StopRepeatingFetch();
-}
-
-void ArcAppReinstallSearchProvider::OnAppRegistered(
- const std::string& app_id,
- const ArcAppListPrefs::AppInfo& app_info) {
- OnAppStatesChanged(app_id, app_info);
-}
-
-void ArcAppReinstallSearchProvider::OnAppStatesChanged(
- const std::string& app_id,
- const ArcAppListPrefs::AppInfo& app_info) {
- if (app_id == arc::kPlayStoreAppId)
- MaybeUpdateFetching();
-}
-
-void ArcAppReinstallSearchProvider::OnAppRemoved(const std::string& app_id) {
- if (app_id == arc::kPlayStoreAppId)
- MaybeUpdateFetching();
-}
-
-void ArcAppReinstallSearchProvider::OnInstallationStarted(
- const std::string& package_name) {
- UpdateStateTime(profile_, package_name, kInstallStartTime);
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::OnInstallationFinished(
- const std::string& package_name,
- bool success) {
- if (success) {
- UpdateStateTime(profile_, package_name, kInstallTime);
- }
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::OnPackageInstalled(
- const arc::mojom::ArcPackageInfo& package_info) {
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::OnPackageRemoved(
- const std::string& package_name,
- bool uninstalled) {
- // If we uninstalled this, update the timestamp before updating results.
- // Otherwise, it's just an app no longer available.
- if (uninstalled) {
- UpdateStateTime(profile_, package_name, kUninstallTime);
- }
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::SetTimerForTesting(
- std::unique_ptr<base::RepeatingTimer> timer) {
- app_fetch_timer_ = std::move(timer);
-}
-
-void ArcAppReinstallSearchProvider::OnOpened(const std::string& package_name) {
- UpdateStateTime(profile_, package_name, kOpenTime);
- int64_t impression_count;
- if (GetStateInt64(profile_, package_name, kImpressionCount,
- &impression_count)) {
- UMA_HISTOGRAM_COUNTS_100(kAppListImpressionsBeforeOpen, impression_count);
- }
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::OnVisibilityChanged(
- const std::string& package_name,
- bool visibility) {
- if (!visibility) {
- // do not update state when showing, update when we hide.
- return;
- }
-
- // If never shown before, or shown more than |kNewImpressionTime| ago,
- // increment the count here.
- const base::TimeDelta now = base::Time::Now().ToDeltaSinceWindowsEpoch();
- base::TimeDelta latest_impression;
- int64_t impression_count;
- if (!GetStateInt64(profile_, package_name, kImpressionCount,
- &impression_count)) {
- impression_count = 0;
- }
- UMA_HISTOGRAM_COUNTS_100("Arc.AppListRecommendedImp.AllImpression", 1);
- // Get impression count and time. If neither is set, set them.
- // If they're set, update if appropriate.
- if (!GetStateTime(profile_, package_name, kImpressionTime,
- &latest_impression) ||
- impression_count == 0 ||
- (now - latest_impression > base::Seconds(kNewImpressionTime.Get()))) {
- UpdateStateTime(profile_, package_name, kImpressionTime);
- SetStateInt64(profile_, package_name, kImpressionCount,
- impression_count + 1);
- UMA_HISTOGRAM_COUNTS_100("Arc.AppListRecommendedImp.CountedImpression", 1);
- UpdateResults();
- }
-}
-
-void ArcAppReinstallSearchProvider::RegisterProfilePrefs(
- PrefRegistrySimple* registry) {
- registry->RegisterDictionaryPref(kAppState);
-}
-
-// For icon load callback, in OnGetAppReinstallCandidates
-void ArcAppReinstallSearchProvider::OnIconLoaded(const std::string& icon_url) {
- auto skia_ptr = loading_icon_urls_.find(icon_url);
- DCHECK(skia_ptr != loading_icon_urls_.end());
- if (skia_ptr == loading_icon_urls_.end()) {
- return;
- }
- const std::vector<gfx::ImageSkiaRep> image_reps =
- skia_ptr->second.image_reps();
- for (const gfx::ImageSkiaRep& rep : image_reps)
- skia_ptr->second.RemoveRepresentation(rep.scale());
- DCHECK_LE(skia_ptr->second.width(), icon_dimension_);
-
- // ImageSkia is now ready to serve, move to the done list and update the
- // screen.
- icon_urls_[icon_url] = skia_ptr->second;
- loading_icon_urls_.erase(icon_url);
- UpdateResults();
-}
-
-bool ArcAppReinstallSearchProvider::ShouldShowPackage(
- const std::string& package_id) const {
- base::TimeDelta timestamp;
- const base::TimeDelta now = base::Time::Now().ToDeltaSinceWindowsEpoch();
- if (GetStateTime(profile_, package_id, kUninstallTime, ×tamp)) {
- const auto delta = now - timestamp;
- if (delta < base::Hours(kUninstallGrace.Get())) {
- // We uninstalled this recently, don't show.
- return false;
- }
- }
- if (GetStateTime(profile_, package_id, kInstallStartTime, ×tamp)) {
- const auto delta = now - timestamp;
- if (delta < base::Hours(kInstallStartGrace.Get())) {
- // We started install on this recently, don't show.
- return false;
- }
- }
- int64_t value;
- if (GetStateInt64(profile_, package_id, kImpressionCount, &value)) {
- if (value > kImpressionLimit.Get()) {
- // Shown too many times, ignore.
- return false;
- }
- }
- return true;
-}
-
-bool ArcAppReinstallSearchProvider::ShouldShowAnything() const {
- if (!kInteractionGrace.Get()) {
- return true;
- }
- const base::TimeDelta grace_period = base::Hours(kInteractionGrace.Get());
- const base::TimeDelta now = base::Time::Now().ToDeltaSinceWindowsEpoch();
- std::unordered_set<std::string> package_names;
- GetKnownPackageNames(profile_, &package_names);
-
- for (const std::string& package_name : package_names) {
- base::TimeDelta install_time;
- if (GetStateTime(profile_, package_name, kInstallTime, &install_time)) {
- if (now - install_time < grace_period) {
- // installed in grace, do not show anything.
- return false;
- }
- }
-
- base::TimeDelta result_open;
- if (GetStateTime(profile_, package_name, kOpenTime, &result_open)) {
- if (now - result_open < grace_period) {
- // Shown in grace, do not show anything.
- return false;
- }
- }
-
- int64_t impression_count;
- if (GetStateInt64(profile_, package_name, kImpressionCount,
- &impression_count)) {
- if (impression_count >= kImpressionLimit.Get()) {
- base::TimeDelta impression_time;
- if (GetStateTime(profile_, package_name, kImpressionTime,
- &impression_time)) {
- if (now - impression_time < grace_period) {
- // We showed a too-many-shown result recently, within grace, don't
- // show anything.
- return false;
- }
- }
- }
- }
- }
- return true;
-}
-
-bool ArcAppReinstallSearchProvider::ResultsIdentical(
- const std::vector<std::unique_ptr<ChromeSearchResult>>& old_results,
- const std::vector<std::unique_ptr<ChromeSearchResult>>& new_results) {
- if (old_results.size() != new_results.size()) {
- return false;
- }
- for (size_t i = 0; i < old_results.size(); ++i) {
- const ChromeSearchResult& old_result = *(old_results[i]);
- const ChromeSearchResult& new_result = *(new_results[i]);
- if (!old_result.icon().icon.BackedBySameObjectAs(new_result.icon().icon)) {
- return false;
- }
- if (old_result.title() != new_result.title()) {
- return false;
- }
- if (old_result.id() != new_result.id()) {
- return false;
- }
- if (old_result.relevance() != new_result.relevance()) {
- return false;
- }
- if (old_result.rating() != new_result.rating()) {
- return false;
- }
- }
- return true;
-}
-
-void ArcAppReinstallSearchProvider::OnLoadSuccess(const base::Value& app_list) {
- // TODO(thanhdng): add a UMA histogram here.
- loaded_value_.clear();
-
- for (const auto& item : app_list.GetList()) {
- base::Value app_info = item.Clone();
- const auto package_name = app_info.ExtractPath("package_name");
- const auto name = app_info.ExtractPath("name");
- const auto icon = app_info.ExtractPath("icon");
- if (icon.has_value() && package_name.has_value() && name.has_value()) {
- if (icon.value().is_string() && package_name.value().is_string() &&
- name.value().is_string()) {
- // TODO(thanhdng): currently rating count and average rating is
- // unavailable. Set them to appropriate value when available.
- loaded_value_.push_back(arc::mojom::AppReinstallCandidate::New(
- package_name.value().GetString(), name.value().GetString(),
- icon.value().GetString(), 0, 0));
- }
- }
- }
-
- MaybeyResetOldImpressionCounts();
- UpdateResults();
-}
-
-void ArcAppReinstallSearchProvider::OnLoadError() {
- // TODO(thanhdng): add a UMA histogram here.
-}
-
-void ArcAppReinstallSearchProvider::OnParseResponseError() {
- // TODO(thanhdng): add a UMA histogram here.
-}
-
-} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h
deleted file mode 100644
index 1209f16..0000000
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2018 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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_SEARCH_PROVIDER_H_
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h"
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h"
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h"
-#include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "ui/gfx/image/image_skia.h"
-
-class PrefRegistrySimple;
-class Profile;
-FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest,
- TestResultsWithSearchChanged);
-FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest,
- TestResultsWithAppsChanged);
-FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest,
- TestResultListComparison);
-FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest, TestShouldShowAnything);
-
-namespace app_list {
-// A search provider that returns app candidates that are reinstallation
-// candidates. The current provider of candidates for this provider is the Fast
-// App Reinstall API. This Provider returns a list of applications, in
-// preference order. Apps are returned as cards for empty query items - and with
-// queries we match with regular expression and then return only matching as app
-// list results.
-//
-// For users who do not have ARC++ enabled, we do not make a call through to the
-// Play Store, but rather populate with empty results.
-class ArcAppReinstallSearchProvider : public SearchProvider,
- public ArcAppListPrefs::Observer,
- public ArcAppReinstallAppResult::Observer,
- public RecommendAppsFetcherDelegate {
- public:
- // Fields for working with pref syncable state.
- // constants used for prefs.
- static constexpr char kInstallTime[] = "install_time";
-
- // Overall dictionary to use for all arc app reinstall states.
- static constexpr char kAppState[] = "arc_app_reinstall_state";
-
- // field name for install start time, as milliseconds since epoch
- static constexpr char kInstallStartTime[] = "install_start_time";
-
- // field name for install opened time, as milliseconds since epoch
- static constexpr char kOpenTime[] = "open_time";
- // field name for uninstalltime, as milliseconds since epoch.
- static constexpr char kUninstallTime[] = "uninstall_time";
-
- // field name for latest impressiontime, as milliseconds since epoch.
- static constexpr char kImpressionTime[] = "impression_time";
- // Number of impressions.
- static constexpr char kImpressionCount[] = "impression_count";
-
- // Constructor receives the Profile in order to
- // instantiate App results. Ownership is not taken.
- //
- // We also give a max result count, so that the provider only instantiates the
- // correct number of results for output.
- ArcAppReinstallSearchProvider(Profile* profile,
- unsigned int max_result_count);
-
- ArcAppReinstallSearchProvider(const ArcAppReinstallSearchProvider&) = delete;
- ArcAppReinstallSearchProvider& operator=(
- const ArcAppReinstallSearchProvider&) = delete;
-
- ~ArcAppReinstallSearchProvider() override;
-
- // SearchProvider:
- void Start(const std::u16string& query) override;
- ash::AppListSearchResultType ResultType() override;
-
- // Used by unit tests. SearchProvider takes ownership of pointer.
- void SetTimerForTesting(std::unique_ptr<base::RepeatingTimer> timer);
-
- // ArcAppReinstallAppResult::Observer:
- void OnOpened(const std::string& package_name) override;
-
- void OnVisibilityChanged(const std::string& package_name,
- bool visibility) override;
-
- // RecommendAppsFetcherDelegate:
- void OnLoadSuccess(const base::Value& app_list) override;
- void OnLoadError() override;
- void OnParseResponseError() override;
-
- static void RegisterProfilePrefs(PrefRegistrySimple* registry);
- private:
- FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
- TestResultsWithSearchChanged);
- FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
- TestResultsWithAppsChanged);
- FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
- TestResultListComparison);
- FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
- TestShouldShowAnything);
-
- // Called to start fetching from our server for this result set. Called when
- // the play store becomes available.
- void StartFetch();
-
- void BeginRepeatingFetch();
- void StopRepeatingFetch();
-
- // Based on any change in results or query, updates the results appropriately.
- void UpdateResults();
-
- // Update the dictionary to reset old impression counts.
- void MaybeyResetOldImpressionCounts();
-
- // If start_time is UnixEpoch, indicates a manual call.
- void OnGetAppReinstallCandidates(
- base::Time start_time,
- arc::mojom::AppReinstallState state,
- std::vector<arc::mojom::AppReinstallCandidatePtr> results);
-
- void MaybeUpdateFetching();
-
- // ArcAppListPrefs::Observer:
- // We listen for app state / registration for the play store, which is our
- // gate to turn on fetching.
- void OnAppRegistered(const std::string& app_id,
- const ArcAppListPrefs::AppInfo& app_info) override;
- void OnAppStatesChanged(const std::string& app_id,
- const ArcAppListPrefs::AppInfo& app_info) override;
- void OnAppRemoved(const std::string& id) override;
- void OnInstallationStarted(const std::string& package_name) override;
- void OnInstallationFinished(const std::string& package_name,
- bool success) override;
- void OnPackageInstalled(
- const arc::mojom::ArcPackageInfo& package_info) override;
- void OnPackageRemoved(const std::string& package_name,
- bool uninstalled) override;
-
- // For icon load callback, in OnGetAppReinstallCandidates
- void OnIconLoaded(const std::string& icon_url);
-
- // Should we show this package?
- bool ShouldShowPackage(const std::string& package_id) const;
- // Should we show anything to the user?
- bool ShouldShowAnything() const;
-
- // Are both lists of chrome search results of the same title in the same
- // order?
- static bool ResultsIdentical(
- const std::vector<std::unique_ptr<ChromeSearchResult>>& old_results,
- const std::vector<std::unique_ptr<ChromeSearchResult>>& new_results);
-
- Profile* const profile_;
- const unsigned int max_result_count_;
- const int icon_dimension_;
-
- // This is the latest loaded set of reinstallation candidates loaded from the
- // Play Store. This is used inside UpdateResults() to choose a subset of at
- // most max_result_count_ results, which are then shown to the user._
- std::vector<arc::mojom::AppReinstallCandidatePtr> loaded_value_;
- bool query_is_empty_ = true;
-
- // Repeating timer to fetch results.
- std::unique_ptr<base::RepeatingTimer> app_fetch_timer_;
-
- // Url to imageskia. This list is for icons that have been fully loaded.
- std::unordered_map<std::string, gfx::ImageSkia> icon_urls_;
-
- std::unique_ptr<RecommendAppsFetcher> recommend_apps_fetcher_;
-
- // url to imageskia of icons being loaded.
- std::unordered_map<std::string, gfx::ImageSkia> loading_icon_urls_;
-
- base::WeakPtrFactory<ArcAppReinstallSearchProvider> weak_ptr_factory_{this};
-};
-
-} // namespace app_list
-
-#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_REINSTALL_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
deleted file mode 100644
index 6286533..0000000
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2018 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.
-
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
-
-#include <map>
-#include <utility>
-
-#include "ash/components/arc/mojom/app.mojom.h"
-#include "ash/components/arc/test/fake_app_instance.h"
-#include "ash/constants/ash_features.h"
-#include "ash/public/cpp/app_list/app_list_features.h"
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/timer/mock_timer.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_service_test_base.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_test.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "extensions/grit/extensions_browser_resources.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image_skia.h"
-
-using testing::ByRef;
-using testing::Eq;
-
-class ArcAppReinstallSearchProviderTest
- : public extensions::ExtensionServiceTestBase {
- protected:
- void SetUp() override {
- extensions::ExtensionServiceTestBase::SetUp();
- auto params = CreateDefaultInitParams();
- // We unset the pref_file so that testing_profile will have a
- // testing_pref_service() available.
- params.pref_file = base::FilePath();
- InitializeExtensionService(params);
- service_->Init();
-
- // Let any async services complete their set-up.
- base::RunLoop().RunUntilIdle();
-
- // Set up custom things for our tests.
- arc_app_test_.SetUp(profile_.get());
- app_provider_ =
- base::WrapUnique(new app_list::ArcAppReinstallSearchProvider(
- profile_.get(), /*max_result_count=*/2));
- std::unique_ptr<base::MockRepeatingTimer> timer =
- std::make_unique<base::MockRepeatingTimer>();
- mock_timer_ = timer.get();
- app_provider_->SetTimerForTesting(std::move(timer));
- app_candidate_ptr_ = arc::mojom::AppReinstallCandidate::New();
- }
-
- void TearDown() override {
- mock_timer_ = nullptr;
- app_provider_.reset(nullptr);
- arc_app_test_.TearDown();
-
- extensions::ExtensionServiceTestBase::TearDown();
- }
-
- arc::FakeAppInstance* app_instance() { return arc_app_test_.app_instance(); }
-
- void SendPlayStoreApp() {
- arc::mojom::AppInfo app;
- app.name = "Play Store";
- app.package_name = arc::kPlayStorePackage;
- app.activity = arc::kPlayStoreActivity;
-
- app_instance()->SendRefreshAppList({app});
- }
-
- arc::mojom::ArcPackageInfoPtr GetPackagePtr(const std::string& package_name) {
- arc::mojom::ArcPackageInfo package;
- package.package_name = package_name;
- package.sync = false;
- return package.Clone();
- }
-
- std::string kAppState = "arc_app_reinstall_state";
- void SetStateInt64(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- const int64_t value) {
- const std::string int64_str = base::NumberToString(value);
- DictionaryPrefUpdate update(profile->GetPrefs(), kAppState);
- base::DictionaryValue* const dictionary = update.Get();
- base::Value* package_item =
- dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
- if (!package_item) {
- package_item = dictionary->SetKey(
- package_name, base::Value(base::Value::Type::DICTIONARY));
- }
-
- package_item->SetKey(key, base::Value(int64_str));
- }
-
- void SetStateTime(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- const base::Time tstamp) {
- const int64_t timestamp =
- tstamp.ToDeltaSinceWindowsEpoch().InMilliseconds();
- SetStateInt64(profile, package_name, key, timestamp);
- }
-
- bool GetStateInt64(Profile* profile,
- const std::string& package_name,
- const std::string& key,
- int64_t* value) {
- const base::DictionaryValue* dictionary =
- profile->GetPrefs()->GetDictionary(kAppState);
- if (!dictionary)
- return false;
- const base::Value* package_item =
- dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
- if (!package_item)
- return false;
- const std::string* value_str = package_item->FindStringKey(key);
- if (!value_str)
- return false;
-
- if (!base::StringToInt64(*value_str, value)) {
- LOG(ERROR) << "Failed conversion " << *value_str;
- return false;
- }
-
- return true;
- }
-
- // Owned by |app_provider_|.
- base::MockRepeatingTimer* mock_timer_;
- ArcAppTest arc_app_test_;
- std::unique_ptr<app_list::ArcAppReinstallSearchProvider> app_provider_;
- arc::mojom::AppReinstallCandidatePtr app_candidate_ptr_;
-};
-
-namespace {
-class TestSearchResult : public ChromeSearchResult {
- public:
- void Open(int event_flags) override {}
- void SetId(const std::string& str) {
- // set_id is protected in chromesearchresult.
- ChromeSearchResult::set_id(str);
- }
-};
-} // namespace
-
-TEST_F(ArcAppReinstallSearchProviderTest, NoResultWithoutPlayStore) {
- EXPECT_EQ(0u, app_provider_->results().size());
- EXPECT_FALSE(mock_timer_->IsRunning());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestTimerOn) {
- EXPECT_EQ(0, app_instance()->get_app_reinstall_callback_count());
- SendPlayStoreApp();
- EXPECT_TRUE(mock_timer_->IsRunning());
- EXPECT_EQ(1, app_instance()->get_app_reinstall_callback_count());
- mock_timer_->Fire();
- EXPECT_EQ(2, app_instance()->get_app_reinstall_callback_count());
- // We expect no results since there are no apps we added to the candidate
- // list.
- EXPECT_EQ(0u, app_provider_->results().size());
-
- // Now, stop!
- arc_app_test_.StopArcInstance();
- EXPECT_FALSE(mock_timer_->IsRunning());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestPolicyManagedUser) {
- testing_pref_service()->SetManagedPref(
- prefs::kAppReinstallRecommendationEnabled,
- std::make_unique<base::Value>(false));
- std::vector<arc::mojom::AppReinstallCandidatePtr> candidates;
- candidates.emplace_back(arc::mojom::AppReinstallCandidate::New(
- "com.package.fakepackage1", "Title of first package",
- "http://icon.com/icon1", 15, 4.7));
- app_instance()->SetAppReinstallCandidates(candidates);
- EXPECT_EQ(0, app_instance()->get_app_reinstall_callback_count());
- SendPlayStoreApp();
- // It's a managed user, default of pref to allow for this feature is false.
- // Expect 0 callback executions.
- EXPECT_EQ(0, app_instance()->get_app_reinstall_callback_count());
-
- // Let's update the pref to true, and see that we end up with a result.
- testing_pref_service()->SetManagedPref(
- prefs::kAppReinstallRecommendationEnabled,
- std::make_unique<base::Value>(true));
- mock_timer_->Fire();
- EXPECT_EQ(1, app_instance()->get_app_reinstall_callback_count());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestResultsWithSearchChanged) {
- std::vector<arc::mojom::AppReinstallCandidatePtr> candidates;
- candidates.emplace_back(arc::mojom::AppReinstallCandidate::New(
- "com.package.fakepackage1", "Title of first package",
- "http://icon.com/icon1", 15, 4.7));
- candidates.emplace_back(arc::mojom::AppReinstallCandidate::New(
- "com.package.fakepackage2", "Title of second package",
- "http://icon.com/icon2", 15, 4.3));
- app_instance()->SetAppReinstallCandidates(candidates);
- EXPECT_EQ(0, app_instance()->get_app_reinstall_callback_count());
- SendPlayStoreApp();
- EXPECT_EQ(1, app_instance()->get_app_reinstall_callback_count());
- // So we should have populated exactly 0 apps, since we expect loading to
- // finish later.
- EXPECT_EQ(0u, app_provider_->results().size());
- EXPECT_EQ(2u, app_provider_->loading_icon_urls_.size());
-
- // Fake the load of 2 icons.
- app_provider_->OnIconLoaded("http://icon.com/icon1");
- EXPECT_EQ(1u, app_provider_->loading_icon_urls_.size());
- app_provider_->OnIconLoaded("http://icon.com/icon2");
- ASSERT_EQ(2u, app_provider_->results().size());
-
- EXPECT_EQ(
- "https://play.google.com/store/apps/details?id=com.package.fakepackage1",
- app_provider_->results()[0]->id());
-
- // Test that we set to 0 results when having a query, or when arc is turned
- // off.
- app_provider_->Start(u"non empty query");
- EXPECT_EQ(0u, app_provider_->results().size());
- // Verify that all icons are still loaded.
- EXPECT_EQ(2u, app_provider_->icon_urls_.size());
- EXPECT_EQ(0u, app_provider_->loading_icon_urls_.size());
- app_provider_->Start(std::u16string());
- EXPECT_EQ(2u, app_provider_->results().size());
-
- app_instance()->SendInstallationStarted("com.package.fakepackage1");
- EXPECT_EQ(1u, app_provider_->results().size());
-
- // We should see that only 1 icon is loaded in our final results.
- EXPECT_EQ(1u, app_provider_->icon_urls_.size());
-
- // When arc is turned off, we should get no results and that we get no
- arc_app_test_.StopArcInstance();
- EXPECT_EQ(0u, app_provider_->results().size());
- // We expect icons to be deleted when arc is stopped.
- EXPECT_EQ(0u, app_provider_->icon_urls_.size());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestResultsWithAppsChanged) {
- std::vector<arc::mojom::AppReinstallCandidatePtr> candidates;
- // We do something unlikely and sneaky here: we give the same icon to two
- // apps. Unlikely, but possible.
- candidates.emplace_back(arc::mojom::AppReinstallCandidate::New(
- "com.package.fakepackage1", "Title of first package",
- "http://icon.com/icon1", 15, 4.7));
- candidates.emplace_back(arc::mojom::AppReinstallCandidate::New(
- "com.package.fakepackage2", "Title of second package",
- "http://icon.com/icon1", 15, 4.3));
- app_instance()->SetAppReinstallCandidates(candidates);
- EXPECT_EQ(0, app_instance()->get_app_reinstall_callback_count());
- SendPlayStoreApp();
- EXPECT_EQ(1, app_instance()->get_app_reinstall_callback_count());
- // So we should have populated exactly 0 apps, since we expect loading to
- // finish later.
- EXPECT_EQ(0u, app_provider_->results().size());
-
- // Fake the load of 1 icon.
- app_provider_->OnIconLoaded("http://icon.com/icon1");
- ASSERT_EQ(2u, app_provider_->results().size());
-
- EXPECT_EQ(
- "https://play.google.com/store/apps/details?id=com.package.fakepackage1",
- app_provider_->results()[0]->id());
-
- app_instance()->SendInstallationStarted("com.package.fakepackage1");
- EXPECT_EQ(1u, app_provider_->results().size());
- app_instance()->InstallPackage(GetPackagePtr("com.package.fakepackage1"));
- app_instance()->SendInstallationFinished("com.package.fakepackage1", true);
- EXPECT_EQ(1u, app_provider_->results().size());
- app_instance()->UninstallPackage("com.package.fakepackage1");
- // We expect the uninstall not to go back to the list.
- EXPECT_EQ(1u, app_provider_->results().size());
-
- // Check for persistence:
-
- app_provider_ = base::WrapUnique(new app_list::ArcAppReinstallSearchProvider(
- profile_.get(), /*max_result_count=*/2));
-
- EXPECT_EQ(0u, app_provider_->results().size());
- app_provider_->OnIconLoaded("http://icon.com/icon1");
- EXPECT_EQ(1u, app_provider_->results().size());
-
- base::HistogramTester histogram_tester;
- // Check that impression counts are read and written appropriately.
- const std::string fake_package2 = "com.package.fakepackage2";
-
- // should update to 1.
- app_provider_->OnVisibilityChanged(fake_package2, true);
-
- int64_t loaded_impression_count = 0;
- EXPECT_TRUE(
- GetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount,
- &loaded_impression_count));
- EXPECT_EQ(1, loaded_impression_count);
- EXPECT_EQ(1, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.AllImpression", 1));
- EXPECT_EQ(1, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.CountedImpression", 1));
-
- // An immediate re-show does nothing, but the "all impression count" is
- // increased.
- app_provider_->OnVisibilityChanged(fake_package2, true);
- EXPECT_EQ(2, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.AllImpression", 1));
- EXPECT_EQ(1, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.CountedImpression", 1));
- loaded_impression_count = 0;
- EXPECT_TRUE(
- GetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount,
- &loaded_impression_count));
- EXPECT_EQ(1, loaded_impression_count);
-
- // But, setting impression time back does.
- for (int i = 0; i < 4; ++i) {
- SetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionTime, 0);
- app_provider_->OnVisibilityChanged(fake_package2, true);
- }
- loaded_impression_count = 0;
- EXPECT_TRUE(
- GetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount,
- &loaded_impression_count));
- EXPECT_EQ(5, loaded_impression_count);
- EXPECT_EQ(6, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.AllImpression", 1));
- EXPECT_EQ(5, histogram_tester.GetBucketCount(
- "Arc.AppListRecommendedImp.CountedImpression", 1));
-
- SetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount, 50);
- app_provider_->UpdateResults();
- EXPECT_EQ(0u, app_provider_->results().size());
- SetStateInt64(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount, 0);
- app_provider_->UpdateResults();
- app_provider_->OnIconLoaded("http://icon.com/icon1");
- EXPECT_EQ(1u, app_provider_->results().size());
-
- // If uninstalled recently, avoid.
- const std::string uninstall_time = "uninstall_time";
- SetStateInt64(profile_.get(), fake_package2, uninstall_time,
- base::Time::Now().ToDeltaSinceWindowsEpoch().InMilliseconds());
- app_provider_->UpdateResults();
- EXPECT_EQ(0u, app_provider_->results().size());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestShouldShowAnything) {
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
- std::map<std::string, std::string> feature_params;
- feature_params["interaction_grace_hours"] = "72";
- feature_params["impression_count_limit"] = "5";
- const std::string fake_package2 = "com.package.fakepackage2";
- const std::string fake_package3 = "com.package.fakepackage3";
- const std::string fake_package4 = "com.package.fakepackage4";
-
- base::test::ScopedFeatureList list;
- list.InitWithFeaturesAndParameters(
- {{app_list_features::kEnableAppReinstallZeroState, feature_params}}, {});
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
- SetStateTime(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kInstallTime,
- base::Time::Now() - base::Seconds(30));
- // Expect this to now say we shouldn't show, since a package was installed
- // well within an install grace.
- EXPECT_FALSE(app_provider_->ShouldShowAnything());
- SetStateTime(profile_.get(), fake_package2,
- app_list::ArcAppReinstallSearchProvider::kInstallTime,
- base::Time::Now() - base::Days(30));
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
-
- // Testing for opens: if an a recommendation is opened within the grace
- // period, we won't show anything. That's 72 hours (per configuration here).
- SetStateTime(profile_.get(), fake_package3,
- app_list::ArcAppReinstallSearchProvider::kOpenTime,
- base::Time::Now() - base::Seconds(30));
- EXPECT_FALSE(app_provider_->ShouldShowAnything());
- SetStateTime(profile_.get(), fake_package3,
- app_list::ArcAppReinstallSearchProvider::kOpenTime,
- base::Time::Now() - base::Days(30));
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
-
- // Testing for impression counts: If we've shown a result more than the
- // feature param "impression_count_limit", and the latest time we've shown it
- // is within the grace period, do not show anything.
- SetStateInt64(profile_.get(), fake_package4,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount, 10);
- // no impression time is set, show.
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
- // shown recently.
- SetStateTime(profile_.get(), fake_package4,
- app_list::ArcAppReinstallSearchProvider::kImpressionTime,
- base::Time::Now() - base::Seconds(30));
- EXPECT_FALSE(app_provider_->ShouldShowAnything());
- // shown long ago.
- SetStateTime(profile_.get(), fake_package4,
- app_list::ArcAppReinstallSearchProvider::kImpressionTime,
- base::Time::Now() - base::Days(30));
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
-
- // Shown recently, but not frequently.
- SetStateInt64(profile_.get(), fake_package4,
- app_list::ArcAppReinstallSearchProvider::kImpressionCount, 3);
- SetStateTime(profile_.get(), fake_package4,
- app_list::ArcAppReinstallSearchProvider::kImpressionTime,
- base::Time::Now() - base::Seconds(30));
- EXPECT_TRUE(app_provider_->ShouldShowAnything());
-}
-
-TEST_F(ArcAppReinstallSearchProviderTest, TestResultListComparison) {
- std::vector<std::unique_ptr<ChromeSearchResult>> a, b;
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- a.emplace_back(new TestSearchResult);
-
- // different sizes.
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- b.emplace_back(new TestSearchResult);
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- // Different Titles.
- a[0]->SetTitle(u"fake_title");
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- b[0]->SetTitle(u"fake_title");
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
-
- // Different ID.
- static_cast<TestSearchResult*>(a[0].get())->SetId("id");
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- static_cast<TestSearchResult*>(b[0].get())->SetId(a[0]->id());
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
-
- // Different relevance
- a[0]->set_relevance(0.7);
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- b[0]->set_relevance(a[0]->relevance());
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
-
- // Different Rating.
- a[0]->SetRating(0.3);
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- b[0]->SetRating(a[0]->rating());
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
-
- // for icon equality.
- gfx::ImageSkia aimg =
- *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_APP_DEFAULT_ICON),
- bimg =
- *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_EXTENSION_DEFAULT_ICON);
- ASSERT_FALSE(aimg.BackedBySameObjectAs(bimg));
- a[0]->SetIcon(ChromeSearchResult::IconInfo(aimg));
- b[0]->SetIcon(ChromeSearchResult::IconInfo(bimg));
- EXPECT_FALSE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
- b[0]->SetIcon(ChromeSearchResult::IconInfo(aimg));
- EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
-}
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc
index cd2ef0b..97f45a0 100644
--- a/chrome/browser/ui/app_list/search/search_controller_factory.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -17,7 +17,6 @@
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/app_search_provider.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
#include "chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h"
#include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h"
#include "chrome/browser/ui/app_list/search/assistant_text_search_provider.h"
@@ -64,7 +63,6 @@
// duplicates of these results for the suggestion chips.
constexpr size_t kMaxZeroStateFileResults = 20;
constexpr size_t kMaxZeroStateDriveResults = 10;
-constexpr size_t kMaxAppReinstallSearchResults = 1;
// TODO(warx): Need UX spec.
constexpr size_t kMaxAppShortcutResults = 4;
@@ -125,16 +123,6 @@
std::make_unique<DriveSearchProvider>(profile));
}
- // reinstallation candidates for Arc++ apps.
- if (app_list_features::IsAppReinstallZeroStateEnabled() &&
- arc::IsArcAllowedForProfile(profile)) {
- size_t recommended_app_group_id =
- controller->AddGroup(kMaxAppReinstallSearchResults);
- controller->AddProvider(recommended_app_group_id,
- std::make_unique<ArcAppReinstallSearchProvider>(
- profile, kMaxAppReinstallSearchResults));
- }
-
if (arc::IsArcAllowedForProfile(profile)) {
size_t app_shortcut_group_id = controller->AddGroup(kMaxAppShortcutResults);
controller->AddProvider(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index f6d19b11..daca786 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6583,7 +6583,6 @@
"../browser/ui/app_list/md_icon_normalizer_unittest.cc",
"../browser/ui/app_list/reorder/app_list_reorder_util_unittest.cc",
"../browser/ui/app_list/search/app_search_provider_unittest.cc",
- "../browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc",
"../browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc",
"../browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc",
"../browser/ui/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc",
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml
index 79b6553..9a44b73 100644
--- a/tools/metrics/histograms/metadata/apps/histograms.xml
+++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -1719,6 +1719,9 @@
<histogram name="Apps.AppListRecommendedImpResultCountAfterOpen" units="shows"
expires_after="2021-11-28">
+ <obsolete>
+ Removed December 2021.
+ </obsolete>
<owner>[email protected]</owner>
<owner>[email protected]</owner>
<owner>[email protected]</owner>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 77a872a..eca0fb1 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -237,6 +237,9 @@
<histogram name="Arc.AppListRecommendedImp.AllImpression" units="count"
expires_after="2022-01-09">
+ <obsolete>
+ Removed December 2021.
+ </obsolete>
<owner>[email protected]</owner>
<owner>[email protected]</owner>
<owner>[email protected]</owner>
@@ -249,6 +252,9 @@
<histogram name="Arc.AppListRecommendedImp.CountedImpression" units="count"
expires_after="2022-01-09">
+ <obsolete>
+ Removed December 2021.
+ </obsolete>
<owner>[email protected]</owner>
<owner>[email protected]</owner>
<owner>[email protected]</owner>