Commit 7c017cd5 authored by Thanh Nguyen's avatar Thanh Nguyen Committed by Chromium LUCI CQ

[local-search-service] Clean sync code of LSS

Since LSS has been sandboxed and clients are using new sandboxed LSS, we
need to clean up the code. This CL cleans the unused sync code.

Design doc: go/lss-sandboxing
Implementation plan: go/lss-sandboxing-impl

Bug: 1137560
Change-Id: If8347e621b0169ff15062deb7a8953c1c76bf6f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2594747Reviewed-by: default avatarJia Meng <jiameng@chromium.org>
Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Commit-Queue: Thanh Nguyen <thanhdng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838583}
parent e8384250
......@@ -343,7 +343,6 @@
#include "chromeos/audio/audio_devices_pref_handler_impl.h"
#include "chromeos/components/account_manager/account_manager.h"
#include "chromeos/components/local_search_service/search_metrics_reporter.h"
#include "chromeos/components/local_search_service/search_metrics_reporter_sync.h"
#include "chromeos/components/quick_answers/public/cpp/quick_answers_prefs.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/network/fast_transition_observer.h"
......@@ -423,6 +422,15 @@ const char kDataReductionNetworkProperties[] =
// Deprecated 10/2019
const char kDisplayRotationAcceleratorDialogHasBeenAccepted[] =
"settings.a11y.display_rotation_accelerator_dialog_has_been_accepted";
// Deprecated 12/2020
const char kLocalSearchServiceSyncMetricsDailySample[] =
"local_search_service_sync.metrics.daily_sample";
const char kLocalSearchServiceSyncMetricsCrosSettingsCount[] =
"local_search_service_sync.metrics.cros_settings_count";
const char kLocalSearchServiceSyncMetricsHelpAppCount[] =
"local_search_service_sync.metrics.help_app_count";
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Deprecated 11/2019
......@@ -540,6 +548,11 @@ void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(kRegisteredSupervisedUserAllowlists);
registry->RegisterIntegerPref(kSupervisedUsersNextId, 0);
registry->RegisterStringPref(kFirstRunTrialGroup, std::string());
registry->RegisterInt64Pref(kLocalSearchServiceSyncMetricsDailySample, 0);
registry->RegisterIntegerPref(kLocalSearchServiceSyncMetricsHelpAppCount, 0);
registry->RegisterIntegerPref(kLocalSearchServiceSyncMetricsCrosSettingsCount,
0);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if !defined(OS_ANDROID)
......@@ -740,9 +753,6 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
chromeos::language_prefs::RegisterPrefs(registry);
chromeos::local_search_service::SearchMetricsReporter::
RegisterLocalStatePrefs(registry);
// TODO(crbug/1137560): Remove the Sync version later after LSS is sandboxed.
chromeos::local_search_service::SearchMetricsReporterSync::
RegisterLocalStatePrefs(registry);
chromeos::login::SecurityTokenSessionController::RegisterLocalStatePrefs(
registry);
chromeos::MultiProfileUserController::RegisterPrefs(registry);
......@@ -1155,6 +1165,9 @@ void MigrateObsoleteLocalStatePrefs(PrefService* local_state) {
// Added 12/2020.
local_state->ClearPref(kFirstRunTrialGroup);
local_state->ClearPref(kLocalSearchServiceSyncMetricsDailySample);
local_state->ClearPref(kLocalSearchServiceSyncMetricsCrosSettingsCount);
local_state->ClearPref(kLocalSearchServiceSyncMetricsHelpAppCount);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if !defined(OS_ANDROID)
......
......@@ -10,8 +10,6 @@ source_set("local_search_service") {
"content_extraction_utils.h",
"index.cc",
"index.h",
"index_sync.cc",
"index_sync.h",
"inverted_index.cc",
"inverted_index.h",
"inverted_index_search.cc",
......@@ -24,8 +22,6 @@ source_set("local_search_service") {
"pref_names.h",
"search_metrics_reporter.cc",
"search_metrics_reporter.h",
"search_metrics_reporter_sync.cc",
"search_metrics_reporter_sync.h",
"search_utils.cc",
"search_utils.h",
"shared_structs.cc",
......@@ -47,19 +43,6 @@ source_set("local_search_service") {
]
}
source_set("local_search_service_sync") {
sources = [
"local_search_service_sync.cc",
"local_search_service_sync.h",
"local_search_service_sync_factory.cc",
"local_search_service_sync_factory.h",
]
deps = [
":local_search_service",
"//components/keyed_service/content:content",
]
}
source_set("local_search_service_provider") {
sources = [
"local_search_service_provider_for_testing.cc",
......@@ -75,31 +58,6 @@ source_set("local_search_service_provider") {
]
}
source_set("local_search_service_proxy") {
sources = [
"index_sync_proxy.cc",
"index_sync_proxy.h",
"local_search_service_sync_proxy.cc",
"local_search_service_sync_proxy.h",
"local_search_service_sync_proxy_factory.cc",
"local_search_service_sync_proxy_factory.h",
]
deps = [
"//base:i18n",
"//cc",
]
public_deps = [
":local_search_service",
":local_search_service_sync",
"//base",
"//chromeos/components/local_search_service/public/mojom",
"//components/keyed_service/content:content",
"//components/prefs",
]
}
source_set("test_support") {
testonly = true
......@@ -124,10 +82,7 @@ source_set("unit_tests") {
"linear_map_search_unittest.cc",
"local_search_service_provider_unittest.cc",
"local_search_service_proxy_unittest.cc",
"local_search_service_sync_proxy_unittest.cc",
"local_search_service_sync_unittest.cc",
"local_search_service_unittest.cc",
"search_metrics_reporter_sync_unittest.cc",
"search_metrics_reporter_unittest.cc",
"search_utils_unittest.cc",
]
......@@ -135,7 +90,6 @@ source_set("unit_tests") {
deps = [
":local_search_service",
":local_search_service_provider",
":local_search_service_proxy",
":test_support",
"//base/test:test_support",
"//chromeos/components/local_search_service/public/cpp:cpp",
......
......@@ -27,6 +27,12 @@ class Index : public mojom::Index {
void SetReporterRemote(
mojo::PendingRemote<mojom::SearchMetricsReporter> reporter_remote);
void SetSearchParams(const SearchParams& search_params) {
search_params_ = search_params;
}
SearchParams GetSearchParamsForTesting() const { return search_params_; }
protected:
// Logs daily search metrics if |reporter_remote_| is bound. Also logs
// other UMA metrics (number results and search latency).
......@@ -37,6 +43,7 @@ class Index : public mojom::Index {
// Logs number of documents in the index.
void MaybeLogIndexSize(uint64_t index_size);
SearchParams search_params_;
IndexId index_id_;
private:
......
// Copyright 2019 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 "chromeos/components/local_search_service/index_sync.h"
#include <utility>
#include "base/metrics/histogram_functions.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace local_search_service {
namespace {
void LogIndexIdAndBackendType(const std::string& histogram_prefix,
Backend backend) {
base::UmaHistogramEnumeration(histogram_prefix + ".Backend", backend);
}
std::string IndexIdBasedHistogramPrefix(IndexId index_id) {
const std::string prefix = "LocalSearchService.";
switch (index_id) {
case IndexId::kCrosSettings:
return prefix + "CrosSettings";
case IndexId::kHelpApp:
return prefix + "HelpApp";
}
}
} // namespace
IndexSync::IndexSync(IndexId index_id,
Backend backend,
PrefService* local_state) {
histogram_prefix_ = IndexIdBasedHistogramPrefix(index_id);
DCHECK(!histogram_prefix_.empty());
LogIndexIdAndBackendType(histogram_prefix_, backend);
// TODO(jiameng): consider enforcing this to be non-nullable.
if (!local_state) {
return;
}
reporter_ = std::make_unique<SearchMetricsReporterSync>(local_state);
DCHECK(reporter_);
reporter_->SetIndexId(index_id);
}
IndexSync::~IndexSync() = default;
void IndexSync::MaybeLogSearchResultsStatsSync(ResponseStatus status,
size_t num_results,
base::TimeDelta latency) {
if (reporter_)
reporter_->OnSearchPerformed();
base::UmaHistogramEnumeration(histogram_prefix_ + ".ResponseStatus", status);
if (status == ResponseStatus::kSuccess) {
// Only logs number of results and latency if search is a success.
base::UmaHistogramCounts100(histogram_prefix_ + ".NumberResults",
num_results);
base::UmaHistogramTimes(histogram_prefix_ + ".SearchLatency", latency);
}
}
void IndexSync::MaybeLogIndexSizeSync() {
const uint64_t index_size = GetSizeSync();
if (index_size != 0u) {
base::UmaHistogramCounts10000(histogram_prefix_ + ".NumberDocuments",
index_size);
}
}
void IndexSync::SetSearchParams(const SearchParams& search_params) {
search_params_ = search_params;
}
SearchParams IndexSync::GetSearchParamsForTesting() {
return search_params_;
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2019 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "chromeos/components/local_search_service/search_metrics_reporter_sync.h"
#include "chromeos/components/local_search_service/shared_structs.h"
class PrefService;
namespace chromeos {
namespace local_search_service {
// A local search service IndexSync.
// It is the client-facing API for search and indexing. It can be implemented
// with different backends that provide actual data storage/indexing/search
// functions.
class IndexSync {
public:
IndexSync(IndexId index_id, Backend backend, PrefService* local_state);
virtual ~IndexSync();
IndexSync(const IndexSync&) = delete;
IndexSync& operator=(const IndexSync&) = delete;
// Returns number of data items.
virtual uint64_t GetSizeSync() = 0;
// Adds or updates data.
// IDs of data should not be empty.
virtual void AddOrUpdateSync(const std::vector<Data>& data) = 0;
// Deletes data with |ids| and returns number of items deleted.
// If an id doesn't exist in the Index, no operation will be done.
// IDs should not be empty.
virtual uint32_t DeleteSync(const std::vector<std::string>& ids) = 0;
// Clears all data in the index.
virtual void ClearIndexSync() = 0;
// Returns matching results for a given query.
// Zero |max_results| means no max.
// Search behaviour depends on the implementation.
virtual ResponseStatus FindSync(const base::string16& query,
uint32_t max_results,
std::vector<Result>* results) = 0;
// Logs daily search metrics if |reporter_| is non-null. Also logs other
// UMA metrics (number results and search latency).
// Each implementation of this class should call this method at the end of
// Find.
void MaybeLogSearchResultsStatsSync(ResponseStatus status,
size_t num_results,
base::TimeDelta latency);
// Logs number of documents in the index if the index is not empty.
// Each implementation of this class should call this method at the end of
// Find.
void MaybeLogIndexSizeSync();
void SetSearchParams(const SearchParams& search_params);
SearchParams GetSearchParamsForTesting();
protected:
SearchParams search_params_;
private:
std::string histogram_prefix_;
std::unique_ptr<SearchMetricsReporterSync> reporter_;
base::WeakPtrFactory<IndexSync> weak_ptr_factory_{this};
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_H_
// Copyright 2020 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 "chromeos/components/local_search_service/index_sync_proxy.h"
#include "base/optional.h"
#include "chromeos/components/local_search_service/index_sync.h"
namespace chromeos {
namespace local_search_service {
IndexSyncProxy::IndexSyncProxy(IndexSync* index) : index_(index) {
DCHECK(index_);
}
IndexSyncProxy::~IndexSyncProxy() = default;
void IndexSyncProxy::BindReceiver(
mojo::PendingReceiver<mojom::IndexSyncProxy> receiver) {
receivers_.Add(this, std::move(receiver));
}
void IndexSyncProxy::GetSize(GetSizeCallback callback) {
const uint64_t num_items = index_->GetSizeSync();
std::move(callback).Run(num_items);
}
void IndexSyncProxy::AddOrUpdate(const std::vector<Data>& data,
AddOrUpdateCallback callback) {
index_->AddOrUpdateSync(data);
std::move(callback).Run();
}
void IndexSyncProxy::Delete(const std::vector<std::string>& ids,
DeleteCallback callback) {
const uint64_t num_deleted = index_->DeleteSync(ids);
std::move(callback).Run(num_deleted);
}
void IndexSyncProxy::Find(const base::string16& query,
uint32_t max_results,
FindCallback callback) {
std::vector<Result> results;
ResponseStatus status = index_->FindSync(query, max_results, &results);
if (status != ResponseStatus::kSuccess) {
std::move(callback).Run(status, base::nullopt);
} else {
std::move(callback).Run(status, std::move(results));
}
}
void IndexSyncProxy::ClearIndex(ClearIndexCallback callback) {
index_->ClearIndexSync();
std::move(callback).Run();
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2020 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_PROXY_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_PROXY_H_
#include <vector>
#include "base/strings/string16.h"
#include "chromeos/components/local_search_service/public/mojom/local_search_service_proxy.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
namespace chromeos {
namespace local_search_service {
class IndexSync;
class IndexSyncProxy : public mojom::IndexSyncProxy {
public:
explicit IndexSyncProxy(IndexSync* index);
~IndexSyncProxy() override;
void BindReceiver(mojo::PendingReceiver<mojom::IndexSyncProxy> receiver);
// mojom::IndexSyncProxy:
void GetSize(GetSizeCallback callback) override;
void AddOrUpdate(const std::vector<Data>& data,
AddOrUpdateCallback callback) override;
void Delete(const std::vector<std::string>& ids,
DeleteCallback callback) override;
void Find(const base::string16& query,
uint32_t max_results,
FindCallback callback) override;
void ClearIndex(ClearIndexCallback callback) override;
private:
IndexSync* const index_;
mojo::ReceiverSet<mojom::IndexSyncProxy> receivers_;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_INDEX_SYNC_PROXY_H_
......@@ -78,10 +78,8 @@ std::unordered_set<base::string16> GetTokenizedQuery(
} // namespace
InvertedIndexSearch::InvertedIndexSearch(IndexId index_id,
PrefService* local_state)
: IndexSync(index_id, Backend::kInvertedIndex, local_state),
Index(index_id, Backend::kInvertedIndex),
InvertedIndexSearch::InvertedIndexSearch(IndexId index_id)
: Index(index_id, Backend::kInvertedIndex),
inverted_index_(std::make_unique<InvertedIndex>()),
blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::BEST_EFFORT, base::MayBlock(),
......@@ -91,82 +89,6 @@ InvertedIndexSearch::~InvertedIndexSearch() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
uint64_t InvertedIndexSearch::GetSizeSync() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return inverted_index_->NumberDocuments();
}
void InvertedIndexSearch::AddOrUpdateSync(
const std::vector<local_search_service::Data>& data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!data.empty());
++num_queued_index_updates_;
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(), FROM_HERE,
base::BindOnce(&ExtractDocumentsContent, data),
base::BindOnce(&InvertedIndexSearch::FinalizeAddOrUpdateSync,
weak_ptr_factory_.GetWeakPtr()));
}
uint32_t InvertedIndexSearch::DeleteSync(const std::vector<std::string>& ids) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!ids.empty());
if (num_queued_index_updates_ == 0) {
// We can remove the documents immediately as there is no earlier
// index-modifying operation.
inverted_index_->RemoveDocuments(ids);
MaybeBuildInvertedIndex();
return ids.size();
}
// If there is an earlier index-modifying operation, Delete should wait until
// the other operations are complete. Delete is queued and we create a no-op
// to run on the same |blocking_task_runner_|.
++num_queued_index_updates_;
blocking_task_runner_->PostTaskAndReply(
FROM_HERE, base::DoNothing(),
base::BindOnce(&InvertedIndexSearch::FinalizeDeleteSync,
weak_ptr_factory_.GetWeakPtr(), ids));
return ids.size();
}
void InvertedIndexSearch::ClearIndexSync() {
inverted_index_->ClearInvertedIndex();
}
ResponseStatus InvertedIndexSearch::FindSync(const base::string16& query,
uint32_t max_results,
std::vector<Result>* results) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const base::TimeTicks start = base::TimeTicks::Now();
DCHECK(results);
results->clear();
if (query.empty()) {
const ResponseStatus status = ResponseStatus::kEmptyQuery;
MaybeLogSearchResultsStatsSync(status, 0u, base::TimeDelta());
return status;
}
if (GetSizeSync() == 0u) {
const ResponseStatus status = ResponseStatus::kEmptyIndex;
MaybeLogSearchResultsStatsSync(status, 0u, base::TimeDelta());
return status;
}
*results = inverted_index_->FindMatchingDocumentsApproximately(
GetTokenizedQuery(query), search_params_.prefix_threshold,
search_params_.fuzzy_threshold);
if (results->size() > max_results && max_results > 0u)
results->resize(max_results);
const base::TimeTicks end = base::TimeTicks::Now();
const ResponseStatus status = ResponseStatus::kSuccess;
MaybeLogSearchResultsStatsSync(status, results->size(), end - start);
return status;
}
void InvertedIndexSearch::GetSize(GetSizeCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run(inverted_index_->NumberDocuments());
......@@ -253,22 +175,6 @@ InvertedIndexSearch::FindTermForTesting(const base::string16& term) const {
return doc_with_freq;
}
void InvertedIndexSearch::FinalizeAddOrUpdateSync(
const ExtractedContent& documents) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
--num_queued_index_updates_;
inverted_index_->AddDocuments(documents);
MaybeBuildInvertedIndex();
}
void InvertedIndexSearch::FinalizeDeleteSync(
const std::vector<std::string>& ids) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
--num_queued_index_updates_;
inverted_index_->RemoveDocuments(ids);
MaybeBuildInvertedIndex();
}
void InvertedIndexSearch::FinalizeAddOrUpdate(
AddOrUpdateCallback callback,
const ExtractedContent& documents) {
......
......@@ -15,7 +15,6 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string16.h"
#include "chromeos/components/local_search_service/index.h"
#include "chromeos/components/local_search_service/index_sync.h"
#include "chromeos/components/local_search_service/shared_structs.h"
namespace chromeos {
......@@ -25,34 +24,14 @@ class InvertedIndex;
// An implementation of Index.
// A search via the inverted index backend with TF-IDF based document ranking.
class InvertedIndexSearch : public IndexSync, public Index {
class InvertedIndexSearch : public Index {
public:
InvertedIndexSearch(IndexId index_id, PrefService* local_state);
explicit InvertedIndexSearch(IndexId index_id);
~InvertedIndexSearch() override;
InvertedIndexSearch(const InvertedIndexSearch&) = delete;
InvertedIndexSearch& operator=(const InvertedIndexSearch&) = delete;
// IndexSync overrides:
uint64_t GetSizeSync() override;
// TODO(jiameng): we always build the index after documents are updated. May
// revise this strategy if there is a different use case.
void AddOrUpdateSync(const std::vector<Data>& data) override;
// TODO(jiameng): we always build the index after documents are deleted. May
// revise this strategy if there is a different use case.
// TODO(jiameng): for inverted index, the Delete function returns |ids| size,
// and not actual number of documents deleted. This would change in the next
// cl when these operations become async.
uint32_t DeleteSync(const std::vector<std::string>& ids) override;
void ClearIndexSync() override;
// Returns matching results for a given query by approximately matching the
// query with terms in the documents. Documents are ranked by TF-IDF scores.
// Scores in results are positive but not guaranteed to be in any particular
// range.
ResponseStatus FindSync(const base::string16& query,
uint32_t max_results,
std::vector<Result>* results) override;
// Index overrides:
// GetSize is only accurate if the index has done updating.
void GetSize(GetSizeCallback callback) override;
......@@ -73,14 +52,6 @@ class InvertedIndexSearch : public IndexSync, public Index {
const base::string16& term) const;
private:
void FinalizeAddOrUpdateSync(
const std::vector<std::pair<std::string, std::vector<Token>>>& documents);
// FinalizeDeleteSync is called if Delete cannot be immediately done because
// there's another index updating operation before it, i.e.
// |num_queued_index_updates_| is not zero.
void FinalizeDeleteSync(const std::vector<std::string>& ids);
void FinalizeAddOrUpdate(
AddOrUpdateCallback callback,
const std::vector<std::pair<std::string, std::vector<Token>>>& documents);
......
......@@ -14,7 +14,6 @@
#include "chromeos/components/local_search_service/search_utils.h"
#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
#include "chromeos/components/string_matching/tokenized_string.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace local_search_service {
......@@ -80,70 +79,11 @@ void UpdateData(const std::string& id,
} // namespace
LinearMapSearch::LinearMapSearch(IndexId index_id, PrefService* local_state)
: IndexSync(index_id, Backend::kLinearMap, local_state),
Index(index_id, Backend::kLinearMap) {}
LinearMapSearch::LinearMapSearch(IndexId index_id)
: Index(index_id, Backend::kLinearMap) {}
LinearMapSearch::~LinearMapSearch() = default;
uint64_t LinearMapSearch::GetSizeSync() {
return data_.size();
}
void LinearMapSearch::AddOrUpdateSync(
const std::vector<local_search_service::Data>& data) {
for (const auto& item : data) {
const auto& id = item.id;
DCHECK(!id.empty());
UpdateData(id, item.contents, &data_);
}
MaybeLogIndexSizeSync();
}
uint32_t LinearMapSearch::DeleteSync(const std::vector<std::string>& ids) {
uint32_t num_deleted = 0u;
for (const auto& id : ids) {
DCHECK(!id.empty());
num_deleted += data_.erase(id);
}
MaybeLogIndexSizeSync();
return num_deleted;
}
void LinearMapSearch::ClearIndexSync() {
data_.clear();
}
ResponseStatus LinearMapSearch::FindSync(const base::string16& query,
uint32_t max_results,
std::vector<Result>* results) {
const base::TimeTicks start = base::TimeTicks::Now();
DCHECK(results);
results->clear();
if (query.empty()) {
const ResponseStatus status = ResponseStatus::kEmptyQuery;
MaybeLogSearchResultsStatsSync(status, 0u, base::TimeDelta());
return status;
}
if (data_.empty()) {
const ResponseStatus status = ResponseStatus::kEmptyIndex;
MaybeLogSearchResultsStatsSync(status, 0u, base::TimeDelta());
return status;
}
*results = GetSearchResults(query, max_results);
const base::TimeTicks end = base::TimeTicks::Now();
const ResponseStatus status = ResponseStatus::kSuccess;
MaybeLogSearchResultsStatsSync(status, results->size(), end - start);
return status;
}
void LinearMapSearch::GetSize(GetSizeCallback callback) {
std::move(callback).Run(data_.size());
}
......
......@@ -13,11 +13,8 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "chromeos/components/local_search_service/index.h"
#include "chromeos/components/local_search_service/index_sync.h"
#include "chromeos/components/local_search_service/shared_structs.h"
class PrefService;
namespace chromeos {
namespace string_matching {
......@@ -38,26 +35,14 @@ typedef std::map<
// A search backend that linearly scans all documents in the storage and finds
// documents that match the input query. Search is done by matching query with
// documents' search tags.
class LinearMapSearch : public IndexSync, public Index {
class LinearMapSearch : public Index {
public:
LinearMapSearch(IndexId index_id, PrefService* local_state);
explicit LinearMapSearch(IndexId index_id);
~LinearMapSearch() override;
LinearMapSearch(const LinearMapSearch&) = delete;
LinearMapSearch& operator=(const LinearMapSearch&) = delete;
// IndexSync overrides:
uint64_t GetSizeSync() override;
void AddOrUpdateSync(const std::vector<Data>& data) override;
uint32_t DeleteSync(const std::vector<std::string>& ids) override;
void ClearIndexSync() override;
// For each data in the index, we return the 1st search tag that matches
// the query (i.e. above the threshold). Client should put the most
// important search tag first when registering the data in the index.
ResponseStatus FindSync(const base::string16& query,
uint32_t max_results,
std::vector<Result>* results) override;
// Index overrides:
void GetSize(GetSizeCallback callback) override;
void AddOrUpdate(const std::vector<Data>& data,
......
......@@ -32,43 +32,7 @@ void CheckSearchParams(const SearchParams& actual,
EXPECT_DOUBLE_EQ(actual.fuzzy_threshold, expected.fuzzy_threshold);
}
void FindAndCheckResults(LinearMapSearch* index,
std::string query,
int32_t max_results,
ResponseStatus expected_status,
const std::vector<ResultWithIds>& expected_results) {
DCHECK(index);
std::vector<Result> results;
auto status =
index->FindSync(base::UTF8ToUTF16(query), max_results, &results);
EXPECT_EQ(status, expected_status);
if (!results.empty()) {
// If results are returned, check size and values match the expected.
EXPECT_EQ(results.size(), expected_results.size());
for (size_t i = 0; i < results.size(); ++i) {
EXPECT_EQ(results[i].id, expected_results[i].first);
EXPECT_EQ(results[i].positions.size(), expected_results[i].second.size());
for (size_t j = 0; j < results[i].positions.size(); ++j) {
EXPECT_EQ(results[i].positions[j].content_id,
expected_results[i].second[j]);
}
// Scores should be non-increasing.
if (i < results.size() - 1) {
EXPECT_GE(results[i].score, results[i + 1].score);
}
}
return;
}
// If no results are returned, expected ids should be empty.
EXPECT_TRUE(expected_results.empty());
}
void GetSizeAndCheckResultsWithCallback(LinearMapSearch* index,
void GetSizeAndCheckResults(LinearMapSearch* index,
uint32_t expectd_num_items) {
bool callback_done = false;
uint32_t num_items = 0;
......@@ -82,8 +46,7 @@ void GetSizeAndCheckResultsWithCallback(LinearMapSearch* index,
EXPECT_EQ(num_items, expectd_num_items);
}
void AddOrUpdateWithCallback(LinearMapSearch* index,
const std::vector<Data>& data) {
void AddOrUpdate(LinearMapSearch* index, const std::vector<Data>& data) {
bool callback_done = false;
index->AddOrUpdate(
data, base::BindOnce([](bool* callback_done) { *callback_done = true; },
......@@ -108,8 +71,7 @@ void UpdateDocumentsAndCheckResults(LinearMapSearch* index,
EXPECT_EQ(num_deleted, expect_num_deleted);
}
void FindAndCheckResultsWithCallback(
LinearMapSearch* index,
void FindAndCheckResults(LinearMapSearch* index,
std::string query,
int32_t max_results,
ResponseStatus expected_status,
......@@ -162,8 +124,7 @@ void FindAndCheckResultsWithCallback(
class LinearMapSearchTest : public testing::Test {
void SetUp() override {
index_ = std::make_unique<LinearMapSearch>(IndexId::kCrosSettings,
nullptr /* local_state */);
index_ = std::make_unique<LinearMapSearch>(IndexId::kCrosSettings);
}
protected:
......@@ -198,8 +159,10 @@ TEST_F(LinearMapSearchTest, RelevanceThreshold) {
const std::map<std::string, std::vector<ContentWithId>> data_to_register = {
{"id1", {{"tag1", "Wi-Fi"}}}, {"id2", {{"tag2", "famous"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
index_->AddOrUpdateSync(data);
EXPECT_EQ(index_->GetSizeSync(), 2u);
AddOrUpdate(index_.get(), data);
GetSizeAndCheckResults(index_.get(), 2u);
{
SearchParams search_params;
search_params.relevance_threshold = 0.0;
......@@ -236,8 +199,9 @@ TEST_F(LinearMapSearchTest, MaxResults) {
{"id1", {{"tag1", "abcde"}, {"tag2", "Wi-Fi"}}},
{"id2", {{"tag3", "wifi"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
index_->AddOrUpdateSync(data);
EXPECT_EQ(index_->GetSizeSync(), 2u);
AddOrUpdate(index_.get(), data);
GetSizeAndCheckResults(index_.get(), 2u);
SearchParams search_params;
search_params.relevance_threshold = 0.3;
index_->SetSearchParams(search_params);
......@@ -264,8 +228,8 @@ TEST_F(LinearMapSearchTest, ResultFound) {
std::vector<Data> data = CreateTestData(data_to_register);
EXPECT_EQ(data.size(), 2u);
index_->AddOrUpdateSync(data);
EXPECT_EQ(index_->GetSizeSync(), 2u);
AddOrUpdate(index_.get(), data);
GetSizeAndCheckResults(index_.get(), 2u);
// Find result with query "id1". It returns an exact match.
const std::vector<ResultWithIds> expected_results = {{"id1", {"cid1"}}};
......@@ -283,115 +247,14 @@ TEST_F(LinearMapSearchTest, ClearIndex) {
std::vector<Data> data = CreateTestData(data_to_register);
EXPECT_EQ(data.size(), 2u);
index_->AddOrUpdateSync(data);
EXPECT_EQ(index_->GetSizeSync(), 2u);
index_->ClearIndexSync();
EXPECT_EQ(index_->GetSizeSync(), 0u);
}
TEST_F(LinearMapSearchTest, RelevanceThresholdCallback) {
const std::map<std::string, std::vector<ContentWithId>> data_to_register = {
{"id1", {{"tag1", "Wi-Fi"}}}, {"id2", {{"tag2", "famous"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
AddOrUpdateWithCallback(index_.get(), data);
GetSizeAndCheckResultsWithCallback(index_.get(), 2u);
{
SearchParams search_params;
search_params.relevance_threshold = 0.0;
index_->SetSearchParams(search_params);
const std::vector<ResultWithIds> expected_results = {{"id1", {"tag1"}},
{"id2", {"tag2"}}};
FindAndCheckResultsWithCallback(index_.get(), "wifi",
/*max_results=*/-1,
ResponseStatus::kSuccess, expected_results);
}
{
SearchParams search_params;
search_params.relevance_threshold = 0.3;
index_->SetSearchParams(search_params);
const std::vector<ResultWithIds> expected_results = {{"id1", {"tag1"}}};
FindAndCheckResultsWithCallback(index_.get(), "wifi",
/*max_results=*/-1,
ResponseStatus::kSuccess, expected_results);
}
{
SearchParams search_params;
search_params.relevance_threshold = 0.9;
index_->SetSearchParams(search_params);
FindAndCheckResultsWithCallback(index_.get(), "wifi",
/*max_results=*/-1,
ResponseStatus::kSuccess, {});
}
}
TEST_F(LinearMapSearchTest, MaxResultsCallback) {
const std::map<std::string, std::vector<ContentWithId>> data_to_register = {
{"id1", {{"tag1", "abcde"}, {"tag2", "Wi-Fi"}}},
{"id2", {{"tag3", "wifi"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
AddOrUpdateWithCallback(index_.get(), data);
GetSizeAndCheckResultsWithCallback(index_.get(), 2u);
SearchParams search_params;
search_params.relevance_threshold = 0.3;
index_->SetSearchParams(search_params);
{
const std::vector<ResultWithIds> expected_results = {{"id2", {"tag3"}},
{"id1", {"tag2"}}};
FindAndCheckResultsWithCallback(index_.get(), "wifi",
/*max_results=*/-1,
ResponseStatus::kSuccess, expected_results);
}
{
const std::vector<ResultWithIds> expected_results = {{"id2", {"tag3"}}};
FindAndCheckResultsWithCallback(index_.get(), "wifi",
/*max_results=*/1, ResponseStatus::kSuccess,
expected_results);
}
}
TEST_F(LinearMapSearchTest, ResultFoundCallback) {
const std::map<std::string, std::vector<ContentWithId>> data_to_register = {
{"id1", {{"cid1", "id1"}, {"cid2", "tag1a"}, {"cid3", "tag1b"}}},
{"xyz", {{"cid4", "xyz"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
EXPECT_EQ(data.size(), 2u);
AddOrUpdateWithCallback(index_.get(), data);
GetSizeAndCheckResultsWithCallback(index_.get(), 2u);
// Find result with query "id1". It returns an exact match.
const std::vector<ResultWithIds> expected_results = {{"id1", {"cid1"}}};
FindAndCheckResultsWithCallback(index_.get(), "id1",
/*max_results=*/-1, ResponseStatus::kSuccess,
expected_results);
FindAndCheckResultsWithCallback(index_.get(), "abc",
/*max_results=*/-1, ResponseStatus::kSuccess,
{});
}
TEST_F(LinearMapSearchTest, ClearIndexCallback) {
const std::map<std::string, std::vector<ContentWithId>> data_to_register = {
{"id1", {{"cid1", "id1"}, {"cid2", "tag1a"}, {"cid3", "tag1b"}}},
{"xyz", {{"cid4", "xyz"}}}};
std::vector<Data> data = CreateTestData(data_to_register);
EXPECT_EQ(data.size(), 2u);
AddOrUpdateWithCallback(index_.get(), data);
GetSizeAndCheckResultsWithCallback(index_.get(), 2u);
AddOrUpdate(index_.get(), data);
GetSizeAndCheckResults(index_.get(), 2u);
bool callback_done = false;
index_->ClearIndex(base::BindOnce(
[](bool* callback_done) { *callback_done = true; }, &callback_done));
ASSERT_TRUE(callback_done);
GetSizeAndCheckResultsWithCallback(index_.get(), 0u);
GetSizeAndCheckResults(index_.get(), 0u);
}
TEST_F(LinearMapSearchTest, UpdateDocuments) {
......@@ -401,8 +264,8 @@ TEST_F(LinearMapSearchTest, UpdateDocuments) {
std::vector<Data> data = CreateTestData(data_to_register);
EXPECT_EQ(data.size(), 2u);
AddOrUpdateWithCallback(index_.get(), data);
GetSizeAndCheckResultsWithCallback(index_.get(), 2u);
AddOrUpdate(index_.get(), data);
GetSizeAndCheckResults(index_.get(), 2u);
const std::map<std::string, std::vector<ContentWithId>>
update_data_to_register = {{"id1",
......@@ -415,7 +278,7 @@ TEST_F(LinearMapSearchTest, UpdateDocuments) {
EXPECT_EQ(update_data.size(), 3u);
UpdateDocumentsAndCheckResults(index_.get(), update_data, 1u);
GetSizeAndCheckResultsWithCallback(index_.get(), 1u);
GetSizeAndCheckResults(index_.get(), 1u);
}
} // namespace local_search_service
......
......@@ -23,17 +23,15 @@ void LocalSearchService::BindIndex(
auto it = indices_.find(index_id);
if (it == indices_.end()) {
switch (backend) {
// TODO(thanhdng): Remove |local_state| when IndexSync is removed.
case Backend::kLinearMap:
it = indices_
.emplace(index_id, std::make_unique<LinearMapSearch>(
index_id, /*local_state*/ nullptr))
.emplace(index_id, std::make_unique<LinearMapSearch>(index_id))
.first;
break;
case Backend::kInvertedIndex:
it = indices_
.emplace(index_id, std::make_unique<InvertedIndexSearch>(
index_id, /*local_state*/ nullptr))
.emplace(index_id,
std::make_unique<InvertedIndexSearch>(index_id))
.first;
}
if (!it->second) {
......
// Copyright 2019 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 "chromeos/components/local_search_service/local_search_service_sync.h"
#include <utility>
#include "chromeos/components/local_search_service/inverted_index_search.h"
#include "chromeos/components/local_search_service/linear_map_search.h"
namespace chromeos {
namespace local_search_service {
LocalSearchServiceSync::LocalSearchServiceSync() = default;
LocalSearchServiceSync::~LocalSearchServiceSync() = default;
IndexSync* LocalSearchServiceSync::GetIndexSync(IndexId index_id,
Backend backend,
PrefService* local_state) {
auto it = indices_.find(index_id);
if (it == indices_.end()) {
switch (backend) {
case Backend::kLinearMap:
it = indices_
.emplace(index_id, std::make_unique<LinearMapSearch>(
index_id, local_state))
.first;
break;
case Backend::kInvertedIndex:
it = indices_
.emplace(index_id, std::make_unique<InvertedIndexSearch>(
index_id, local_state))
.first;
}
}
DCHECK(it != indices_.end());
DCHECK(it->second);
return it->second.get();
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2019 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_H_
#include <map>
#include <memory>
#include "base/macros.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "components/keyed_service/core/keyed_service.h"
class PrefService;
namespace chromeos {
namespace local_search_service {
class IndexSync;
// LocalSearchServiceSync creates and owns content-specific Indices. Clients can
// call it |GetIndexSync| method to get an IndexSync for a given index id.
class LocalSearchServiceSync : public KeyedService {
public:
LocalSearchServiceSync();
~LocalSearchServiceSync() override;
LocalSearchServiceSync(const LocalSearchServiceSync&) = delete;
LocalSearchServiceSync& operator=(const LocalSearchServiceSync&) = delete;
IndexSync* GetIndexSync(IndexId index_id,
Backend backend,
PrefService* local_state);
private:
std::map<IndexId, std::unique_ptr<IndexSync>> indices_;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_H_
// Copyright 2019 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 "chromeos/components/local_search_service/local_search_service_sync_factory.h"
#include "chromeos/components/local_search_service/local_search_service_sync.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace chromeos {
namespace local_search_service {
LocalSearchServiceSync* LocalSearchServiceSyncFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<LocalSearchServiceSync*>(
LocalSearchServiceSyncFactory::GetInstance()->GetServiceForBrowserContext(
context, true /* create */));
}
LocalSearchServiceSyncFactory* LocalSearchServiceSyncFactory::GetInstance() {
return base::Singleton<LocalSearchServiceSyncFactory>::get();
}
LocalSearchServiceSyncFactory::LocalSearchServiceSyncFactory()
: BrowserContextKeyedServiceFactory(
"LocalSearchServiceSync",
BrowserContextDependencyManager::GetInstance()) {}
LocalSearchServiceSyncFactory::~LocalSearchServiceSyncFactory() = default;
content::BrowserContext* LocalSearchServiceSyncFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
// The service should exist in incognito mode.
return context;
}
KeyedService* LocalSearchServiceSyncFactory::BuildServiceInstanceFor(
content::BrowserContext* /* context */) const {
return new LocalSearchServiceSync();
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2019 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_FACTORY_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_FACTORY_H_
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace chromeos {
namespace local_search_service {
class LocalSearchServiceSync;
class LocalSearchServiceSyncFactory : public BrowserContextKeyedServiceFactory {
public:
static LocalSearchServiceSync* GetForBrowserContext(
content::BrowserContext* context);
static LocalSearchServiceSyncFactory* GetInstance();
private:
friend struct base::DefaultSingletonTraits<LocalSearchServiceSyncFactory>;
LocalSearchServiceSyncFactory();
~LocalSearchServiceSyncFactory() override;
LocalSearchServiceSyncFactory(const LocalSearchServiceSyncFactory&) = delete;
LocalSearchServiceSyncFactory& operator=(
const LocalSearchServiceSyncFactory&) = delete;
// BrowserContextKeyedServiceFactory overrides.
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_FACTORY_H_
// Copyright 2020 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 "chromeos/components/local_search_service/local_search_service_sync_proxy.h"
#include "chromeos/components/local_search_service/index_sync_proxy.h"
#include "chromeos/components/local_search_service/local_search_service_sync.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace local_search_service {
LocalSearchServiceSyncProxy::LocalSearchServiceSyncProxy(
local_search_service::LocalSearchServiceSync* local_search_service)
: service_(local_search_service) {
DCHECK(service_);
}
LocalSearchServiceSyncProxy::~LocalSearchServiceSyncProxy() = default;
void LocalSearchServiceSyncProxy::GetIndex(
IndexId index_id,
Backend backend,
mojo::PendingReceiver<mojom::IndexSyncProxy> index_receiver) {
GetIndex(index_id, backend, nullptr, std::move(index_receiver));
}
void LocalSearchServiceSyncProxy::GetIndex(
IndexId index_id,
Backend backend,
PrefService* local_state,
mojo::PendingReceiver<mojom::IndexSyncProxy> index_receiver) {
auto it = indices_.find(index_id);
if (it == indices_.end()) {
IndexSync* index = service_->GetIndexSync(index_id, backend, local_state);
it = indices_.emplace(index_id, std::make_unique<IndexSyncProxy>(index))
.first;
}
it->second->BindReceiver(std::move(index_receiver));
}
void LocalSearchServiceSyncProxy::BindReceiver(
mojo::PendingReceiver<mojom::LocalSearchServiceSyncProxy> receiver) {
receivers_.Add(this, std::move(receiver));
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2020 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_H_
#include <map>
#include "chromeos/components/local_search_service/public/mojom/local_search_service_proxy.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
class PrefService;
namespace chromeos {
namespace local_search_service {
class LocalSearchServiceSync;
class IndexSyncProxy;
enum class IndexId;
enum class Backend;
class LocalSearchServiceSyncProxy : public mojom::LocalSearchServiceSyncProxy,
public KeyedService {
public:
explicit LocalSearchServiceSyncProxy(
LocalSearchServiceSync* local_search_service);
~LocalSearchServiceSyncProxy() override;
LocalSearchServiceSyncProxy(const LocalSearchServiceSyncProxy&) = delete;
LocalSearchServiceSyncProxy& operator=(const LocalSearchServiceSyncProxy) =
delete;
// mojom::LocalSearchServiceSyncProxy:
void GetIndex(
IndexId index_id,
Backend backend,
mojo::PendingReceiver<mojom::IndexSyncProxy> index_receiver) override;
void BindReceiver(
mojo::PendingReceiver<mojom::LocalSearchServiceSyncProxy> receiver);
// The version below allows an out-of-process client to directly obtain an
// Index using their own delegate that runs in C++.
// 1. Client's delegate obtains LocalSearchServicProxy from
// LocalSearchServiceSyncProxyFactory.
// 2. Client's delegate calls GetIndex to obtain an Index and binds the
// IndexSyncProxy remote
// to the IndexSyncProxy implementation.
void GetIndex(IndexId index_id,
Backend backend,
PrefService* local_state,
mojo::PendingReceiver<mojom::IndexSyncProxy> index_receiver);
private:
LocalSearchServiceSync* const service_;
mojo::ReceiverSet<mojom::LocalSearchServiceSyncProxy> receivers_;
std::map<IndexId, std::unique_ptr<IndexSyncProxy>> indices_;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_H_
// Copyright 2020 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 "chromeos/components/local_search_service/local_search_service_sync_proxy_factory.h"
#include "chromeos/components/local_search_service/local_search_service_sync_factory.h"
#include "chromeos/components/local_search_service/local_search_service_sync_proxy.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace chromeos {
namespace local_search_service {
// static
LocalSearchServiceSyncProxy*
LocalSearchServiceSyncProxyFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<LocalSearchServiceSyncProxy*>(
LocalSearchServiceSyncProxyFactory::GetInstance()
->GetServiceForBrowserContext(context, /*create=*/true));
}
// static
LocalSearchServiceSyncProxyFactory*
LocalSearchServiceSyncProxyFactory::GetInstance() {
static base::NoDestructor<LocalSearchServiceSyncProxyFactory> instance;
return instance.get();
}
LocalSearchServiceSyncProxyFactory::LocalSearchServiceSyncProxyFactory()
: BrowserContextKeyedServiceFactory(
"LocalSearchServiceSyncProxy",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(LocalSearchServiceSyncFactory::GetInstance());
}
LocalSearchServiceSyncProxyFactory::~LocalSearchServiceSyncProxyFactory() =
default;
content::BrowserContext*
LocalSearchServiceSyncProxyFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
// The service should exist in incognito mode.
return context;
}
KeyedService* LocalSearchServiceSyncProxyFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
DCHECK(context);
return new LocalSearchServiceSyncProxy(
LocalSearchServiceSyncFactory::GetForBrowserContext(context));
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2020 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_FACTORY_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_FACTORY_H_
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace chromeos {
namespace local_search_service {
class LocalSearchServiceSyncProxy;
class LocalSearchServiceSyncProxyFactory
: public BrowserContextKeyedServiceFactory {
public:
static LocalSearchServiceSyncProxy* GetForBrowserContext(
content::BrowserContext* context);
static LocalSearchServiceSyncProxyFactory* GetInstance();
LocalSearchServiceSyncProxyFactory(
const LocalSearchServiceSyncProxyFactory&) = delete;
LocalSearchServiceSyncProxyFactory& operator=(
const LocalSearchServiceSyncProxyFactory&) = delete;
private:
friend class base::NoDestructor<LocalSearchServiceSyncProxyFactory>;
LocalSearchServiceSyncProxyFactory();
~LocalSearchServiceSyncProxyFactory() override;
// BrowserContextKeyedServiceFactory:
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_LOCAL_SEARCH_SERVICE_SYNC_PROXY_FACTORY_H_
// Copyright 2020 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 "chromeos/components/local_search_service/local_search_service_sync_proxy.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "chromeos/components/local_search_service/index_sync_proxy.h"
#include "chromeos/components/local_search_service/local_search_service_sync.h"
#include "chromeos/components/local_search_service/public/mojom/types.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace local_search_service {
class LocalSearchServiceSyncProxyTest : public testing::Test {
public:
LocalSearchServiceSyncProxyTest() {
service_proxy_ = std::make_unique<LocalSearchServiceSyncProxy>(&service_);
service_proxy_->BindReceiver(service_remote_.BindNewPipeAndPassReceiver());
}
protected:
mojo::Remote<mojom::LocalSearchServiceSyncProxy> service_remote_;
private:
base::test::TaskEnvironment task_environment_;
LocalSearchServiceSync service_;
std::unique_ptr<LocalSearchServiceSyncProxy> service_proxy_;
};
TEST_F(LocalSearchServiceSyncProxyTest, GetIndex) {
mojo::Remote<mojom::IndexSyncProxy> index_remote;
service_remote_->GetIndex(IndexId::kCrosSettings, Backend::kLinearMap,
index_remote.BindNewPipeAndPassReceiver());
base::RunLoop().RunUntilIdle();
// Check that IndexRemote is bound.
bool callback_done = false;
uint64_t num_items;
index_remote->GetSize(base::BindOnce(
[](bool* callback_done, uint64_t* num_items, uint64_t size) {
*callback_done = true;
*num_items = size;
},
&callback_done, &num_items));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(callback_done);
EXPECT_EQ(num_items, 0U);
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2019 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 <map>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "base/test/task_environment.h"
#include "chromeos/components/local_search_service/index_sync.h"
#include "chromeos/components/local_search_service/local_search_service_sync.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace local_search_service {
class LocalSearchServiceSyncTest : public testing::Test {
protected:
LocalSearchServiceSync service_;
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::MainThreadType::DEFAULT,
base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED};
};
TEST_F(LocalSearchServiceSyncTest, GetLinearMapSearch) {
IndexSync* const index = service_.GetIndexSync(
IndexId::kCrosSettings, Backend::kLinearMap, nullptr /* local_state */);
CHECK(index);
EXPECT_EQ(index->GetSizeSync(), 0u);
}
TEST_F(LocalSearchServiceSyncTest, GetInvertedIndexSearch) {
IndexSync* const index =
service_.GetIndexSync(IndexId::kCrosSettings, Backend::kInvertedIndex,
nullptr /* local_state */);
CHECK(index);
EXPECT_EQ(index->GetSizeSync(), 0u);
}
} // namespace local_search_service
} // namespace chromeos
......@@ -8,7 +8,6 @@ mojom("mojom") {
sources = [
"index.mojom",
"local_search_service.mojom",
"local_search_service_proxy.mojom",
"types.mojom",
]
......
......@@ -6,7 +6,17 @@ module chromeos.local_search_service.mojom;
import "chromeos/components/local_search_service/public/mojom/index.mojom";
import "chromeos/components/local_search_service/public/mojom/types.mojom";
import "chromeos/components/local_search_service/public/mojom/local_search_service_proxy.mojom";
enum IndexId {
kCrosSettings = 0,
kHelpApp = 1
// Add new client IDs here.
};
enum Backend {
kLinearMap = 0,
kInvertedIndex = 1
};
// Interface that helps to log daily search requests to UMA.
interface SearchMetricsReporter {
......
// Copyright 2020 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.
module chromeos.local_search_service.mojom;
import "chromeos/components/local_search_service/public/mojom/types.mojom";
import "mojo/public/mojom/base/string16.mojom";
enum IndexId {
kCrosSettings = 0,
kHelpApp = 1
// Add new client IDs here.
};
enum Backend {
kLinearMap = 0,
kInvertedIndex = 1
};
// LocalSearchServiceSyncProxy creates and owns content-specific IndexProxies.
// Clients can call |GetIndex| to get an IndexSyncProxy for a given index id.
interface LocalSearchServiceSyncProxy {
// A client can call this function to bind an IndexSyncProxy for |index_id|.
// If the Index isn't created when this function is called, LocalSearchService
// will create one.
// Note, there should be one primary client that is the owner of the data and
// can read/write the data to the Index. The other clients should only use
// the Index for query search.
GetIndex(IndexId index_id, Backend backend,
pending_receiver<IndexSyncProxy> index_receiver);
};
// A proxy to a local search service Index.
// An Index has a registry of searchable data, which can be updated. It also
// runs a search function to find matching items for a given query.
// Each Index can serve multiple clients, but only one client (the primary
// client) that owns the data should be allowed to modify the Index.
interface IndexSyncProxy {
// Returns number of data items.
GetSize() => (uint64 num_items);
// Adds or updates data and callbacks upon completion.
// Only the primary client should be allowed to do this operation.
AddOrUpdate(array<Data> data) => ();
// Deletes data with |ids| and returns the number of items deleted.
// If an id doesn't exist in the Index, no operation will be done.
// Only the primary client should be allowed to do this operation.
Delete(array<string> ids) => (uint32 num_deleted);
// Takes an asynchronous search request call and returns results and status
// code via a callback. |results| will be null if there is an error.
Find(mojo_base.mojom.String16 query, uint32 max_results)
=> (ResponseStatus status, array<Result>? results);
// Clears all data stored by the index.
ClearIndex() => ();
};
......@@ -6,7 +6,7 @@
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_PUBLIC_MOJOM_TYPES_MOJOM_TRAITS_H_
#include "base/strings/string16.h"
#include "chromeos/components/local_search_service/public/mojom/local_search_service_proxy.mojom-shared.h"
#include "chromeos/components/local_search_service/public/mojom/local_search_service.mojom-shared.h"
#include "chromeos/components/local_search_service/public/mojom/types.mojom-shared.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
......
// Copyright 2020 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 "chromeos/components/local_search_service/search_metrics_reporter_sync.h"
#include "base/check_op.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "chromeos/components/local_search_service/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace local_search_service {
namespace {
// Interval for asking metrics::DailyEvent to check whether a day has passed.
constexpr base::TimeDelta kCheckDailyEventInternal =
base::TimeDelta::FromMinutes(30);
// Prefs corresponding to IndexId values.
constexpr std::array<const char*, SearchMetricsReporterSync::kNumberIndexIds>
kDailyCountPrefs = {
prefs::kLocalSearchServiceSyncMetricsCrosSettingsCount,
prefs::kLocalSearchServiceSyncMetricsHelpAppCount,
};
// Histograms corresponding to IndexId values.
constexpr std::array<const char*, SearchMetricsReporterSync::kNumberIndexIds>
kDailyCountHistograms = {
SearchMetricsReporterSync::kCrosSettingsName,
SearchMetricsReporterSync::kHelpAppName,
};
} // namespace
constexpr char SearchMetricsReporterSync::kDailyEventIntervalName[];
constexpr char SearchMetricsReporterSync::kCrosSettingsName[];
constexpr char SearchMetricsReporterSync::kHelpAppName[];
constexpr int SearchMetricsReporterSync::kNumberIndexIds;
// This class is needed since metrics::DailyEvent requires taking ownership
// of its observers. It just forwards events to SearchMetricsReporter.
class SearchMetricsReporterSync::DailyEventObserver
: public metrics::DailyEvent::Observer {
public:
explicit DailyEventObserver(SearchMetricsReporterSync* reporter)
: reporter_(reporter) {
DCHECK(reporter_);
}
~DailyEventObserver() override = default;
DailyEventObserver(const DailyEventObserver&) = delete;
DailyEventObserver& operator=(const DailyEventObserver&) = delete;
// metrics::DailyEvent::Observer:
void OnDailyEvent(metrics::DailyEvent::IntervalType type) override {
reporter_->ReportDailyMetrics(type);
}
private:
SearchMetricsReporterSync* reporter_; // Not owned.
};
// static:
void SearchMetricsReporterSync::RegisterLocalStatePrefs(
PrefRegistrySimple* registry) {
metrics::DailyEvent::RegisterPref(
registry, prefs::kLocalSearchServiceSyncMetricsDailySample);
for (const char* daily_count_pref : kDailyCountPrefs) {
registry->RegisterIntegerPref(daily_count_pref, 0);
}
}
SearchMetricsReporterSync::SearchMetricsReporterSync(
PrefService* local_state_pref_service)
: pref_service_(local_state_pref_service),
daily_event_(std::make_unique<metrics::DailyEvent>(
pref_service_,
prefs::kLocalSearchServiceSyncMetricsDailySample,
kDailyEventIntervalName)) {
for (size_t i = 0; i < kDailyCountPrefs.size(); ++i) {
daily_counts_[i] = pref_service_->GetInteger(kDailyCountPrefs[i]);
}
daily_event_->AddObserver(std::make_unique<DailyEventObserver>(this));
daily_event_->CheckInterval();
timer_.Start(FROM_HERE, kCheckDailyEventInternal, daily_event_.get(),
&metrics::DailyEvent::CheckInterval);
}
SearchMetricsReporterSync::~SearchMetricsReporterSync() = default;
void SearchMetricsReporterSync::SetIndexId(IndexId index_id) {
DCHECK(!index_id_);
index_id_ = index_id;
DCHECK_LT(static_cast<size_t>(index_id), kDailyCountPrefs.size());
}
void SearchMetricsReporterSync::OnSearchPerformed() {
DCHECK(index_id_);
const size_t index = static_cast<size_t>(*index_id_);
const char* daily_count_pref = kDailyCountPrefs[index];
++daily_counts_[index];
pref_service_->SetInteger(daily_count_pref, daily_counts_[index]);
}
void SearchMetricsReporterSync::ReportDailyMetricsForTesting(
metrics::DailyEvent::IntervalType type) {
ReportDailyMetrics(type);
}
void SearchMetricsReporterSync::ReportDailyMetrics(
metrics::DailyEvent::IntervalType type) {
if (!index_id_)
return;
// Don't send metrics on first run or if the clock is changed.
if (type == metrics::DailyEvent::IntervalType::DAY_ELAPSED) {
const size_t index = static_cast<size_t>(*index_id_);
base::UmaHistogramCounts1000(kDailyCountHistograms[index],
daily_counts_[index]);
}
for (size_t i = 0; i < kDailyCountPrefs.size(); ++i) {
daily_counts_[i] = 0;
pref_service_->SetInteger(kDailyCountPrefs[i], 0);
}
}
} // namespace local_search_service
} // namespace chromeos
// Copyright 2020 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 CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_SEARCH_METRICS_REPORTER_SYNC_H_
#define CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_SEARCH_METRICS_REPORTER_SYNC_H_
#include <array>
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "components/metrics/daily_event.h"
class PrefRegistrySimple;
class PrefService;
namespace chromeos {
namespace local_search_service {
// SearchMetricsReporter logs daily search requests to UMA.
class SearchMetricsReporterSync {
public:
static constexpr int kNumberIndexIds =
static_cast<int>(IndexId::kMaxValue) + 1;
// A histogram recorded in UMA, showing reasons why daily metrics are
// reported.
static constexpr char kDailyEventIntervalName[] =
"LocalSearchService.MetricsDailyEventInterval";
// Histogram names of daily counts, one for each IndexId.
static constexpr char kCrosSettingsName[] =
"LocalSearchService.CrosSettings.DailySearch";
static constexpr char kHelpAppName[] =
"LocalSearchService.HelpApp.DailySearch";
// Registers prefs used by SearchMetricsReporter in |registry|.
static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
// RegisterLocalStatePrefs() must be called before instantiating this class.
explicit SearchMetricsReporterSync(PrefService* local_state_pref_service);
~SearchMetricsReporterSync();
SearchMetricsReporterSync(const SearchMetricsReporterSync&) = delete;
SearchMetricsReporterSync& operator=(const SearchMetricsReporterSync&) =
delete;
// Sets |index_id_|.
void SetIndexId(IndexId index_id);
// Increments number of searches for |index_id_|. Should only
// be called after |SetIndexId| is called.
void OnSearchPerformed();
// Calls ReportDailyMetrics directly.
void ReportDailyMetricsForTesting(metrics::DailyEvent::IntervalType type);
private:
class DailyEventObserver;
// Called by DailyEventObserver whenever a day has elapsed according to
// |daily_event_|.
void ReportDailyMetrics(metrics::DailyEvent::IntervalType type);
// Used as an index into |daily_counts_| for counting searches.
base::Optional<IndexId> index_id_;
PrefService* pref_service_; // Not owned.
std::unique_ptr<metrics::DailyEvent> daily_event_;
// Instructs |daily_event_| to check if a day has passed.
base::RepeatingTimer timer_;
// Daily count for each index id. Ordered by IndexId values.
// Initial values will be loaded from prefs service.
std::array<int, kNumberIndexIds> daily_counts_;
};
} // namespace local_search_service
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_LOCAL_SEARCH_SERVICE_SEARCH_METRICS_REPORTER_SYNC_H_
// Copyright 2020 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 "chromeos/components/local_search_service/search_metrics_reporter_sync.h"
#include <memory>
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "chromeos/components/local_search_service/pref_names.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "components/metrics/daily_event.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace local_search_service {
class SearchMetricsReporterSyncTest : public testing::Test {
public:
SearchMetricsReporterSyncTest() = default;
~SearchMetricsReporterSyncTest() override = default;
void SetUp() override {
SearchMetricsReporterSync::RegisterLocalStatePrefs(
pref_service_.registry());
}
void TearDown() override { reporter_.reset(); }
protected:
void SetReporter(IndexId index_id) {
reporter_ = std::make_unique<SearchMetricsReporterSync>(&pref_service_);
reporter_->SetIndexId(index_id);
}
// Notifies |reporter_| that a search is performed.
void SendOnSearchPerformed() { reporter_->OnSearchPerformed(); }
// Instructs |reporter_| to report daily metrics for reason |type|.
void TriggerDailyEvent(metrics::DailyEvent::IntervalType type) {
reporter_->ReportDailyMetricsForTesting(type);
}
// Instructs |reporter_| to report daily metrics due to the passage of a day
// and verifies that it reports one sample with each of the passed values.
void TriggerDailyEventAndVerifyHistograms(const std::string& histogram_name,
int expected_count) {
base::HistogramTester histogram_tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::DAY_ELAPSED);
histogram_tester.ExpectUniqueSample(histogram_name, expected_count, 1);
}
base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<SearchMetricsReporterSync> reporter_;
};
TEST_F(SearchMetricsReporterSyncTest, CountAndReportEvents) {
SetReporter(IndexId::kCrosSettings);
SendOnSearchPerformed();
SendOnSearchPerformed();
SendOnSearchPerformed();
TriggerDailyEventAndVerifyHistograms(
SearchMetricsReporterSync::kCrosSettingsName, 3);
// The next day, another two searches.
SendOnSearchPerformed();
SendOnSearchPerformed();
TriggerDailyEventAndVerifyHistograms(
SearchMetricsReporterSync::kCrosSettingsName, 2);
}
TEST_F(SearchMetricsReporterSyncTest, LoadInitialCountsFromPrefs) {
// Create a new reporter and check that it loads its initial event counts from
// prefs.
pref_service_.SetInteger(
prefs::kLocalSearchServiceSyncMetricsCrosSettingsCount, 2);
SetReporter(IndexId::kCrosSettings);
TriggerDailyEventAndVerifyHistograms(
SearchMetricsReporterSync::kCrosSettingsName, 2);
// The previous report should've cleared the prefs, so a new reporter should
// start out at zero.
TriggerDailyEventAndVerifyHistograms(
SearchMetricsReporterSync::kCrosSettingsName, 0);
}
TEST_F(SearchMetricsReporterSyncTest, IgnoreDailyEventFirstRun) {
SetReporter(IndexId::kCrosSettings);
// metrics::DailyEvent notifies observers immediately on first run. Histograms
// shouldn't be sent in this case.
base::HistogramTester tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::FIRST_RUN);
tester.ExpectTotalCount(SearchMetricsReporterSync::kCrosSettingsName, 0);
}
TEST_F(SearchMetricsReporterSyncTest, IgnoreDailyEventClockChanged) {
SetReporter(IndexId::kCrosSettings);
SendOnSearchPerformed();
// metrics::DailyEvent notifies observers if it sees that the system clock has
// jumped back. Histograms shouldn't be sent in this case.
base::HistogramTester tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::CLOCK_CHANGED);
tester.ExpectTotalCount(SearchMetricsReporterSync::kCrosSettingsName, 0);
// The existing stats should be cleared when the clock change notification is
// received, so the next report should only contain zeros.
TriggerDailyEventAndVerifyHistograms(
SearchMetricsReporterSync::kCrosSettingsName, 0);
}
} // namespace local_search_service
} // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment