0

[game search] Add skeleton of search provider and result

This adds:
- A stub API for cloud gaming results, to be replaced in the near future
- A search provider and result using that API
- Filtering logic to deduplicate between omnibox and game search results

Bug: 1305880
Change-Id: I0f1e3433c5a5f01ae76d9c8063dd768d40cc7c00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3527536
Reviewed-by: Rachel Wong <wrong@chromium.org>
Commit-Queue: Tony Yeoman <tby@chromium.org>
Cr-Commit-Position: refs/heads/main@{#984705}
This commit is contained in:
tby
2022-03-24 06:50:58 +00:00
committed by Chromium LUCI CQ
parent 1569cf3e13
commit e8dad277a3
15 changed files with 679 additions and 5 deletions

@ -4649,6 +4649,9 @@ New install
<message name="IDS_APP_LIST_OPEN_TAB_HINT" desc="Shown alongside launcher search results which will take the user to an open tab when clicked.">
Go to this tab
</message>
<message name="IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX" desc="Shown next to a video game search result, begins a list of cloud gaming platforms the game is playable on.">
on
</message>
<message name="IDS_APP_LIST_START_ASSISTANT" desc="Tooltip for the button that starts Google Assistant from the search box in the app list.">
Google Assistant
</message>

@ -0,0 +1 @@
2098bdec94d7cc66c749c8caa9127e2ffd1115f2

@ -2024,6 +2024,12 @@ static_library("ui") {
"app_list/search/files/zero_state_drive_provider.h",
"app_list/search/files/zero_state_file_provider.cc",
"app_list/search/files/zero_state_file_provider.h",
"app_list/search/games/game_provider.cc",
"app_list/search/games/game_provider.h",
"app_list/search/games/game_result.cc",
"app_list/search/games/game_result.h",
"app_list/search/games/stub_api.cc",
"app_list/search/games/stub_api.h",
"app_list/search/help_app_provider.cc",
"app_list/search/help_app_provider.h",
"app_list/search/keyboard_shortcut_data.cc",

@ -70,8 +70,7 @@ class FileResult : public ChromeSearchResult {
}
private:
// Callback for the result of MaybeRequestThumbnail's call to the
// ThumbnailLoader.
// Callback for the result of RequestThumbnail's call to the ThumbnailLoader.
void OnThumbnailLoaded(const SkBitmap* bitmap, base::File::Error error);
// Callback for the result of SetDetailsToJustificationString to

@ -0,0 +1,124 @@
// Copyright 2022 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/games/game_provider.h"
#include <utility>
#include "base/strings/strcat.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ui/app_list/search/games/game_result.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/components/string_matching/tokenized_string.h"
#include "chromeos/components/string_matching/tokenized_string_match.h"
#include "ui/base/l10n/l10n_util.h"
namespace app_list {
namespace {
using chromeos::string_matching::TokenizedString;
using chromeos::string_matching::TokenizedStringMatch;
constexpr double kRelevanceThreshold = 0.7;
constexpr size_t kMaxResults = 3u;
double CalculateTitleRelevance(const TokenizedString& tokenized_query,
const std::u16string& game_title) {
const TokenizedString tokenized_title(game_title,
TokenizedString::Mode::kCamelCase);
if (tokenized_query.text().empty() || tokenized_title.text().empty()) {
static constexpr double kDefaultRelevance = 0.0;
return kDefaultRelevance;
}
TokenizedStringMatch match;
match.Calculate(tokenized_query, tokenized_title);
return match.relevance();
}
std::vector<std::pair<GameData, double>> SearchGames(std::u16string query,
GameIndex* index) {
TokenizedString tokenized_query(query, TokenizedString::Mode::kCamelCase);
std::vector<std::pair<GameData, double>> matches;
for (const auto& game_data : *index) {
double relevance =
CalculateTitleRelevance(tokenized_query, game_data.title);
if (relevance > kRelevanceThreshold) {
matches.push_back(std::make_pair(game_data, relevance));
}
}
return matches;
}
} // namespace
GameProvider::GameProvider(Profile* profile,
AppListControllerDelegate* list_controller)
: profile_(profile), list_controller_(list_controller) {
DCHECK(profile_);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
game_index_manager_ = std::make_unique<GameIndexManager>();
game_index_ = game_index_manager_->GetIndex();
index_observer_.Observe(game_index_manager_.get());
}
GameProvider::~GameProvider() = default;
ash::AppListSearchResultType GameProvider::ResultType() const {
return ash::AppListSearchResultType::kGames;
}
void GameProvider::OnIndexUpdated(const absl::optional<GameIndex>& index) {
if (index)
game_index_ = index;
}
void GameProvider::Start(const std::u16string& query) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!game_index_)
return;
// Clear results and discard any existing searches.
ClearResultsSilently();
weak_factory_.InvalidateWeakPtrs();
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::TaskPriority::USER_BLOCKING},
base::BindOnce(&SearchGames, query, &game_index_.value()),
base::BindOnce(&GameProvider::OnSearchComplete,
weak_factory_.GetWeakPtr(), query));
}
void GameProvider::SetGameIndexForTest(const GameIndex& game_index) {
game_index_ = game_index;
}
void GameProvider::OnSearchComplete(
std::u16string query,
std::vector<std::pair<GameData, double>> matches) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Sort matches by descending relevance score.
std::sort(matches.begin(), matches.end(),
[](const auto& a, const auto& b) { return a.second > b.second; });
SearchProvider::Results results;
for (size_t i = 0; i < std::min(matches.size(), kMaxResults); ++i) {
results.emplace_back(std::make_unique<GameResult>(
profile_, list_controller_, game_index_manager_.get(), matches[i].first,
matches[i].second, query));
}
SwapResults(&results);
}
} // namespace app_list

@ -0,0 +1,63 @@
// Copyright 2022 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_GAMES_GAME_PROVIDER_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "chrome/browser/ui/app_list/search/games/stub_api.h"
#include "chrome/browser/ui/app_list/search/search_provider.h"
#include "chrome/browser/ui/ash/thumbnail_loader.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
class AppListControllerDelegate;
class Profile;
namespace app_list {
// Provider for cloud gaming search.
class GameProvider : public SearchProvider, public GameIndexManager::Observer {
public:
GameProvider(Profile* profile, AppListControllerDelegate* list_controller);
~GameProvider() override;
GameProvider(const GameProvider&) = delete;
GameProvider& operator=(const GameProvider&) = delete;
// GameIndexManager::Observer:
void OnIndexUpdated(const absl::optional<GameIndex>& index) override;
// SearchProvider:
ash::AppListSearchResultType ResultType() const override;
void Start(const std::u16string& query) override;
void SetGameIndexForTest(const GameIndex& game_index);
private:
void OnSearchComplete(std::u16string query,
std::vector<std::pair<GameData, double>> matches);
Profile* const profile_;
AppListControllerDelegate* list_controller_;
std::unique_ptr<GameIndexManager> game_index_manager_;
absl::optional<GameIndex> game_index_;
base::ScopedObservation<GameIndexManager, GameIndexManager::Observer>
index_observer_{this};
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<GameProvider> weak_factory_{this};
};
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_

@ -0,0 +1,90 @@
// Copyright 2022 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/games/game_provider.h"
#include "ash/public/cpp/app_list/app_list_features.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "chrome/browser/ui/app_list/search/games/stub_api.h"
#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace app_list {
namespace {
using ::testing::ElementsAre;
using ::testing::UnorderedElementsAre;
MATCHER_P(Title, title, "") {
return base::UTF16ToUTF8(arg->title()) == title;
}
GameData MakeGameData(const std::u16string& title) {
GameData data;
data.title = title;
data.source = GameSource::kExampleSource;
data.launch_url = GURL("https://example.com");
return data;
}
} // namespace
class GameProviderTest : public testing::Test {
protected:
void SetUp() override {
profile_ = std::make_unique<TestingProfile>();
provider_ =
std::make_unique<GameProvider>(profile_.get(), &list_controller_);
search_controller_ = std::make_unique<TestSearchController>();
provider_->set_controller(search_controller_.get());
}
const SearchProvider::Results& LastResults() {
if (app_list_features::IsCategoricalSearchEnabled()) {
return search_controller_->last_results();
} else {
return provider_->results();
}
}
void SetUpTestingIndex() {
GameIndex index;
index.push_back(MakeGameData(u"First Title"));
index.push_back(MakeGameData(u"Second Title"));
index.push_back(MakeGameData(u"Third Title"));
provider_->SetGameIndexForTest(std::move(index));
}
void Wait() { task_environment_.RunUntilIdle(); }
content::BrowserTaskEnvironment task_environment_;
::test::TestAppListControllerDelegate list_controller_;
std::unique_ptr<TestSearchController> search_controller_;
std::unique_ptr<Profile> profile_;
std::unique_ptr<GameProvider> provider_;
};
TEST_F(GameProviderTest, SearchResultsMatchQuery) {
SetUpTestingIndex();
provider_->Start(u"first");
Wait();
EXPECT_THAT(LastResults(), ElementsAre(Title("First Title")));
provider_->Start(u"title");
Wait();
EXPECT_THAT(LastResults(),
UnorderedElementsAre(Title("First Title"), Title("Second Title"),
Title("Third Title")));
}
} // namespace app_list

