File: enterprise_search_manager.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (223 lines) | stat: -rw-r--r-- 8,928 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/search_engines/enterprise/enterprise_search_manager.h"

#include <memory>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/values.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_value_map.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/search_engines/default_search_manager.h"
#include "components/search_engines/template_url_data.h"
#include "components/search_engines/template_url_data_util.h"

namespace {

std::unique_ptr<TemplateURLData> DictToTemplateURLData(
    const base::Value& engine) {
  const base::Value::Dict& url_dict = engine.GetDict();
  std::unique_ptr<TemplateURLData> turl_data =
      TemplateURLDataFromDictionary(url_dict);
  CHECK(turl_data);
  return turl_data;
}

}  // namespace

// A dictionary to hold all data related to the site search engines defined by
// policy.
const char EnterpriseSearchManager::kSiteSearchSettingsPrefName[] =
    "site_search_settings.template_url_data";
// A list to hold the keywords of site search engines which the user
// has overridden.
const char
    EnterpriseSearchManager::kSiteSearchSettingsOverriddenKeywordsPrefName[] =
        "site_search_settings.overridden_keywords";

// A dictionary to hold all TemplateURL data related to the enterprise search
// aggregator defined by policy.
const char
    EnterpriseSearchManager::kEnterpriseSearchAggregatorSettingsPrefName[] =
        "enterprise_search_aggregator_settings.template_url_data";
// A boolean to hold whether a shortcut is required for the enterprise search
// aggregator.
const char EnterpriseSearchManager::
    kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName[] =
        "enterprise_search_aggregator_settings.require_shortcut";

EnterpriseSearchManager::EnterpriseSearchManager(
    PrefService* pref_service,
    const ObserverCallback& change_observer)
    : pref_service_(pref_service), change_observer_(change_observer) {
  if (pref_service_) {
    pref_change_registrar_.Init(pref_service_);
    pref_change_registrar_.Add(
        kSiteSearchSettingsPrefName,
        base::BindRepeating(&EnterpriseSearchManager::OnPrefChanged,
                            base::Unretained(this)));
    if (base::FeatureList::IsEnabled(omnibox::kEnableSearchAggregatorPolicy)) {
      pref_change_registrar_.Add(
          kEnterpriseSearchAggregatorSettingsPrefName,
          base::BindRepeating(&EnterpriseSearchManager::OnPrefChanged,
                              base::Unretained(this)));
    }
    OnPrefChanged();
  }
}

EnterpriseSearchManager::~EnterpriseSearchManager() = default;

// static
void EnterpriseSearchManager::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterListPref(kSiteSearchSettingsPrefName);
  registry->RegisterListPref(kSiteSearchSettingsOverriddenKeywordsPrefName);
  registry->RegisterListPref(kEnterpriseSearchAggregatorSettingsPrefName);
  registry->RegisterBooleanPref(
      kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName, false);
}

bool EnterpriseSearchManager::GetRequireShortcutValue() const {
  // Prefer mock `require_shortcut` over `require_shortcut` from pref.
  // TODO(crbug.com/402175538): Remove the ability to override pref engines via
  // feature.
  if (!omnibox_feature_configs::SearchAggregatorProvider::Get()
           .AreMockEnginesValid()) {
    // Use the `require_shortcut` preference value if set by policy.
    const PrefService::Preference* pref = pref_service_->FindPreference(
        kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName);
    return pref && pref->GetValue()->GetBool();
  }

  return omnibox_feature_configs::SearchAggregatorProvider::Get()
      .require_shortcut;
}

void EnterpriseSearchManager::OnPrefChanged() {
  if (!change_observer_) {
    return;
  }

  EnterpriseSearchManager::OwnedTemplateURLDataVector search_engines;
  LoadingResult site_search_loading_result = LoadSearchEnginesFromPrefs(
      pref_service_->FindPreference(kSiteSearchSettingsPrefName),
      &search_engines);
  LoadingResult search_aggregator_loading_result =
      LoadSearchAggregator(&search_engines);
  if (site_search_loading_result != LoadingResult::kUnavailable ||
      search_aggregator_loading_result != LoadingResult::kUnavailable) {
    change_observer_.Run(std::move(search_engines));
  }
}

