1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_TAG_REGISTRY_H_
6 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_TAG_REGISTRY_H_
7 
8 #include <unordered_map>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/gtest_prod_util.h"
13 #include "base/observer_list.h"
14 #include "base/observer_list_types.h"
15 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h"
16 #include "chromeos/components/local_search_service/index_sync.h"
17 
18 namespace chromeos {
19 
20 namespace local_search_service {
21 class IndexSync;
22 class LocalSearchServiceSync;
23 }  // namespace local_search_service
24 
25 namespace settings {
26 
27 struct SearchConcept;
28 
29 // Processes all registered search tags by adding/removing them from
30 // LocalSearchServiceSync and providing metadata via GetTagMetadata().
31 class SearchTagRegistry {
32  public:
33   class Observer : public base::CheckedObserver {
34    public:
35     ~Observer() override = default;
36     virtual void OnRegistryUpdated() = 0;
37   };
38 
39   class ScopedTagUpdater {
40    public:
41     ScopedTagUpdater(ScopedTagUpdater&&);
42     ScopedTagUpdater(const ScopedTagUpdater&) = delete;
43     ScopedTagUpdater& operator=(const ScopedTagUpdater&) = delete;
44     ~ScopedTagUpdater();
45 
46     void AddSearchTags(const std::vector<SearchConcept>& search_tags);
47     void RemoveSearchTags(const std::vector<SearchConcept>& search_tags);
48 
49    private:
50     friend class SearchTagRegistry;
51 
52     explicit ScopedTagUpdater(SearchTagRegistry* registry);
53 
54     void ProcessPendingSearchTags(const std::vector<SearchConcept>& search_tags,
55                                   bool is_pending_add);
56 
57     SearchTagRegistry* registry_;
58 
59     // A SearchConcept along with a bool of the pending update state. If the
60     // bool is true, the concept should be added; if the bool is false, the
61     // concept should be removed.
62     using ConceptWithShouldAddBool = std::pair<const SearchConcept*, bool>;
63     std::unordered_map<std::string, ConceptWithShouldAddBool> pending_updates_;
64   };
65 
66   SearchTagRegistry(
67       local_search_service::LocalSearchServiceSync* local_search_service);
68   SearchTagRegistry(const SearchTagRegistry& other) = delete;
69   SearchTagRegistry& operator=(const SearchTagRegistry& other) = delete;
70   virtual ~SearchTagRegistry();
71 
72   void AddObserver(Observer* observer);
73   void RemoveObserver(Observer* observer);
74 
75   // Starts a tag update, which allows clients to add/remove search tags. The
76   // ScopedTagUpdater object is returned by value and only updates tags when it
77   // goes out of scope, so clients should not hold onto it outside the scope of
78   // a function.
79   ScopedTagUpdater StartUpdate();
80 
81   // Returns the tag metadata associated with |result_id|, which is the ID
82   // returned by the LocalSearchServiceSync. If no metadata is available, null
83   // is returned.
84   const SearchConcept* GetTagMetadata(const std::string& result_id) const;
85  private:
86   FRIEND_TEST_ALL_PREFIXES(SearchTagRegistryTest, AddAndRemove);
87 
88   static std::string ToResultId(const SearchConcept& concept);
89 
90   void AddSearchTags(const std::vector<const SearchConcept*>& search_tags);
91   void RemoveSearchTags(const std::vector<const SearchConcept*>& search_tags);
92 
93   std::vector<local_search_service::Data> ConceptVectorToDataVector(
94       const std::vector<const SearchConcept*>& search_tags);
95   void NotifyRegistryUpdated();
96 
97   // Index used by the LocalSearchServiceSync for string matching.
98   local_search_service::IndexSync* index_;
99 
100   // In-memory cache of all results which have been added to the
101   // LocalSearchServiceSync. Contents are kept in sync with |index_|.
102   std::unordered_map<std::string, const SearchConcept*>
103       result_id_to_metadata_list_map_;
104 
105   base::ObserverList<Observer> observer_list_;
106 };
107 
108 }  // namespace settings
109 }  // namespace chromeos
110 
111 #endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_TAG_REGISTRY_H_
112