@ -0,0 +1,121 @@
// Copyright 2022 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/games/game_result.h"
#include <string>
#include "ash/public/cpp/app_list/app_list_config.h"
#include "ash/public/cpp/app_list/app_list_types.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
#include "chrome/browser/ui/app_list/search/search_tags_util.h"
#include "chrome/browser/ui/ash/thumbnail_loader.h"
#include "chromeos/components/string_matching/tokenized_string.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/page_transition_types.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image_skia.h"
namespace app_list {
namespace {
constexpr char16_t kPlatformDelimiter[] = u", ";
constexpr char16_t kDetailsDelimiter[] = u" - ";
constexpr char16_t kA11yDelimiter[] = u", ";
} // namespace
GameResult::GameResult(Profile* profile,
AppListControllerDelegate* list_controller,
GameIndexManager* index_manager,
const GameData& game_data,
double relevance,
const std::u16string& query)
: profile_(profile),
list_controller_(list_controller),
launch_url_(game_data.launch_url) {
DCHECK(profile);
DCHECK(list_controller);
DCHECK(index_manager);
DCHECK(launch_url_.is_valid());
set_id(launch_url_.spec());
set_relevance(relevance);
SetMetricsType(ash::GAME_SEARCH);
SetResultType(ResultType::kGames);
SetDisplayType(DisplayType::kList);
SetCategory(Category::kGames);
UpdateText(game_data, query);
// TODO(crbug.com/1305880): Set a default icon.
index_manager->GetIcon(game_data.icon_url,
base::BindOnce(&GameResult::OnIconLoaded,
weak_ptr_factory_.GetWeakPtr()));
}
GameResult::~GameResult() = default;
void GameResult::Open(int event_flags) {
list_controller_->OpenURL(profile_, launch_url_, ui::PAGE_TRANSITION_TYPED,
ui::DispositionFromEventFlags(event_flags));
}
void GameResult::UpdateText(const GameData& game_data,
const std::u16string& query) {
SetTitle(game_data.title);
SetTitleTags(CalculateTags(query, title()));
std::vector<ash::SearchResultTextItem> details;
std::vector<std::u16string> accessible_name;
accessible_name.push_back(title());
accessible_name.push_back(kA11yDelimiter);
std::u16string source = GameSourceDisplayString(game_data.source);
details.push_back(CreateStringTextItem(source).SetElidable(false));
accessible_name.push_back(source);
if (game_data.platforms) {
std::u16string platforms =
base::JoinString(game_data.platforms.value(), kPlatformDelimiter);
details.push_back(CreateStringTextItem(kDetailsDelimiter));
details.push_back(
CreateStringTextItem(IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX));
details.push_back(CreateStringTextItem(u" "));
details.push_back(CreateStringTextItem(platforms));
accessible_name.push_back(kA11yDelimiter);
accessible_name.push_back(
l10n_util::GetStringUTF16(IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX));
accessible_name.push_back(u" ");
accessible_name.push_back(platforms);
}
SetDetailsTextVector(details);
SetAccessibleName(base::StrCat(accessible_name));
}
void GameResult::OnIconLoaded(const SkBitmap* bitmap) {
if (!bitmap || bitmap->isNull())
return;
IconInfo icon_info(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap),
GetAppIconDimension(), IconShape::kRoundedRectangle);
SetIcon(icon_info);
}
} // namespace app_list

