chromium/chrome/browser/ash/app_list/search/app_search_provider.cc

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/app_list/search/app_search_provider.h"

#include <string>
#include <string_view>
#include <utility>

#include "ash/public/cpp/app_list/app_list_features.h"
#include "base/callback_list.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/i18n/rtl.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "chrome/browser/ash/app_list/app_list_model_updater.h"
#include "chrome/browser/ash/app_list/search/app_search_data_source.h"
#include "chrome/browser/ash/app_list/search/chrome_search_result.h"
#include "chrome/browser/ash/app_list/search/types.h"

namespace app_list {

namespace {

// Checks if current locale is non Latin locales.
bool IsNonLatinLocale(std::string_view locale) {
  // A set of of non Latin locales. This set is used to select appropriate
  // algorithm for app search.
  static constexpr char kNonLatinLocales[][6] = {
      "am", "ar", "be", "bg", "bn",    "el",    "fa",   "gu", "hi",
      "hy", "iw", "ja", "ka", "kk",    "km",    "kn",   "ko", "ky",
      "lo", "mk", "ml", "mn", "mr",    "my",    "pa",   "ru", "sr",
      "ta", "te", "th", "uk", "zh-CN", "zh-HK", "zh-TW"};
  return base::Contains(kNonLatinLocales, locale);
}

}  // namespace

AppSearchProvider::AppSearchProvider(AppSearchDataSource* data_source)
    : SearchProvider(SearchCategory::kApps), data_source_(data_source) {
  app_updates_subscription_ =
      data_source_->SubscribeToAppUpdates(base::BindRepeating(
          &AppSearchProvider::UpdateResults, base::Unretained(this)));
}

AppSearchProvider::~AppSearchProvider() = default;

void AppSearchProvider::Start(const std::u16string& query) {
  query_ = query;
  query_start_time_ = base::TimeTicks::Now();
  // We only need to record app search latency for queries started by user.
  record_query_uma_ = true;

  {
    // Prevent `UpdateResults()` from running as a result of a data source
    // refresh callback to avoid double update.
    base::AutoReset<bool> auto_reset(&updates_blocked_, true);
    data_source_->RefreshIfNeeded();
  }

  UpdateResults();
}

void AppSearchProvider::StopQuery() {
  query_.clear();
  record_query_uma_ = false;
}

ash::AppListSearchResultType AppSearchProvider::ResultType() const {
  return ash::AppListSearchResultType::kInstalledApp;
}

void AppSearchProvider::UpdateResults() {
  if (updates_blocked_ || query_.empty())
    return;

  SearchProvider::Results new_results;

  const bool use_exact_match =
      app_list_features::IsExactMatchForNonLatinLocaleEnabled() &&
      IsNonLatinLocale(base::i18n::GetConfiguredLocale());

  if (use_exact_match) {
    new_results = data_source_->GetExactMatches(query_);
  } else {
    new_results = data_source_->GetFuzzyMatches(query_);
  }

  if (record_query_uma_) {
    record_query_uma_ = false;
    UMA_HISTOGRAM_TIMES("Apps.AppList.AppSearchProvider.QueryTime",
                        base::TimeTicks::Now() - query_start_time_);
  }

  SwapResults(&new_results);
}

}  // namespace app_list