// Adds the search providers read from `pref` to `search_engines`. Returns true
// if `pref` exists and is managed.
EnterpriseSearchManager::LoadingResult
EnterpriseSearchManager::LoadSearchEnginesFromPrefs(
    const PrefService::Preference* pref,
    EnterpriseSearchManager::OwnedTemplateURLDataVector* search_engines) {
  // Only accept site search engine created by policy.
  if (!pref || !pref->IsManaged()) {
    return LoadingResult::kUnavailable;
  }

  // Get the list of engines from the main policy pref.
  const base::Value::List& engine_list = pref->GetValue()->GetList();
  // For site search engines, load the
  // `kSiteSearchSettingsOverriddenKeywordsPrefName` pref dictionary.
  if (base::FeatureList::IsEnabled(
          omnibox::kEnableSiteSearchAllowUserOverridePolicy) &&
      pref->name() == kSiteSearchSettingsPrefName) {
    LoadOverriddenKeywordsPref(engine_list);
  }

  LoadingResult result = LoadingResult::kAvailableEmpty;
  for (const base::Value& engine : engine_list) {
    const base::Value::Dict& engine_dict = engine.GetDict();
    const std::string* keyword =
        engine_dict.FindString(DefaultSearchManager::kKeyword);
    CHECK(keyword);
    if (base::FeatureList::IsEnabled(
            omnibox::kEnableSiteSearchAllowUserOverridePolicy) &&
        pref_service_
            ->GetList(EnterpriseSearchManager::
                          kSiteSearchSettingsOverriddenKeywordsPrefName)
            .contains(*keyword)) {
      continue;
    }
    search_engines->emplace_back(DictToTemplateURLData(engine));
    result = LoadingResult::kAvailableNonEmpty;
  }
  return result;
}

EnterpriseSearchManager::LoadingResult
EnterpriseSearchManager::LoadSearchAggregator(
    EnterpriseSearchManager::OwnedTemplateURLDataVector* search_engines) {
  // Prefer mock engines over engines from pref.
  // TODO(crbug.com/402175538): Remove the ability to override pref engines via
  // feature.
  if (!omnibox_feature_configs::SearchAggregatorProvider::Get()
           .AreMockEnginesValid()) {
    return LoadSearchEnginesFromPrefs(
        pref_service_->FindPreference(
            kEnterpriseSearchAggregatorSettingsPrefName),
        search_engines);
  }

  // NOTE: This function assumes that `search_engines` does not contain any
  // engines that should be overridden by the feature config.
  std::ranges::transform(
      omnibox_feature_configs::SearchAggregatorProvider::Get()
          .CreateMockSearchEngines(),
      std::back_inserter(*search_engines), [](const base::Value& mock_engine) {
        return DictToTemplateURLData(mock_engine);
      });
  return LoadingResult::kAvailableNonEmpty;
}

void EnterpriseSearchManager::LoadOverriddenKeywordsPref(
    const base::Value::List& engine_list) {
  ScopedListPrefUpdate overridden_keywords_update(
      pref_service_, kSiteSearchSettingsOverriddenKeywordsPrefName);
  base::Value::List& overridden_keywords_list =
      overridden_keywords_update.Get();

  // Keep track of keywords present in the current policy along with whether
  // they are enforced by policy.
  base::flat_map<std::string, bool> policy_keywords_enforced_status;
  for (const base::Value& engine : engine_list) {
    const base::Value::Dict& engine_dict = engine.GetDict();
    const std::string* keyword =
        engine_dict.FindString(DefaultSearchManager::kKeyword);
    CHECK(keyword);
    bool enforced_by_policy =
        engine_dict.FindBool(DefaultSearchManager::kEnforcedByPolicy)
            .value_or(false);
    policy_keywords_enforced_status[*keyword] = enforced_by_policy;
  }

  // Remove keywords from the overridden keywords list for engines that are no
  // longer present in the policy or that are NOW enforced.
  overridden_keywords_list.EraseIf(
      [&policy_keywords_enforced_status](const base::Value& v) {
        auto it = policy_keywords_enforced_status.find(v.GetString());
        return it == policy_keywords_enforced_status.end() || it->second;
      });
}

void EnterpriseSearchManager::AddOverriddenKeyword(const std::string& keyword) {
  if (!pref_service_) {
    return;
  }
  ScopedListPrefUpdate overridden_keywords_update(
      pref_service_, kSiteSearchSettingsOverriddenKeywordsPrefName);
  overridden_keywords_update.Get().Append(keyword);
}