@ -0,0 +1,51 @@
// Copyright 2022 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_GAMES_GAME_RESULT_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
#include "chrome/browser/ui/app_list/search/games/stub_api.h"
#include "url/gurl.h"
class AppListControllerDelegate;
class Profile;
class SkBitmap;
namespace app_list {
// Search result for cloud gaming search.
class GameResult : public ChromeSearchResult {
public:
GameResult(Profile* profile,
AppListControllerDelegate* list_controller,
GameIndexManager* index_manager,
const GameData& game_data,
double relevance,
const std::u16string& query);
~GameResult() override;
GameResult(const GameResult&) = delete;
GameResult& operator=(const GameResult&) = delete;
// ChromeSearchResult overrides:
void Open(int event_flags) override;
private:
void OnIconLoaded(const SkBitmap* bitmap);
void UpdateText(const GameData& game_data, const std::u16string& query);
Profile* profile_;
AppListControllerDelegate* list_controller_;
const GURL launch_url_;
base::WeakPtrFactory<GameResult> weak_ptr_factory_{this};
};
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_

@ -0,0 +1,60 @@
// Copyright 2022 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/games/game_result.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/strings/strcat.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
#include "chrome/browser/ui/app_list/search/games/stub_api.h"
#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
namespace app_list {
class GameResultTest : public testing::Test {
public:
GameResultTest() { profile_ = std::make_unique<TestingProfile>(); }
~GameResultTest() override = default;
content::BrowserTaskEnvironment task_environment_;
test::TestAppListControllerDelegate list_controller_;
std::unique_ptr<Profile> profile_;
};
TEST_F(GameResultTest, Basic) {
GameIndexManager index_manager;
GameData game_data;
game_data.title = u"Title";
game_data.source = GameSource::kExampleSource;
game_data.launch_url = GURL("https://test-url.com/");
game_data.platforms = {u"A", u"B", u"C"};
GameResult result(profile_.get(), &list_controller_, &index_manager,
game_data, 0.6, u"SomeGame");
EXPECT_EQ(result.title(), u"Title");
EXPECT_EQ(StringFromTextVector(result.details_text_vector()),
base::StrCat({u"Example source - ",
l10n_util::GetStringUTF16(
IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX),
u" A, B, C"}));
EXPECT_EQ(result.accessible_name(),
base::StrCat({u"Title, Example source, ",
l10n_util::GetStringUTF16(
IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX),
u" A, B, C"}));
}
} // namespace app_list

@ -0,0 +1,40 @@
// Copyright 2022 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/games/stub_api.h"
// TODO(crbug.com/1305880)
// This whole file is a temporary fake API for the game index manager, that can
// be deleted and replaced once the real API is implemented.
namespace app_list {
GameData::GameData() = default;
GameData::~GameData() = default;
GameData::GameData(const GameData&) = default;
GameData& GameData::operator=(const GameData&) = default;
absl::optional<GameIndex> GameIndexManager::GetIndex() {
return absl::nullopt;
}
void GameIndexManager::AddObserver(GameIndexManager::Observer* observer) {}
void GameIndexManager::RemoveObserver(GameIndexManager::Observer* observer) {}
void GameIndexManager::GetIcon(
const GURL& icon_url,
base::OnceCallback<void(const SkBitmap*)> callback) {}
std::u16string GameSourceDisplayString(GameSource source) {
switch (source) {
case GameSource::kExampleSource:
return u"Example source";
}
}
} // namespace app_list

@ -0,0 +1,72 @@
// Copyright 2022 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_GAMES_STUB_API_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_STUB_API_H_
#include <string>
#include "base/callback.h"
#include "base/observer_list_types.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
// TODO(crbug.com/1305880)
// This whole file is a temporary fake API for the game index manager, that can
// be deleted and replaced once the real API is implemented.
namespace app_list {
// Each possible source a game can be provided by.
enum class GameSource {
kExampleSource,
};
// Metadata for a single game in the index of games.
struct GameData {
// Game title
std::u16string title;
GameSource source = GameSource::kExampleSource;
// What platforms the game is available on.
absl::optional<std::vector<std::u16string>> platforms;
// The URL that should be opened when the search result is clicked.
GURL launch_url;
// A token uniquely identifying an icon.
GURL icon_url;
GameData();
~GameData();
GameData(const GameData&);
GameData& operator=(const GameData&);
};
// A collection of game data, forming an index.
using GameIndex = std::vector<GameData>;
class GameIndexManager {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnIndexUpdated(const absl::optional<GameIndex>& index) = 0;
};
absl::optional<GameIndex> GetIndex();
void GetIcon(const GURL& icon_url,
base::OnceCallback<void(const SkBitmap*)> callback);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
};
std::u16string GameSourceDisplayString(GameSource source);
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_STUB_API_H_

@ -18,6 +18,35 @@
namespace app_list {
namespace {
// Given `higher_priority` and `lower_priority` result types, deduplicate
// results between the two result types in `results` based on their id,
// preserving the ones in `higher_priority`.
//
// Note this only deduplicates results whose ids are present in both result
// types; if two results of one result type have the same id, they will not be
// deduplicated.
void DeduplicateResults(ResultsMap& results,
ResultType higher_priority,
ResultType lower_priority) {
const auto first_it = results.find(higher_priority);
const auto second_it = results.find(lower_priority);
if (first_it == results.end() || second_it == results.end())
return;
const auto& first_results = first_it->second;
const auto& second_results = second_it->second;
base::flat_set<std::string> first_ids;
for (const auto& result : first_results) {
if (result->result_type() == higher_priority)
first_ids.insert(result->id());
}
for (auto& result : second_results) {
if (first_ids.contains(result->id()))
result->scoring().filter = true;
}
}
void DeduplicateDriveFilesAndTabs(ResultsMap& results) {
const auto omnibox_it = results.find(ProviderType::kOmnibox);
const auto drive_it = results.find(ProviderType::kDriveSearch);
@ -91,6 +120,9 @@ void FilteringRanker::UpdateResultRanks(ResultsMap& results,
return;
FilterOmniboxResults(results);
DeduplicateDriveFilesAndTabs(results);
// TODO(crbug.com/1305880): Verify that game URLs match the omnibox stripped
// URL once game URLs are finalized.
DeduplicateResults(results, ResultType::kGames, ResultType::kOmnibox);
}
} // namespace app_list

@ -25,6 +25,7 @@
#include "chrome/browser/ui/app_list/search/files/file_search_provider.h"
#include "chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h"
#include "chrome/browser/ui/app_list/search/files/zero_state_file_provider.h"
#include "chrome/browser/ui/app_list/search/games/game_provider.h"
#include "chrome/browser/ui/app_list/search/help_app_provider.h"
#include "chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h"
#include "chrome/browser/ui/app_list/search/mixer.h"
@ -171,6 +172,15 @@ std::unique_ptr<SearchController> CreateSearchController(
controller->AddProvider(help_app_group_id,
std::make_unique<HelpAppProvider>(profile));
// TODO(crbug.com/1305880): Move this to its own flag.
if (ash::features::IsProductivityLauncherEnabled() &&
base::GetFieldTrialParamByFeatureAsBool(
ash::features::kProductivityLauncher, "enable_games", false)) {
size_t games_group_id = controller->AddGroup(kGenericMaxResults);
controller->AddProvider(games_group_id, std::make_unique<GameProvider>(
profile, list_controller));
}
return controller;
}

@ -2669,9 +2669,8 @@ if (!is_android) {
"//third_party/liblouis/wasm/liblouis_wrapper_browsertest.cc",
]
deps += [ "//chrome/browser/chromeos" ]
data_deps += [
"//third_party/liblouis:liblouis_test_data",
]
data_deps += [ "//third_party/liblouis:liblouis_test_data" ]
# TODO(https://crbug.com/1299021): Implement building these NaCl
# targets as ARM32 when Chrome is built for ARM64 (for Linux/Chrome
# OS).
@ -2692,6 +2691,7 @@ if (!is_android) {
# browser process as needed by this test. See http://crbug.com/157312.
sources -= [ "../browser/nacl_host/test/gdb_debug_stub_browsertest.cc" ]
}
# TODO(https://crbug.com/1299021): Implement building this NaCl target
# as ARM32 when Chrome is built for ARM64 (for Linux/Chrome OS).
if ((is_linux || is_chromeos) && target_cpu != "arm64") {
@ -7021,6 +7021,8 @@ test("unit_tests") {
"../browser/ui/app_list/search/files/justifications_unittest.cc",
"../browser/ui/app_list/search/files/zero_state_drive_provider_unittest.cc",
"../browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc",
"../browser/ui/app_list/search/games/game_provider_unittest.cc",
"../browser/ui/app_list/search/games/game_result_unittest.cc",
"../browser/ui/app_list/search/help_app_provider_unittest.cc",
"../browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc",
"../browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc",