First draft of an App Service search provider
Lots of TODOs, but there's enough implemented so that running "chrome
--enable-features=AppService" will populate the app list search box with
apps' names and icons, and clicking on the icon will launch the app.
BUG=826982
Change-Id: I564bbd9142061e95a91c1a0b63a70980c970d56d
Reviewed-on: https://chromium-review.googlesource.com/c/1362597
Commit-Queue: Nigel Tao <nigeltao@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Dominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#614583}
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
index 569562e..8826a09 100644
--- a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
+++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/ui/app_list/internal_app/internal_app_item.h"
#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
#include "chrome/browser/ui/app_list/search/internal_app_result.h"
+#include "chrome/browser/ui/app_list/search/search_util.h"
#include "chrome/services/app_service/public/mojom/types.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ui/base/l10n/l10n_util.h"
@@ -38,6 +39,10 @@
app->show_in_launcher = internal_app.show_in_launcher
? apps::mojom::OptionalBool::kTrue
: apps::mojom::OptionalBool::kFalse;
+ app->show_in_search = internal_app.searchable
+ ? apps::mojom::OptionalBool::kTrue
+ : apps::mojom::OptionalBool::kFalse;
+
return app;
}
@@ -68,6 +73,16 @@
// TODO(crbug.com/826982): move source of truth for built-in apps from
// ui/app_list to here when the AppService feature is enabled by default.
for (const auto& internal_app : app_list::GetInternalAppList(profile_)) {
+ // TODO(crbug.com/826982): support the "continue reading" app? Or leave
+ // it specifically to the chrome/browser/ui/app_list/search code? If
+ // moved here, it might mean calling sync_sessions::SessionSyncService's
+ // SubscribeToForeignSessionsChanged. See also app_search_provider.cc's
+ // InternalDataSource.
+ if (internal_app.internal_app_name ==
+ app_list::InternalAppName::kContinueReading) {
+ continue;
+ }
+
apps::mojom::AppPtr app = Convert(internal_app);
if (!app.is_null()) {
apps.push_back(std::move(app));
@@ -108,17 +123,17 @@
switch (launch_source) {
case apps::mojom::LaunchSource::kUnknown:
break;
- case apps::mojom::LaunchSource::kFromAppList:
+ case apps::mojom::LaunchSource::kFromAppListGrid:
InternalAppItem::RecordActiveHistogram(app_id);
break;
- case apps::mojom::LaunchSource::kFromAppListSearch:
+ case apps::mojom::LaunchSource::kFromAppListRecommendation:
+ app_list::InternalAppResult::RecordOpenHistogram(app_id);
+ break;
+ case apps::mojom::LaunchSource::kFromAppListQueryResult:
+ app_list::RecordHistogram(app_list::APP_SEARCH_RESULT);
app_list::InternalAppResult::RecordOpenHistogram(app_id);
break;
}
- // TODO(crbug.com/826982): we should also update a UMA histogram when an app
- // result is *shown* in the app list search box, not just *launched*.
- //
- // See //chrome/browser/ui/app_list/search/internal_app_result.cc.
app_list::OpenInternalApp(app_id, profile_, event_flags);
}
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index 9e5cc9f..b94eebe 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/extension_app_utils.h"
+#include "chrome/browser/ui/app_list/search/search_util.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
#include "chrome/common/extensions/extension_metrics.h"
#include "chrome/services/app_service/public/mojom/types.mojom.h"
@@ -43,9 +44,10 @@
switch (launch_source) {
case apps::mojom::LaunchSource::kUnknown:
return ash::LAUNCH_FROM_UNKNOWN;
- case apps::mojom::LaunchSource::kFromAppList:
+ case apps::mojom::LaunchSource::kFromAppListGrid:
return ash::LAUNCH_FROM_APP_LIST;
- case apps::mojom::LaunchSource::kFromAppListSearch:
+ case apps::mojom::LaunchSource::kFromAppListRecommendation:
+ case apps::mojom::LaunchSource::kFromAppListQueryResult:
return ash::LAUNCH_FROM_APP_LIST_SEARCH;
}
}
@@ -125,10 +127,13 @@
switch (launch_source) {
case apps::mojom::LaunchSource::kUnknown:
break;
- case apps::mojom::LaunchSource::kFromAppList:
+ case apps::mojom::LaunchSource::kFromAppListGrid:
extensions::RecordAppListMainLaunch(extension);
break;
- case apps::mojom::LaunchSource::kFromAppListSearch:
+ case apps::mojom::LaunchSource::kFromAppListRecommendation:
+ break;
+ case apps::mojom::LaunchSource::kFromAppListQueryResult:
+ app_list::RecordHistogram(app_list::APP_SEARCH_RESULT);
extensions::RecordAppListSearchLaunch(extension);
break;
}
@@ -152,9 +157,12 @@
app->icon_key->s_key = extension->id();
app->icon_key->u_key = next_u_key_++;
- app->show_in_launcher = app_list::ShouldShowInLauncher(extension, profile_)
- ? apps::mojom::OptionalBool::kTrue
- : apps::mojom::OptionalBool::kFalse;
+ auto show = app_list::ShouldShowInLauncher(extension, profile_)
+ ? apps::mojom::OptionalBool::kTrue
+ : apps::mojom::OptionalBool::kFalse;
+ app->show_in_launcher = show;
+ app->show_in_search = show;
+
return app;
}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 04412c96..d3582a7 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3232,6 +3232,8 @@
"app_list/page_break_app_item.h",
"app_list/page_break_constants.cc",
"app_list/page_break_constants.h",
+ "app_list/search/app_service_app_result.cc",
+ "app_list/search/app_service_app_result.h",
"app_list/search/arc_app_result.cc",
"app_list/search/arc_app_result.h",
"app_list/search/crostini_app_result.cc",
diff --git a/chrome/browser/ui/app_list/app_service_app_item.cc b/chrome/browser/ui/app_list/app_service_app_item.cc
index 407cb652..e8c5a43 100644
--- a/chrome/browser/ui/app_list/app_service_app_item.cc
+++ b/chrome/browser/ui/app_list/app_service_app_item.cc
@@ -47,7 +47,8 @@
void AppServiceAppItem::Activate(int event_flags) {
apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile());
if (proxy) {
- proxy->Launch(id(), event_flags, apps::mojom::LaunchSource::kFromAppList,
+ proxy->Launch(id(), event_flags,
+ apps::mojom::LaunchSource::kFromAppListGrid,
GetController()->GetAppListDisplayId());
}
}
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index 073d435..6e38eb4 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -26,6 +26,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/clock.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
@@ -44,11 +45,13 @@
#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
#include "chrome/browser/ui/app_list/extension_app_utils.h"
#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ui/app_list/search/app_service_app_result.h"
#include "chrome/browser/ui/app_list/search/arc_app_result.h"
#include "chrome/browser/ui/app_list/search/crostini_app_result.h"
#include "chrome/browser/ui/app_list/search/extension_app_result.h"
#include "chrome/browser/ui/app_list/search/internal_app_result.h"
#include "chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/sync/base/model_type.h"
@@ -247,6 +250,57 @@
namespace {
+class AppServiceDataSource : public AppSearchProvider::DataSource {
+ public:
+ AppServiceDataSource(Profile* profile, AppSearchProvider* owner)
+ : AppSearchProvider::DataSource(profile, owner) {
+ // TODO(crbug.com/826982): observe the cache for apps being installed and
+ // uninstalled, and in the callback, call RefreshAppsAndUpdateResultsXxx().
+ }
+
+ ~AppServiceDataSource() override = default;
+
+ // AppSearchProvider::DataSource overrides:
+ void AddApps(AppSearchProvider::Apps* apps_vector) override {
+ apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile());
+ if (!proxy) {
+ return;
+ }
+ proxy->Cache().ForEachApp(
+ [this, apps_vector](const apps::AppUpdate& update) {
+ if (update.ShowInSearch() != apps::mojom::OptionalBool::kTrue) {
+ return;
+ }
+
+ // TODO(crbug.com/826982): add the "can load in incognito" concept to
+ // the App Service and use it here, similar to ExtensionDataSource.
+
+ apps_vector->emplace_back(std::make_unique<AppSearchProvider::App>(
+ this, update.AppId(),
+ // TODO(crbug.com/826982): add the "short name" concept to the App
+ // Service, and use it here.
+ update.Name(),
+ // TODO(crbug.com/826982): add the "last launch time" and "install
+ // time" concepts to the App Service, and use them here.
+ base::Time(), base::Time(),
+ // TODO(crbug.com/826982): add the "installed internally" concept
+ // to the App Service, and use it here.
+ true));
+ });
+ }
+
+ std::unique_ptr<AppResult> CreateResult(
+ const std::string& app_id,
+ AppListControllerDelegate* list_controller,
+ bool is_recommended) override {
+ return std::make_unique<AppServiceAppResult>(
+ profile(), app_id, list_controller, is_recommended);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AppServiceDataSource);
+};
+
class ExtensionDataSource : public AppSearchProvider::DataSource,
public extensions::ExtensionRegistryObserver {
public:
@@ -392,8 +446,11 @@
class InternalDataSource : public AppSearchProvider::DataSource {
public:
- InternalDataSource(Profile* profile, AppSearchProvider* owner)
- : AppSearchProvider::DataSource(profile, owner) {
+ InternalDataSource(Profile* profile,
+ AppSearchProvider* owner,
+ bool just_continue_reading)
+ : AppSearchProvider::DataSource(profile, owner),
+ just_continue_reading_(just_continue_reading) {
sync_sessions::SessionSyncService* service =
SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
if (!service)
@@ -420,6 +477,8 @@
if (!service || !service->GetOpenTabsUIDelegate()) {
continue;
}
+ } else if (just_continue_reading_) {
+ continue;
}
apps->emplace_back(std::make_unique<AppSearchProvider::App>(
@@ -445,6 +504,15 @@
}
private:
+ // Whether InternalDataSource provides just the kInternalAppIdContinueReading
+ // app. If true, other internal apps are provided by AppServiceDataSource.
+ //
+ // TODO(crbug.com/826982): move the "foreign session updated subscription"
+ // into the App Service? Or if, in terms of UI, "continue reading" is exposed
+ // only in the app list search UI, it might make more sense to leave it in
+ // this code. See also built_in_chromeos_apps.cc.
+ bool just_continue_reading_;
+
std::unique_ptr<base::CallbackList<void()>::Subscription>
foreign_session_updated_subscription_;
@@ -535,16 +603,25 @@
chromeos::ProfileHelper::IsEphemeralUserProfile(profile))),
refresh_apps_factory_(this),
update_results_factory_(this) {
- data_sources_.emplace_back(
- std::make_unique<ExtensionDataSource>(profile, this));
- if (arc::IsArcAllowedForProfile(profile))
- data_sources_.emplace_back(std::make_unique<ArcDataSource>(profile, this));
- if (crostini::IsCrostiniUIAllowedForProfile(profile)) {
+ bool app_service_enabled =
+ base::FeatureList::IsEnabled(features::kAppService);
+ if (app_service_enabled) {
data_sources_.emplace_back(
- std::make_unique<CrostiniDataSource>(profile, this));
+ std::make_unique<AppServiceDataSource>(profile, this));
+ } else {
+ data_sources_.emplace_back(
+ std::make_unique<ExtensionDataSource>(profile, this));
+ if (arc::IsArcAllowedForProfile(profile)) {
+ data_sources_.emplace_back(
+ std::make_unique<ArcDataSource>(profile, this));
+ }
+ if (crostini::IsCrostiniUIAllowedForProfile(profile)) {
+ data_sources_.emplace_back(
+ std::make_unique<CrostiniDataSource>(profile, this));
+ }
}
data_sources_.emplace_back(
- std::make_unique<InternalDataSource>(profile, this));
+ std::make_unique<InternalDataSource>(profile, this, app_service_enabled));
}
AppSearchProvider::~AppSearchProvider() {}
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
new file mode 100644
index 0000000..b0a7001
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -0,0 +1,98 @@
+// 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/app_service_app_result.h"
+
+#include "ash/public/cpp/app_list/app_list_config.h"
+#include "ash/public/cpp/app_list/app_list_types.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/ui/app_list/app_list_client_impl.h"
+#include "chrome/browser/ui/app_list/search/internal_app_result.h"
+#include "extensions/common/extension.h"
+
+namespace app_list {
+
+AppServiceAppResult::AppServiceAppResult(Profile* profile,
+ const std::string& app_id,
+ AppListControllerDelegate* controller,
+ bool is_recommendation)
+ : AppResult(profile, app_id, controller, is_recommendation),
+ weak_ptr_factory_(this) {
+ auto app_type = apps::mojom::AppType::kUnknown;
+ apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile);
+
+ if (proxy) {
+ app_type = proxy->Cache().GetAppType(app_id);
+
+ proxy->LoadIcon(
+ app_id, apps::mojom::IconCompression::kUncompressed,
+ AppListConfig::instance().GetPreferredIconDimension(display_type()),
+ base::BindOnce(&AppServiceAppResult::OnLoadIcon,
+ weak_ptr_factory_.GetWeakPtr(), false));
+
+ if (display_type() == ash::SearchResultDisplayType::kRecommendation) {
+ proxy->LoadIcon(
+ app_id, apps::mojom::IconCompression::kUncompressed,
+ AppListConfig::instance().suggestion_chip_icon_dimension(),
+ base::BindOnce(&AppServiceAppResult::OnLoadIcon,
+ weak_ptr_factory_.GetWeakPtr(), true));
+ }
+ }
+
+ switch (app_type) {
+ case apps::mojom::AppType::kBuiltIn:
+ set_id(app_id);
+ // TODO(crbug.com/826982): Is this SetResultType call necessary?? Does
+ // anyone care about the kInternalApp vs kInstalledApp distinction?
+ SetResultType(ResultType::kInternalApp);
+ // TODO(crbug.com/826982): Move this from the App Service caller to
+ // callee, closer to where other histograms are updated in
+ // BuiltInChromeOsApps::Launch??
+ InternalAppResult::RecordShowHistogram(app_id);
+ break;
+ case apps::mojom::AppType::kExtension:
+ // TODO(crbug.com/826982): why do we pass the URL and not the app_id??
+ // Can we replace this by the simpler "set_id(app_id)", and therefore
+ // pull that out of the switch?
+ set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id).spec());
+ break;
+ default:
+ set_id(app_id);
+ break;
+ }
+}
+
+AppServiceAppResult::~AppServiceAppResult() = default;
+
+void AppServiceAppResult::Open(int event_flags) {
+ apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile());
+ if (proxy) {
+ auto launch_source =
+ (display_type() == ash::SearchResultDisplayType::kRecommendation)
+ ? apps::mojom::LaunchSource::kFromAppListRecommendation
+ : apps::mojom::LaunchSource::kFromAppListQueryResult;
+
+ proxy->Launch(app_id(), event_flags, launch_source,
+ controller()->GetAppListDisplayId());
+ }
+}
+
+void AppServiceAppResult::ExecuteLaunchCommand(int event_flags) {
+ Open(event_flags);
+}
+
+void AppServiceAppResult::OnLoadIcon(bool chip,
+ apps::mojom::IconValuePtr icon_value) {
+ if (icon_value->icon_compression !=
+ apps::mojom::IconCompression::kUncompressed) {
+ return;
+ }
+ if (chip) {
+ SetChipIcon(icon_value->uncompressed);
+ } else {
+ SetIcon(icon_value->uncompressed);
+ }
+}
+
+} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.h b/chrome/browser/ui/app_list/search/app_service_app_result.h
new file mode 100644
index 0000000..dd99bfd
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.h
@@ -0,0 +1,43 @@
+// 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_APP_SERVICE_APP_RESULT_H_
+#define CHROME_BROWSER_UI_APP_LIST_SEARCH_APP_SERVICE_APP_RESULT_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/app_list/search/app_result.h"
+#include "chrome/services/app_service/public/mojom/types.mojom.h"
+
+class AppListControllerDelegate;
+class Profile;
+
+namespace app_list {
+
+class AppServiceAppResult : public AppResult {
+ public:
+ AppServiceAppResult(Profile* profile,
+ const std::string& app_id,
+ AppListControllerDelegate* controller,
+ bool is_recommendation);
+ ~AppServiceAppResult() override;
+
+ private:
+ // ChromeSearchResult overrides:
+ void Open(int event_flags) override;
+
+ // AppContextMenuDelegate overrides:
+ void ExecuteLaunchCommand(int event_flags) override;
+
+ void OnLoadIcon(bool chip, apps::mojom::IconValuePtr icon_value);
+
+ // TODO(crbug.com/826982): implement context menus.
+
+ base::WeakPtrFactory<AppServiceAppResult> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppServiceAppResult);
+};
+
+} // namespace app_list
+
+#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_APP_SERVICE_APP_RESULT_H_
diff --git a/chrome/services/app_service/public/cpp/app_registry_cache.cc b/chrome/services/app_service/public/cpp/app_registry_cache.cc
index 83053dcd..b1546ea 100644
--- a/chrome/services/app_service/public/cpp/app_registry_cache.cc
+++ b/chrome/services/app_service/public/cpp/app_registry_cache.cc
@@ -77,4 +77,12 @@
}
}
+apps::mojom::AppType AppRegistryCache::GetAppType(const std::string& app_id) {
+ auto iter = states_.find(app_id);
+ if (iter != states_.end()) {
+ return iter->second->app_type;
+ }
+ return apps::mojom::AppType::kUnknown;
+}
+
} // namespace apps
diff --git a/chrome/services/app_service/public/cpp/app_registry_cache.h b/chrome/services/app_service/public/cpp/app_registry_cache.h
index 710cc18..7e1bab8 100644
--- a/chrome/services/app_service/public/cpp/app_registry_cache.h
+++ b/chrome/services/app_service/public/cpp/app_registry_cache.h
@@ -69,6 +69,8 @@
// merges the cached states with the deltas.
void OnApps(std::vector<apps::mojom::AppPtr> deltas);
+ apps::mojom::AppType GetAppType(const std::string& app_id);
+
// Calls f, a void-returning function whose arguments are (const
// apps::AppUpdate&), on each app in the cache. The AppUpdate (a
// state-and-delta) is equivalent to the delta being "all unknown" or "no
diff --git a/chrome/services/app_service/public/cpp/app_update.cc b/chrome/services/app_service/public/cpp/app_update.cc
index db04497..c15b24c 100644
--- a/chrome/services/app_service/public/cpp/app_update.cc
+++ b/chrome/services/app_service/public/cpp/app_update.cc
@@ -27,6 +27,9 @@
if (delta->show_in_launcher != apps::mojom::OptionalBool::kUnknown) {
state->show_in_launcher = delta->show_in_launcher;
}
+ if (delta->show_in_search != apps::mojom::OptionalBool::kUnknown) {
+ state->show_in_search = delta->show_in_search;
+ }
// When adding new fields to the App Mojo type, this function should also be
// updated.
@@ -97,4 +100,15 @@
(delta_->show_in_launcher != state_->show_in_launcher);
}
+apps::mojom::OptionalBool AppUpdate::ShowInSearch() const {
+ return (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown)
+ ? delta_->show_in_search
+ : state_->show_in_search;
+}
+
+bool AppUpdate::ShowInSearchChanged() const {
+ return (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown) &&
+ (delta_->show_in_search != state_->show_in_search);
+}
+
} // namespace apps
diff --git a/chrome/services/app_service/public/cpp/app_update.h b/chrome/services/app_service/public/cpp/app_update.h
index ac875ac..2a7aa0f 100644
--- a/chrome/services/app_service/public/cpp/app_update.h
+++ b/chrome/services/app_service/public/cpp/app_update.h
@@ -58,6 +58,9 @@
apps::mojom::OptionalBool ShowInLauncher() const;
bool ShowInLauncherChanged() const;
+ apps::mojom::OptionalBool ShowInSearch() const;
+ bool ShowInSearchChanged() const;
+
private:
const apps::mojom::AppPtr& state_;
const apps::mojom::AppPtr& delta_;
diff --git a/chrome/services/app_service/public/cpp/app_update_unittest.cc b/chrome/services/app_service/public/cpp/app_update_unittest.cc
index f66929d..26dfdde 100644
--- a/chrome/services/app_service/public/cpp/app_update_unittest.cc
+++ b/chrome/services/app_service/public/cpp/app_update_unittest.cc
@@ -135,4 +135,24 @@
EXPECT_FALSE(u.IconKey().is_null());
EXPECT_EQ(apps::mojom::IconType::kExtension, u.IconKey()->icon_type);
EXPECT_FALSE(u.IconKeyChanged());
+
+ // ShowInSearch tests.
+
+ EXPECT_EQ(apps::mojom::OptionalBool::kUnknown, u.ShowInSearch());
+ EXPECT_FALSE(u.ShowInSearchChanged());
+
+ state->show_in_search = apps::mojom::OptionalBool::kFalse;
+
+ EXPECT_EQ(apps::mojom::OptionalBool::kFalse, u.ShowInSearch());
+ EXPECT_FALSE(u.ShowInSearchChanged());
+
+ delta->show_in_search = apps::mojom::OptionalBool::kTrue;
+
+ EXPECT_EQ(apps::mojom::OptionalBool::kTrue, u.ShowInSearch());
+ EXPECT_TRUE(u.ShowInSearchChanged());
+
+ apps::AppUpdate::Merge(state.get(), delta);
+
+ EXPECT_EQ(apps::mojom::OptionalBool::kTrue, u.ShowInSearch());
+ EXPECT_FALSE(u.ShowInSearchChanged());
}
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom
index 85c2f71..5dfbd67 100644
--- a/chrome/services/app_service/public/mojom/types.mojom
+++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -16,7 +16,11 @@
Readiness readiness;
string? name;
IconKey? icon_key;
+
+ // TODO(nigeltao): be more principled, instead of ad hoc show_in_xxx and
+ // show_in_yyy fields?
OptionalBool show_in_launcher;
+ OptionalBool show_in_search;
// When adding new fields, also update the Merge method and other helpers in
// chrome/services/app_service/public/cpp/app_update.*
@@ -76,6 +80,7 @@
enum LaunchSource {
kUnknown,
- kFromAppList,
- kFromAppListSearch,
+ kFromAppListGrid, // Grid of apps, not the search box.
+ kFromAppListRecommendation, // Query-less recommendations (smaller icons).
+ kFromAppListQueryResult, // Query-dependent results (larger icons).
};