Avi Drissman | 8ba1bad | 2022-09-13 19:22:36 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
hashimoto@chromium.org | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 5 | #include "components/search_engines/template_url_service.h" |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 6 | |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 7 | #include <algorithm> |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 8 | #include <iterator> |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 9 | #include <memory> |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 10 | #include <string> |
| 11 | #include <utility> |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 12 | |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 13 | #include "base/auto_reset.h" |
manukh | 87303639 | 2020-11-09 17:23:29 | [diff] [blame] | 14 | #include "base/base64.h" |
| 15 | #include "base/base64url.h" |
Nicolas Dossou-Gbete | 0cd7f0c1 | 2024-01-02 14:37:08 | [diff] [blame] | 16 | #include "base/check_deref.h" |
Jack Yammine | f973df62 | 2023-09-05 14:57:11 | [diff] [blame] | 17 | #include "base/check_is_test.h" |
Jan Wilken Dörrie | 986f0a6 | 2020-12-09 23:29:12 | [diff] [blame] | 18 | #include "base/containers/contains.h" |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 19 | #include "base/containers/flat_map.h" |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 20 | #include "base/debug/crash_logging.h" |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 21 | #include "base/feature_list.h" |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 22 | #include "base/format_macros.h" |
Avi Drissman | 12be031 | 2023-01-11 09:16:09 | [diff] [blame] | 23 | #include "base/functional/bind.h" |
| 24 | #include "base/functional/callback.h" |
| 25 | #include "base/functional/callback_helpers.h" |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 26 | #include "base/i18n/case_conversion.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 27 | #include "base/memory/raw_ptr.h" |
Yash Joshi | d3da59f0 | 2023-03-23 22:24:48 | [diff] [blame] | 28 | #include "base/metrics/field_trial_params.h" |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 29 | #include "base/metrics/histogram_functions.h" |
asvitkine | a0f05db | 2015-06-16 21:45:46 | [diff] [blame] | 30 | #include "base/metrics/histogram_macros.h" |
David Sanders | 88b2443 | 2022-02-28 01:10:02 | [diff] [blame] | 31 | #include "base/observer_list.h" |
manukh | 87303639 | 2020-11-09 17:23:29 | [diff] [blame] | 32 | #include "base/rand_util.h" |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 33 | #include "base/ranges/algorithm.h" |
tfarina@chromium.org | 1988e1c | 2013-02-28 20:27:42 | [diff] [blame] | 34 | #include "base/strings/string_split.h" |
Hans Wennborg | b3e433a | 2020-04-21 11:21:40 | [diff] [blame] | 35 | #include "base/strings/string_util.h" |
avi@chromium.org | e309f31 | 2013-06-07 21:50:08 | [diff] [blame] | 36 | #include "base/strings/utf_string_conversions.h" |
Xiaohan Wang | cff600f | 2022-01-14 14:55:33 | [diff] [blame] | 37 | #include "build/build_config.h" |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 38 | #include "build/chromeos_buildflags.h" |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 39 | #include "components/omnibox/common/omnibox_features.h" |
sdefresne | 2948796 | 2015-07-03 09:24:39 | [diff] [blame] | 40 | #include "components/pref_registry/pref_registry_syncable.h" |
brettw | f00b9b4 | 2016-02-01 22:11:38 | [diff] [blame] | 41 | #include "components/prefs/pref_service.h" |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 42 | #include "components/search_engines/choice_made_location.h" |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 43 | #include "components/search_engines/enterprise_site_search_manager.h" |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 44 | #include "components/search_engines/keyword_web_data_service.h" |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 45 | #include "components/search_engines/search_engine_choice/search_engine_choice_service.h" |
Nicolas Dossou-Gbete | 9b7cf4bc | 2024-04-12 13:10:04 | [diff] [blame^] | 46 | #include "components/search_engines/search_engine_choice/search_engine_choice_utils.h" |
Fabio Tirelo | b8f4349 | 2023-07-18 20:28:24 | [diff] [blame] | 47 | #include "components/search_engines/search_engine_type.h" |
hashimoto@chromium.org | 2d3e710 | 2014-06-21 05:57:17 | [diff] [blame] | 48 | #include "components/search_engines/search_engines_pref_names.h" |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 49 | #include "components/search_engines/search_terms_data.h" |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 50 | #include "components/search_engines/template_url.h" |
| 51 | #include "components/search_engines/template_url_data.h" |
hashimoto@chromium.org | 0915b35 | 2014-06-25 19:58:14 | [diff] [blame] | 52 | #include "components/search_engines/template_url_prepopulate_data.h" |
hashimoto@chromium.org | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 53 | #include "components/search_engines/template_url_service_client.h" |
| 54 | #include "components/search_engines/template_url_service_observer.h" |
Angela Yoeurng | 54419ec6 | 2022-06-07 18:00:01 | [diff] [blame] | 55 | #include "components/search_engines/template_url_starter_pack_data.h" |
hashimoto@chromium.org | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 56 | #include "components/search_engines/util.h" |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 57 | #include "components/sync/model/sync_change.h" |
Mikel Astiz | ed5d9496 | 2018-09-27 13:42:24 | [diff] [blame] | 58 | #include "components/sync/model/sync_change_processor.h" |
Victor Hugo Vianna Silva | e92e300 | 2021-07-26 14:38:50 | [diff] [blame] | 59 | #include "components/sync/protocol/entity_specifics.pb.h" |
Max Bogue | fef332d | 2016-07-28 22:09:09 | [diff] [blame] | 60 | #include "components/sync/protocol/search_engine_specifics.pb.h" |
rsleevi | 24f64dc2 | 2015-08-07 21:39:21 | [diff] [blame] | 61 | #include "components/url_formatter/url_fixer.h" |
hashimoto@chromium.org | 67a832b | 2014-06-28 20:45:00 | [diff] [blame] | 62 | #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
erikwright@chromium.org | 8f1f8ac | 2014-05-11 23:23:05 | [diff] [blame] | 63 | #include "url/gurl.h" |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 64 | |
Xiaohan Wang | cff600f | 2022-01-14 14:55:33 | [diff] [blame] | 65 | #if BUILDFLAG(IS_ANDROID) |
Peter Wen | f517f7d | 2019-06-13 15:28:27 | [diff] [blame] | 66 | #include "components/search_engines/android/template_url_service_android.h" |
| 67 | #endif |
| 68 | |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 69 | typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 70 | typedef TemplateURLService::SyncDataMap SyncDataMap; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 71 | |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 72 | namespace { |
| 73 | |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 74 | const char kDeleteSyncedEngineHistogramName[] = |
| 75 | "Search.DeleteSyncedSearchEngine"; |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 76 | // TODO(yoangela): Consider sharing this const with |
| 77 | // "Omnibox.KeywordModeUsageByEngineType.Accepted" in omnibox_edit_model.cc. |
| 78 | const char kKeywordModeUsageByEngineTypeHistogramName[] = |
| 79 | "Omnibox.KeywordModeUsageByEngineType"; |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 80 | |
| 81 | // Values for an enumerated histogram used to track whenever an ACTION_DELETE is |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 82 | // sent to the server for search engines. These are persisted. Do not re-number. |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 83 | enum DeleteSyncedSearchEngineEvent { |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 84 | DELETE_ENGINE_USER_ACTION = 0, |
| 85 | DELETE_ENGINE_PRE_SYNC = 1, |
| 86 | DELETE_ENGINE_EMPTY_FIELD = 2, |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 87 | DELETE_ENGINE_MAX, |
| 88 | }; |
| 89 | |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 90 | // Returns true iff the change in |change_list| at index |i| should not be sent |
| 91 | // up to the server based on its GUIDs presence in |sync_data| or when compared |
| 92 | // to changes after it in |change_list|. |
| 93 | // The criteria is: |
| 94 | // 1) It is an ACTION_UPDATE or ACTION_DELETE and the sync_guid associated |
| 95 | // with it is NOT found in |sync_data|. We can only update and remove |
| 96 | // entries that were originally from the Sync server. |
| 97 | // 2) It is an ACTION_ADD and the sync_guid associated with it is found in |
| 98 | // |sync_data|. We cannot re-add entries that Sync already knew about. |
| 99 | // 3) There is an update after an update for the same GUID. We prune earlier |
| 100 | // ones just to save bandwidth (Sync would normally coalesce them). |
| 101 | bool ShouldRemoveSyncChange(size_t index, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 102 | syncer::SyncChangeList* change_list, |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 103 | const SyncDataMap* sync_data) { |
| 104 | DCHECK(index < change_list->size()); |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 105 | const syncer::SyncChange& change_i = (*change_list)[index]; |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 106 | const std::string guid = change_i.sync_data().GetSpecifics() |
| 107 | .search_engine().sync_guid(); |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 108 | syncer::SyncChange::SyncChangeType type = change_i.change_type(); |
| 109 | if ((type == syncer::SyncChange::ACTION_UPDATE || |
| 110 | type == syncer::SyncChange::ACTION_DELETE) && |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 111 | sync_data->find(guid) == sync_data->end()) |
| 112 | return true; |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 113 | if (type == syncer::SyncChange::ACTION_ADD && |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 114 | sync_data->find(guid) != sync_data->end()) |
| 115 | return true; |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 116 | if (type == syncer::SyncChange::ACTION_UPDATE) { |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 117 | for (size_t j = index + 1; j < change_list->size(); j++) { |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 118 | const syncer::SyncChange& change_j = (*change_list)[j]; |
| 119 | if ((syncer::SyncChange::ACTION_UPDATE == change_j.change_type()) && |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 120 | (change_j.sync_data().GetSpecifics().search_engine().sync_guid() == |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 121 | guid)) |
| 122 | return true; |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 123 | } |
| 124 | } |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 125 | return false; |
| 126 | } |
| 127 | |
| 128 | // Remove SyncChanges that should not be sent to the server from |change_list|. |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 129 | // This is done to eliminate incorrect SyncChanges added by the merge and |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 130 | // conflict resolution logic when it is unsure of whether or not an entry is new |
| 131 | // from Sync or originally from the local model. This also removes changes that |
| 132 | // would be otherwise be coalesced by Sync in order to save bandwidth. |
| 133 | void PruneSyncChanges(const SyncDataMap* sync_data, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 134 | syncer::SyncChangeList* change_list) { |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 135 | for (size_t i = 0; i < change_list->size(); ) { |
| 136 | if (ShouldRemoveSyncChange(i, change_list, sync_data)) |
| 137 | change_list->erase(change_list->begin() + i); |
| 138 | else |
| 139 | ++i; |
| 140 | } |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 141 | } |
| 142 | |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 143 | // Returns true if |turl|'s GUID is not found inside |sync_data|. This is to be |
| 144 | // used in MergeDataAndStartSyncing to differentiate between TemplateURLs from |
| 145 | // Sync and TemplateURLs that were initially local, assuming |sync_data| is the |
| 146 | // |initial_sync_data| parameter. |
| 147 | bool IsFromSync(const TemplateURL* turl, const SyncDataMap& sync_data) { |
Jan Wilken Dörrie | 45d34f4 | 2019-06-08 09:40:54 | [diff] [blame] | 148 | return base::Contains(sync_data, turl->sync_guid()); |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 149 | } |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 150 | |
stevet@chromium.org | 78a857c | 2012-08-21 20:31:48 | [diff] [blame] | 151 | // Log the number of instances of a keyword that exist, with zero or more |
| 152 | // underscores, which could occur as the result of conflict resolution. |
| 153 | void LogDuplicatesHistogram( |
| 154 | const TemplateURLService::TemplateURLVector& template_urls) { |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 155 | std::map<std::u16string, int> duplicates; |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 156 | for (auto it = template_urls.begin(); it != template_urls.end(); ++it) { |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 157 | std::u16string keyword = (*it)->keyword(); |
Jan Wilken Dörrie | 756999e | 2021-03-23 15:05:24 | [diff] [blame] | 158 | base::TrimString(keyword, u"_", &keyword); |
stevet@chromium.org | 78a857c | 2012-08-21 20:31:48 | [diff] [blame] | 159 | duplicates[keyword]++; |
| 160 | } |
| 161 | |
| 162 | // Count the keywords with duplicates. |
| 163 | int num_dupes = 0; |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 164 | for (std::map<std::u16string, int>::const_iterator it = duplicates.begin(); |
pnoland | 122369ab | 2016-05-31 18:43:31 | [diff] [blame] | 165 | it != duplicates.end(); ++it) { |
stevet@chromium.org | 78a857c | 2012-08-21 20:31:48 | [diff] [blame] | 166 | if (it->second > 1) |
| 167 | num_dupes++; |
| 168 | } |
| 169 | |
| 170 | UMA_HISTOGRAM_COUNTS_100("Search.SearchEngineDuplicateCounts", num_dupes); |
| 171 | } |
| 172 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 173 | bool Contains(TemplateURLService::OwnedTemplateURLVector* template_urls, |
Kevin Bailey | 499298a | 2018-03-16 14:54:43 | [diff] [blame] | 174 | const TemplateURL* turl) { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 175 | return FindTemplateURL(template_urls, turl) != template_urls->end(); |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 176 | } |
| 177 | |
a-v-y | f4eb435 | 2017-02-25 18:46:59 | [diff] [blame] | 178 | bool IsCreatedByExtension(const TemplateURL* template_url) { |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 179 | return template_url->type() == |
| 180 | TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION || |
| 181 | template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION; |
| 182 | } |
| 183 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 184 | // Checks if `new_values` has updated versions of `existing_turl`. Only fields |
| 185 | // set by the `SiteSearchSettings` policy are checked. |
| 186 | bool ShouldMergeEnterpriseSiteSearchEngines(const TemplateURL& existing_turl, |
| 187 | const TemplateURL& new_values) { |
| 188 | CHECK_EQ(existing_turl.keyword(), new_values.keyword()); |
| 189 | |
| 190 | return existing_turl.short_name() != new_values.short_name() || |
| 191 | existing_turl.url() != new_values.url() || |
| 192 | existing_turl.featured_by_policy() != new_values.featured_by_policy(); |
| 193 | } |
| 194 | |
| 195 | // Creates a new `TemplateURL` that copies updates fields from `new_values` into |
| 196 | // `existing_turl`. Only fields set by the `SiteSearchSettings` policy are |
| 197 | // copied from `new_values`, all other fields are copied unchanged from |
| 198 | // `existing_turl`. |
| 199 | TemplateURL MergeEnterpriseSiteSearchEngines(const TemplateURL& existing_turl, |
| 200 | const TemplateURL& new_values) { |
| 201 | CHECK_EQ(existing_turl.keyword(), new_values.keyword()); |
| 202 | |
| 203 | TemplateURLData merged_data(existing_turl.data()); |
| 204 | merged_data.SetShortName(new_values.short_name()); |
| 205 | merged_data.SetURL(new_values.url()); |
| 206 | merged_data.featured_by_policy = new_values.featured_by_policy(); |
| 207 | return TemplateURL(merged_data); |
| 208 | } |
| 209 | |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 210 | } // namespace |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 211 | |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 212 | // TemplateURLService::LessWithPrefix ----------------------------------------- |
| 213 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 214 | class TemplateURLService::LessWithPrefix { |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 215 | public: |
| 216 | // We want to find the set of keywords that begin with a prefix. The STL |
| 217 | // algorithms will return the set of elements that are "equal to" the |
| 218 | // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))". When |
| 219 | // cmp() is the typical std::less<>, this results in lexicographic equality; |
| 220 | // we need to extend this to mark a prefix as "not less than" a keyword it |
| 221 | // begins, which will cause the desired elements to be considered "equal to" |
| 222 | // the prefix. Note: this is still a strict weak ordering, as required by |
| 223 | // equal_range() (though I will not prove that here). |
| 224 | // |
| 225 | // Unfortunately the calling convention is not "prefix and element" but |
| 226 | // rather "two elements", so we pass the prefix as a fake "element" which has |
| 227 | // a NULL KeywordDataElement pointer. |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 228 | bool operator()(const KeywordToTURL::value_type& elem1, |
| 229 | const KeywordToTURL::value_type& elem2) const { |
| 230 | return (elem1.second == nullptr) |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 231 | ? (elem2.first.compare(0, elem1.first.length(), elem1.first) > 0) |
| 232 | : (elem1.first < elem2.first); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 233 | } |
| 234 | }; |
| 235 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 236 | // TemplateURLService::Scoper ------------------------------------------------- |
| 237 | |
| 238 | class TemplateURLService::Scoper { |
| 239 | public: |
| 240 | // Keep one of these handles in scope to coalesce all the notifications into a |
| 241 | // single notification. Likewise, BatchModeScoper defers web data service |
| 242 | // operations into a batch operation. |
| 243 | // |
| 244 | // Notifications are sent when the last outstanding handle is destroyed and |
| 245 | // |model_mutated_notification_pending_| is true. |
| 246 | // |
| 247 | // The web data service batch operation is performed when the batch mode level |
| 248 | // is 0 and more than one operation is pending. This check happens when |
| 249 | // BatchModeScoper is destroyed. |
| 250 | explicit Scoper(TemplateURLService* service) |
| 251 | : batch_mode_scoper_( |
| 252 | std::make_unique<KeywordWebDataService::BatchModeScoper>( |
| 253 | service->web_data_service_.get())), |
| 254 | service_(service) { |
| 255 | ++service_->outstanding_scoper_handles_; |
| 256 | } |
| 257 | |
Peter Boström | 09c0182 | 2021-09-20 22:43:27 | [diff] [blame] | 258 | Scoper(const Scoper&) = delete; |
| 259 | Scoper& operator=(const Scoper&) = delete; |
| 260 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 261 | // When a Scoper is destroyed, the handle count is updated. If the handle |
| 262 | // count is at zero, notify the observers that the model has changed if |
| 263 | // service is loaded and model was mutated. |
| 264 | ~Scoper() { |
| 265 | DCHECK_GT(service_->outstanding_scoper_handles_, 0); |
| 266 | |
| 267 | --service_->outstanding_scoper_handles_; |
| 268 | if (service_->outstanding_scoper_handles_ == 0 && |
| 269 | service_->model_mutated_notification_pending_) { |
| 270 | service_->model_mutated_notification_pending_ = false; |
| 271 | |
| 272 | if (!service_->loaded_) |
| 273 | return; |
| 274 | |
| 275 | for (auto& observer : service_->model_observers_) |
| 276 | observer.OnTemplateURLServiceChanged(); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | private: |
| 281 | std::unique_ptr<KeywordWebDataService::BatchModeScoper> batch_mode_scoper_; |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 282 | raw_ptr<TemplateURLService> service_; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 283 | }; |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 284 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 285 | // TemplateURLService::PreLoadingProviders ------------------------------------- |
| 286 | |
| 287 | class TemplateURLService::PreLoadingProviders { |
| 288 | public: |
| 289 | PreLoadingProviders() = default; |
| 290 | ~PreLoadingProviders() = default; |
| 291 | |
| 292 | const TemplateURL* default_search_provider() const { |
| 293 | return default_search_provider_.get(); |
| 294 | } |
| 295 | |
| 296 | TemplateURL* default_search_provider() { |
| 297 | return default_search_provider_.get(); |
| 298 | } |
| 299 | |
| 300 | void set_default_search_provider( |
| 301 | std::unique_ptr<TemplateURL> default_search_provider) { |
| 302 | default_search_provider_ = std::move(default_search_provider); |
| 303 | } |
| 304 | |
| 305 | TemplateURLService::OwnedTemplateURLVector TakeSiteSearchEngines() { |
| 306 | return std::move(site_search_engines_); |
| 307 | } |
| 308 | |
| 309 | void set_site_search_engines( |
| 310 | TemplateURLService::OwnedTemplateURLVector&& site_search_engines) { |
| 311 | site_search_engines_ = std::move(site_search_engines); |
| 312 | } |
| 313 | |
| 314 | // Looks up `keyword` and returns the best `TemplateURL` for it. Returns |
| 315 | // `nullptr` if the keyword was not found. The caller should not try to delete |
| 316 | // the returned pointer; the data store retains ownership of it. |
| 317 | const TemplateURL* GetTemplateURLForKeyword( |
| 318 | const std::u16string& keyword) const { |
| 319 | return GetTemplateURLForSelector(base::BindRepeating( |
| 320 | [](const std::u16string& keyword, const TemplateURL& turl) { |
| 321 | return turl.keyword() == keyword; |
| 322 | }, |
| 323 | keyword)); |
| 324 | } |
| 325 | |
| 326 | // Returns that `TemplateURL` with the specified GUID, or nullptr if not |
| 327 | // found.The caller should not try to delete the returned pointer; the data |
| 328 | // store retains ownership of it. |
| 329 | const TemplateURL* GetTemplateURLForGUID(const std::string& guid) const { |
| 330 | return GetTemplateURLForSelector(base::BindRepeating( |
| 331 | [](const std::string& guid, const TemplateURL& turl) { |
| 332 | return turl.sync_guid() == guid; |
| 333 | }, |
| 334 | guid)); |
| 335 | } |
| 336 | |
| 337 | // Returns the best `TemplateURL` found with a URL using the specified `host`, |
| 338 | // or nullptr if no such URL can be found. |
| 339 | const TemplateURL* GetTemplateURLForHost( |
| 340 | const std::string& host, |
| 341 | const SearchTermsData& search_terms_data) const { |
| 342 | return GetTemplateURLForSelector(base::BindRepeating( |
| 343 | [](const std::string& host, const SearchTermsData* search_terms_data, |
| 344 | const TemplateURL& turl) { |
| 345 | return turl.GenerateSearchURL(*search_terms_data).host_piece() == |
| 346 | host; |
| 347 | }, |
| 348 | host, &search_terms_data)); |
| 349 | } |
| 350 | |
| 351 | private: |
| 352 | // Returns a pointer to a `TemplateURL` `t` such that `selector(t) == true`. |
| 353 | // Prioritizes DSP. |
| 354 | const TemplateURL* GetTemplateURLForSelector( |
| 355 | base::RepeatingCallback<bool(const TemplateURL& turl)> selector) const { |
| 356 | if (default_search_provider() && selector.Run(*default_search_provider())) { |
| 357 | return default_search_provider(); |
| 358 | } |
| 359 | |
| 360 | for (auto& site_search_engine : site_search_engines_) { |
| 361 | if (selector.Run(*site_search_engine)) { |
| 362 | return site_search_engine.get(); |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | return nullptr; |
| 367 | } |
| 368 | |
| 369 | // A temporary location for the DSE until Web Data has been loaded and it can |
| 370 | // be merged into |template_urls_|. |
| 371 | std::unique_ptr<TemplateURL> default_search_provider_; |
| 372 | |
| 373 | // A temporary location for site search set by policy until Web Data has been |
| 374 | // loaded and it can be merged into |template_urls_|. |
| 375 | TemplateURLService::OwnedTemplateURLVector site_search_engines_; |
| 376 | }; |
| 377 | |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 378 | // TemplateURLService --------------------------------------------------------- |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 379 | TemplateURLService::TemplateURLService( |
| 380 | PrefService* prefs, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 381 | search_engines::SearchEngineChoiceService* search_engine_choice_service, |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 382 | std::unique_ptr<SearchTermsData> search_terms_data, |
dcheng | 4082bfc | 2014-08-28 19:22:02 | [diff] [blame] | 383 | const scoped_refptr<KeywordWebDataService>& web_data_service, |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 384 | std::unique_ptr<TemplateURLServiceClient> client, |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 385 | const base::RepeatingClosure& dsp_change_callback |
| 386 | #if BUILDFLAG(IS_CHROMEOS_LACROS) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 387 | , |
| 388 | bool for_lacros_main_profile |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 389 | #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| 390 | ) |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 391 | : prefs_(prefs), |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 392 | search_engine_choice_service_(search_engine_choice_service), |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 393 | search_terms_data_(std::move(search_terms_data)), |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 394 | web_data_service_(web_data_service), |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 395 | client_(std::move(client)), |
hashimoto@chromium.org | 82fe07e | 2014-07-02 07:40:22 | [diff] [blame] | 396 | dsp_change_callback_(dsp_change_callback), |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 397 | pre_loading_providers_(std::make_unique<PreLoadingProviders>()), |
caitkp@chromium.org | 95d064c | 2014-05-06 07:12:49 | [diff] [blame] | 398 | default_search_manager_( |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 399 | prefs, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 400 | search_engine_choice_service, |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 401 | base::BindRepeating(&TemplateURLService::ApplyDefaultSearchChange, |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 402 | base::Unretained(this)) |
| 403 | #if BUILDFLAG(IS_CHROMEOS_LACROS) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 404 | , |
| 405 | for_lacros_main_profile |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 406 | #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| 407 | ), |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 408 | enterprise_site_search_manager_(GetEnterpriseSiteSearchManager(prefs)) { |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 409 | if (!search_engine_choice_service_) { |
| 410 | CHECK_IS_TEST(); |
| 411 | CHECK(!prefs); |
| 412 | } |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 413 | DCHECK(search_terms_data_); |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 414 | Init(); |
| 415 | } |
| 416 | |
| 417 | TemplateURLService::TemplateURLService( |
| 418 | PrefService* prefs, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 419 | search_engines::SearchEngineChoiceService* search_engine_choice_service, |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 420 | base::span<const TemplateURLService::Initializer> initializers) |
| 421 | : TemplateURLService( |
| 422 | prefs, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 423 | search_engine_choice_service, |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 424 | /*search_terms_data=*/std::make_unique<SearchTermsData>(), |
| 425 | /*web_data_service=*/nullptr, |
| 426 | /*client=*/nullptr, |
| 427 | /*dsp_change_callback=*/base::RepeatingClosure() |
| 428 | #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| 429 | , |
| 430 | /*for_lacros_main_profile=*/false |
| 431 | #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| 432 | ) { |
| 433 | // This constructor is not intended to be used outside of tests. |
| 434 | CHECK_IS_TEST(); |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 435 | CHECK(search_engine_choice_service_ || !prefs); |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 436 | ApplyInitializersForTesting(initializers); // IN-TEST |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 437 | } |
| 438 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 439 | TemplateURLService::TemplateURLService(const Initializer* initializers, |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 440 | const size_t count) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 441 | : pre_loading_providers_(std::make_unique<PreLoadingProviders>()), |
| 442 | default_search_manager_( |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 443 | /*pref_service=*/nullptr, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 444 | /*search_engine_choice_service=*/nullptr, |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 445 | base::BindRepeating(&TemplateURLService::ApplyDefaultSearchChange, |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 446 | base::Unretained(this)) |
| 447 | #if BUILDFLAG(IS_CHROMEOS_LACROS) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 448 | , |
| 449 | false |
Jun Ishiguro | 6bae99ca | 2023-11-06 10:03:49 | [diff] [blame] | 450 | #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| 451 | ), |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 452 | enterprise_site_search_manager_( |
| 453 | GetEnterpriseSiteSearchManager(/*prefs=*/nullptr)) { |
| 454 | CHECK_IS_TEST(); |
| 455 | Init(); |
| 456 | ApplyInitializersForTesting(base::make_span(initializers, count)); // IN-TEST |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 457 | } |
| 458 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 459 | TemplateURLService::~TemplateURLService() { |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 460 | // |web_data_service_| should be deleted during Shutdown(). |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 461 | DCHECK(!web_data_service_); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 462 | } |
| 463 | |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 464 | // static |
sdefresne | 2948796 | 2015-07-03 09:24:39 | [diff] [blame] | 465 | void TemplateURLService::RegisterProfilePrefs( |
| 466 | user_prefs::PrefRegistrySyncable* registry) { |
Xiaohan Wang | cff600f | 2022-01-14 14:55:33 | [diff] [blame] | 467 | #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) |
melandory | c1105ec | 2016-07-01 12:11:53 | [diff] [blame] | 468 | uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS; |
| 469 | #else |
| 470 | uint32_t flags = user_prefs::PrefRegistrySyncable::SYNCABLE_PREF; |
| 471 | #endif |
sdefresne | 2948796 | 2015-07-03 09:24:39 | [diff] [blame] | 472 | registry->RegisterStringPref(prefs::kSyncedDefaultSearchProviderGUID, |
| 473 | std::string(), |
melandory | c1105ec | 2016-07-01 12:11:53 | [diff] [blame] | 474 | flags); |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 475 | registry->RegisterStringPref(prefs::kDefaultSearchProviderGUID, |
| 476 | std::string()); |
sdefresne | 2948796 | 2015-07-03 09:24:39 | [diff] [blame] | 477 | registry->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, true); |
Roman Arora | ebf0ed7f | 2020-06-10 22:33:06 | [diff] [blame] | 478 | registry->RegisterBooleanPref( |
| 479 | prefs::kDefaultSearchProviderContextMenuAccessAllowed, true); |
Jack Yammine | 4ed56a1 | 2023-08-02 07:54:59 | [diff] [blame] | 480 | |
Jens Mueller | 087e5c4 | 2023-10-05 11:36:05 | [diff] [blame] | 481 | if (search_engines::IsChoiceScreenFlagEnabled( |
| 482 | search_engines::ChoicePromo::kAny)) { |
Jack Yammine | 4ed56a1 | 2023-08-02 07:54:59 | [diff] [blame] | 483 | registry->RegisterInt64Pref( |
| 484 | prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp, 0); |
David Roger | c549c54 | 2023-11-29 15:13:31 | [diff] [blame] | 485 | registry->RegisterStringPref( |
| 486 | prefs::kDefaultSearchProviderChoiceScreenCompletionVersion, |
| 487 | std::string()); |
Sylvain Defresne | e7fac2a3 | 2024-04-10 13:32:34 | [diff] [blame] | 488 | |
| 489 | #if BUILDFLAG(IS_IOS) |
| 490 | registry->RegisterIntegerPref( |
| 491 | prefs::kDefaultSearchProviderChoiceScreenSkippedCount, 0); |
| 492 | #endif |
Jack Yammine | 4ed56a1 | 2023-08-02 07:54:59 | [diff] [blame] | 493 | } |
sdefresne | 2948796 | 2015-07-03 09:24:39 | [diff] [blame] | 494 | } |
| 495 | |
Xiaohan Wang | cff600f | 2022-01-14 14:55:33 | [diff] [blame] | 496 | #if BUILDFLAG(IS_ANDROID) |
Peter Wen | f517f7d | 2019-06-13 15:28:27 | [diff] [blame] | 497 | base::android::ScopedJavaLocalRef<jobject> TemplateURLService::GetJavaObject() { |
| 498 | if (!template_url_service_android_) { |
| 499 | template_url_service_android_ = |
| 500 | std::make_unique<TemplateUrlServiceAndroid>(this); |
| 501 | } |
| 502 | return template_url_service_android_->GetJavaObject(); |
| 503 | } |
| 504 | #endif |
| 505 | |
mpearson | 511ce60b | 2015-05-23 23:47:09 | [diff] [blame] | 506 | bool TemplateURLService::CanAddAutogeneratedKeyword( |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 507 | const std::u16string& keyword, |
Tommy Li | abcfd14 | 2021-01-22 20:51:34 | [diff] [blame] | 508 | const GURL& url) { |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 509 | DCHECK(!keyword.empty()); // This should only be called for non-empty |
| 510 | // keywords. If we need to support empty kewords |
| 511 | // the code needs to change slightly. |
Kevin Bailey | 499298a | 2018-03-16 14:54:43 | [diff] [blame] | 512 | const TemplateURL* existing_url = GetTemplateURLForKeyword(keyword); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 513 | if (existing_url) { |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 514 | // TODO(tommycli): Currently, this code goes one step beyond |
| 515 | // safe_for_autoreplace() and also forbids automatically modifying |
| 516 | // prepopulated engines. That's debatable, as we already update prepopulated |
| 517 | // provider favicons as the user browses. See UpdateProviderFavicons(). |
| 518 | return existing_url->safe_for_autoreplace() && |
| 519 | existing_url->prepopulate_id() == 0; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 520 | } |
| 521 | |
mpearson | 511ce60b | 2015-05-23 23:47:09 | [diff] [blame] | 522 | // We don't have a TemplateURL with keyword. We still may not allow this |
| 523 | // keyword if there's evidence we may have created this keyword before and |
| 524 | // the user renamed it (because, for instance, the keyword is a common word |
| 525 | // that may interfere with search queries). An easy heuristic for this is |
| 526 | // whether the user has a TemplateURL that has been manually modified (e.g., |
| 527 | // renamed) connected to the same host. |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 528 | return !url.is_valid() || url.host().empty() || |
mpearson | 511ce60b | 2015-05-23 23:47:09 | [diff] [blame] | 529 | CanAddAutogeneratedKeywordForHost(url.host()); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 530 | } |
| 531 | |
Fabio Tirelo | 41316deb | 2023-11-24 21:33:11 | [diff] [blame] | 532 | bool TemplateURLService::IsPrepopulatedOrDefaultProviderByPolicy( |
jeffschiller | 9c4df02 | 2017-04-14 00:47:38 | [diff] [blame] | 533 | const TemplateURL* t_url) const { |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 534 | return (t_url->prepopulate_id() > 0 || |
| 535 | t_url->created_by_policy() == |
| 536 | TemplateURLData::CreatedByPolicy::kDefaultSearchProvider || |
Pavel Yatsuk | c5fa92d | 2019-09-26 21:43:27 | [diff] [blame] | 537 | t_url->created_from_play_api()) && |
| 538 | t_url->SupportsReplacement(search_terms_data()); |
ltian | 3b5e1a34 | 2016-11-30 19:48:11 | [diff] [blame] | 539 | } |
| 540 | |
jeffschiller | 9c4df02 | 2017-04-14 00:47:38 | [diff] [blame] | 541 | bool TemplateURLService::ShowInDefaultList(const TemplateURL* t_url) const { |
ltian | 3b5e1a34 | 2016-11-30 19:48:11 | [diff] [blame] | 542 | return t_url == default_search_provider_ || |
Fabio Tirelo | 41316deb | 2023-11-24 21:33:11 | [diff] [blame] | 543 | IsPrepopulatedOrDefaultProviderByPolicy(t_url); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 544 | } |
| 545 | |
Fabio Tirelo | cba0d89 | 2023-12-19 18:45:41 | [diff] [blame] | 546 | bool TemplateURLService::ShowInActivesList(const TemplateURL* t_url) const { |
| 547 | return t_url->is_active() == TemplateURLData::ActiveStatus::kTrue || |
| 548 | (t_url->created_by_policy() == |
| 549 | TemplateURLData::CreatedByPolicy::kSiteSearch && |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 550 | t_url->featured_by_policy()); |
Fabio Tirelo | cba0d89 | 2023-12-19 18:45:41 | [diff] [blame] | 551 | } |
| 552 | |
| 553 | bool TemplateURLService::HiddenFromLists(const TemplateURL* t_url) const { |
| 554 | // Hide synthetic entries created by SiteSearchSettings policy, since they |
| 555 | // are only used for discoverability and the corresponding entry that doesn't |
| 556 | // start with "@" is already shown in the actives list. |
| 557 | return t_url->created_by_policy() == |
| 558 | TemplateURLData::CreatedByPolicy::kSiteSearch && |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 559 | t_url->featured_by_policy(); |
Fabio Tirelo | cba0d89 | 2023-12-19 18:45:41 | [diff] [blame] | 560 | } |
| 561 | |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 562 | void TemplateURLService::AddMatchingKeywords(const std::u16string& prefix, |
| 563 | bool supports_replacement_only, |
| 564 | TemplateURLVector* matches) { |
| 565 | AddMatchingKeywordsHelper(keyword_to_turl_, prefix, supports_replacement_only, |
| 566 | matches); |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 567 | } |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 568 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 569 | TemplateURL* TemplateURLService::GetTemplateURLForKeyword( |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 570 | const std::u16string& keyword) { |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 571 | return const_cast<TemplateURL*>( |
| 572 | static_cast<const TemplateURLService*>(this)-> |
| 573 | GetTemplateURLForKeyword(keyword)); |
| 574 | } |
| 575 | |
| 576 | const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 577 | const std::u16string& keyword) const { |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 578 | // Finds and returns the best match for |keyword|. |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 579 | const auto match_range = keyword_to_turl_.equal_range(keyword); |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 580 | if (match_range.first != match_range.second) { |
| 581 | // Among the matches for |keyword| in the multimap, return the best one. |
| 582 | return std::min_element( |
| 583 | match_range.first, match_range.second, |
| 584 | [](const auto& a, const auto& b) { |
Fabio Tirelo | c0de81c | 2024-01-10 18:07:15 | [diff] [blame] | 585 | return a.second->IsBetterThanConflictingEngine(b.second); |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 586 | }) |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 587 | ->second; |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 588 | } |
| 589 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 590 | return loaded_ ? nullptr |
| 591 | : pre_loading_providers_->GetTemplateURLForKeyword(keyword); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 592 | } |
| 593 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 594 | TemplateURL* TemplateURLService::GetTemplateURLForGUID( |
| 595 | const std::string& sync_guid) { |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 596 | return const_cast<TemplateURL*>( |
| 597 | static_cast<const TemplateURLService*>(this)-> |
| 598 | GetTemplateURLForGUID(sync_guid)); |
| 599 | } |
| 600 | |
| 601 | const TemplateURL* TemplateURLService::GetTemplateURLForGUID( |
| 602 | const std::string& sync_guid) const { |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 603 | auto elem(guid_to_turl_.find(sync_guid)); |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 604 | if (elem != guid_to_turl_.end()) { |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 605 | return elem->second; |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 606 | } |
| 607 | |
| 608 | return loaded_ ? nullptr |
| 609 | : pre_loading_providers_->GetTemplateURLForGUID(sync_guid); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 610 | } |
| 611 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 612 | TemplateURL* TemplateURLService::GetTemplateURLForHost( |
| 613 | const std::string& host) { |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 614 | return const_cast<TemplateURL*>( |
| 615 | static_cast<const TemplateURLService*>(this)-> |
| 616 | GetTemplateURLForHost(host)); |
| 617 | } |
| 618 | |
| 619 | const TemplateURL* TemplateURLService::GetTemplateURLForHost( |
| 620 | const std::string& host) const { |
Tommy C. Li | 39c53410 | 2022-05-09 16:49:32 | [diff] [blame] | 621 | if (loaded_) { |
| 622 | // `provider_map_` takes care of finding the best TemplateURL for `host`. |
hashimoto@chromium.org | 168d0872 | 2014-06-18 07:13:28 | [diff] [blame] | 623 | return provider_map_->GetTemplateURLForHost(host); |
Tommy C. Li | 39c53410 | 2022-05-09 16:49:32 | [diff] [blame] | 624 | } |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 625 | |
| 626 | return loaded_ ? nullptr |
| 627 | : pre_loading_providers_->GetTemplateURLForHost( |
| 628 | host, search_terms_data()); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 629 | } |
| 630 | |
Tommy C. Li | 069c5505 | 2022-05-06 19:04:11 | [diff] [blame] | 631 | size_t TemplateURLService::GetTemplateURLCountForHostForLogging( |
| 632 | const std::string& host) const { |
| 633 | DCHECK(loaded_); |
Sophie Chang | 4c700d3 | 2022-05-06 21:39:42 | [diff] [blame] | 634 | auto* host_urls = provider_map_->GetURLsForHost(host); |
| 635 | return host_urls ? host_urls->size() : 0; |
Tommy C. Li | 069c5505 | 2022-05-06 19:04:11 | [diff] [blame] | 636 | } |
| 637 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 638 | TemplateURL* TemplateURLService::Add( |
| 639 | std::unique_ptr<TemplateURL> template_url) { |
a-v-y | c134e76 | 2017-04-18 15:31:31 | [diff] [blame] | 640 | DCHECK(template_url); |
| 641 | DCHECK( |
| 642 | !IsCreatedByExtension(template_url.get()) || |
| 643 | (!FindTemplateURLForExtension(template_url->extension_info_->extension_id, |
| 644 | template_url->type()) && |
| 645 | template_url->id() == kInvalidTemplateURLID)); |
| 646 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 647 | return Add(std::move(template_url), true); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 648 | } |
| 649 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 650 | TemplateURL* TemplateURLService::AddWithOverrides( |
| 651 | std::unique_ptr<TemplateURL> template_url, |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 652 | const std::u16string& short_name, |
| 653 | const std::u16string& keyword, |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 654 | const std::string& url) { |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 655 | DCHECK(!short_name.empty()); |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 656 | DCHECK(!keyword.empty()); |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 657 | DCHECK(!url.empty()); |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 658 | template_url->data_.SetShortName(short_name); |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 659 | template_url->data_.SetKeyword(keyword); |
| 660 | template_url->SetURL(url); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 661 | return Add(std::move(template_url)); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 662 | } |
| 663 | |
Kevin Bailey | 499298a | 2018-03-16 14:54:43 | [diff] [blame] | 664 | void TemplateURLService::Remove(const TemplateURL* template_url) { |
Tommy Li | a83fbf9 | 2021-01-12 21:04:47 | [diff] [blame] | 665 | // CHECK that we aren't trying to Remove() the default search provider. |
| 666 | // This has happened before, and causes permanent damage to the user Profile, |
| 667 | // which can then be Synced to other installations. It's better to crash |
| 668 | // immediately, and that's why this isn't a DCHECK. https://crbug.com/1164024 |
| 669 | { |
| 670 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 671 | |
| 672 | // TODO(tommycli): Once we are sure this never happens in practice, we can |
| 673 | // remove this CrashKeyString, but we should keep the CHECK. |
| 674 | static base::debug::CrashKeyString* crash_key = |
| 675 | base::debug::AllocateCrashKeyString("removed_turl_keyword", |
| 676 | base::debug::CrashKeySize::Size256); |
| 677 | base::debug::ScopedCrashKeyString auto_clear( |
| 678 | crash_key, base::UTF16ToUTF8(template_url->keyword())); |
| 679 | |
| 680 | CHECK_NE(template_url, default_provider); |
Tommy Li | 50aeacaf | 2021-01-20 21:21:12 | [diff] [blame] | 681 | |
Tommy Li | d8e4850ef | 2021-03-05 18:18:19 | [diff] [blame] | 682 | // Before we are loaded, we want to CHECK that we aren't accidentally |
| 683 | // removing the in-table representation of the Default Search Engine. |
| 684 | // |
| 685 | // But users in the wild do indeed have engines with duplicated sync GUIDs. |
| 686 | // For instance, Extensions Override Settings API used to have a bug that |
| 687 | // would clone GUIDs. So therefore skip the check after loading. |
| 688 | // https://crbug.com/1166372#c13 |
| 689 | if (!loaded() && default_provider && |
Tommy Li | 50aeacaf | 2021-01-20 21:21:12 | [diff] [blame] | 690 | default_provider->type() != |
| 691 | TemplateURL::Type::NORMAL_CONTROLLED_BY_EXTENSION && |
| 692 | template_url->type() != |
| 693 | TemplateURL::Type::NORMAL_CONTROLLED_BY_EXTENSION) { |
Tommy Li | a83fbf9 | 2021-01-12 21:04:47 | [diff] [blame] | 694 | CHECK_NE(template_url->sync_guid(), default_provider->sync_guid()); |
Tommy Li | 50aeacaf | 2021-01-20 21:21:12 | [diff] [blame] | 695 | } |
Tommy Li | a83fbf9 | 2021-01-12 21:04:47 | [diff] [blame] | 696 | } |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 697 | |
| 698 | auto i = FindTemplateURL(&template_urls_, template_url); |
| 699 | if (i == template_urls_.end()) |
| 700 | return; |
| 701 | |
| 702 | Scoper scoper(this); |
| 703 | model_mutated_notification_pending_ = true; |
| 704 | |
| 705 | RemoveFromMaps(template_url); |
| 706 | |
| 707 | // Remove it from the vector containing all TemplateURLs. |
| 708 | std::unique_ptr<TemplateURL> scoped_turl = std::move(*i); |
| 709 | template_urls_.erase(i); |
| 710 | |
| 711 | if (template_url->type() == TemplateURL::NORMAL) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 712 | if (web_data_service_) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 713 | web_data_service_->RemoveKeyword(template_url->id()); |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 714 | } |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 715 | // Inform sync of the deletion. |
| 716 | ProcessTemplateURLChange(FROM_HERE, template_url, |
| 717 | syncer::SyncChange::ACTION_DELETE); |
| 718 | |
| 719 | // The default search engine can't be deleted. But the user defined DSE can |
| 720 | // be hidden by an extension or policy and then deleted. Clean up the user |
| 721 | // prefs then. |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 722 | if (prefs_ && (template_url->sync_guid() == |
| 723 | GetDefaultSearchProviderPrefValue(*prefs_))) { |
| 724 | SetDefaultSearchProviderPrefValue(*prefs_, std::string()); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 725 | } |
| 726 | |
| 727 | UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName, |
| 728 | DELETE_ENGINE_USER_ACTION, DELETE_ENGINE_MAX); |
| 729 | } |
| 730 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 731 | if (loaded_ && client_) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 732 | client_->DeleteAllSearchTermsForKeyword(template_url->id()); |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 733 | } |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 734 | } |
| 735 | |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 736 | void TemplateURLService::RemoveExtensionControlledTURL( |
hashimoto@chromium.org | c73b2b5 | 2014-06-27 09:42:33 | [diff] [blame] | 737 | const std::string& extension_id, |
| 738 | TemplateURL::Type type) { |
hashimoto@chromium.org | c73b2b5 | 2014-06-27 09:42:33 | [diff] [blame] | 739 | TemplateURL* url = FindTemplateURLForExtension(extension_id, type); |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 740 | if (!url) |
| 741 | return; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 742 | // NULL this out so that we can call Remove. |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 743 | if (default_search_provider_ == url) |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 744 | default_search_provider_ = nullptr; |
a-v-y | 858416e | 2017-03-01 16:42:45 | [diff] [blame] | 745 | Remove(url); |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 746 | } |
| 747 | |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 748 | void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after, |
| 749 | base::Time created_before) { |
Alan Screen | d6a8b6741 | 2021-01-29 21:35:57 | [diff] [blame] | 750 | RemoveAutoGeneratedForUrlsBetween(base::NullCallback(), created_after, |
| 751 | created_before); |
mkwst@chromium.org | 8d4ec68 | 2012-02-17 12:20:17 | [diff] [blame] | 752 | } |
| 753 | |
msramek | db42f89 | 2016-08-31 11:53:42 | [diff] [blame] | 754 | void TemplateURLService::RemoveAutoGeneratedForUrlsBetween( |
Alan Screen | d6a8b6741 | 2021-01-29 21:35:57 | [diff] [blame] | 755 | const base::RepeatingCallback<bool(const GURL&)>& url_filter, |
mkwst@chromium.org | 8d4ec68 | 2012-02-17 12:20:17 | [diff] [blame] | 756 | base::Time created_after, |
| 757 | base::Time created_before) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 758 | Scoper scoper(this); |
| 759 | |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 760 | for (size_t i = 0; i < template_urls_.size();) { |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 761 | TemplateURL* turl = template_urls_[i].get(); |
| 762 | if (turl->date_created() >= created_after && |
| 763 | (created_before.is_null() || turl->date_created() < created_before) && |
| 764 | turl->safe_for_autoreplace() && turl->prepopulate_id() == 0 && |
Angela Yoeurng | 66776839 | 2023-01-13 00:04:19 | [diff] [blame] | 765 | turl->starter_pack_id() == 0 && !MatchesDefaultSearchProvider(turl) && |
msramek | db42f89 | 2016-08-31 11:53:42 | [diff] [blame] | 766 | (url_filter.is_null() || |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 767 | url_filter.Run(turl->GenerateSearchURL(search_terms_data())))) { |
| 768 | Remove(turl); |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 769 | } else { |
| 770 | ++i; |
| 771 | } |
| 772 | } |
| 773 | } |
| 774 | |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 775 | void TemplateURLService::RegisterOmniboxKeyword( |
a-v-y | f4eb435 | 2017-02-25 18:46:59 | [diff] [blame] | 776 | const std::string& extension_id, |
| 777 | const std::string& extension_name, |
| 778 | const std::string& keyword, |
| 779 | const std::string& template_url_string, |
| 780 | const base::Time& extension_install_time) { |
yoz@chromium.org | d356c98 | 2012-12-12 19:32:55 | [diff] [blame] | 781 | DCHECK(loaded_); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 782 | |
hashimoto@chromium.org | c73b2b5 | 2014-06-27 09:42:33 | [diff] [blame] | 783 | if (FindTemplateURLForExtension(extension_id, |
| 784 | TemplateURL::OMNIBOX_API_EXTENSION)) |
| 785 | return; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 786 | |
hashimoto@chromium.org | c73b2b5 | 2014-06-27 09:42:33 | [diff] [blame] | 787 | TemplateURLData data; |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 788 | data.SetShortName(base::UTF8ToUTF16(extension_name)); |
hashimoto@chromium.org | c73b2b5 | 2014-06-27 09:42:33 | [diff] [blame] | 789 | data.SetKeyword(base::UTF8ToUTF16(keyword)); |
| 790 | data.SetURL(template_url_string); |
Jinho Bang | fa6b575 | 2018-01-03 20:52:19 | [diff] [blame] | 791 | Add(std::make_unique<TemplateURL>(data, TemplateURL::OMNIBOX_API_EXTENSION, |
a-v-y | c134e76 | 2017-04-18 15:31:31 | [diff] [blame] | 792 | extension_id, extension_install_time, |
| 793 | false)); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 794 | } |
| 795 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 796 | TemplateURLService::TemplateURLVector TemplateURLService::GetTemplateURLs() { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 797 | TemplateURLVector result; |
| 798 | for (const auto& turl : template_urls_) |
| 799 | result.push_back(turl.get()); |
| 800 | return result; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 801 | } |
| 802 | |
Nicolas Dossou-Gbete | 4a319dbd | 2024-03-29 17:01:15 | [diff] [blame] | 803 | std::unique_ptr<search_engines::ChoiceScreenData> |
| 804 | TemplateURLService::GetChoiceScreenData() { |
| 805 | OwnedTemplateURLVector owned_template_urls; |
| 806 | bool was_current_default_inserted = false; |
| 807 | |
| 808 | // We call `GetPrepopulatedEngines` instead of |
| 809 | // `GetSearchProvidersUsingLoadedEngines` because the latter will return the |
| 810 | // list of search engines that might have been modified by the user (by |
| 811 | // changing the engine's keyword in settings for example). |
| 812 | // Changing this will cause issues in the icon generation behavior that's |
| 813 | // handled by `generate_search_engine_icons.py`. |
| 814 | std::vector<std::unique_ptr<TemplateURLData>> engines = |
| 815 | TemplateURLPrepopulateData::GetPrepopulatedEngines( |
| 816 | prefs_, search_engine_choice_service_, |
| 817 | /*default_search_provider_index=*/nullptr, |
| 818 | /*include_current_default=*/true, /*template_url_service=*/this, |
| 819 | /*was_current_default_inserted=*/&was_current_default_inserted); |
| 820 | for (const auto& engine : engines) { |
| 821 | owned_template_urls.push_back(std::make_unique<TemplateURL>(*engine)); |
| 822 | } |
| 823 | |
| 824 | return std::make_unique<search_engines::ChoiceScreenData>( |
| 825 | std::move(owned_template_urls), |
| 826 | search_engine_choice_service_->GetCountryId(), |
| 827 | /*list_is_modified_by_current_default=*/was_current_default_inserted, |
| 828 | search_terms_data()); |
| 829 | } |
| 830 | |
Nicolas Dossou-Gbete | 0cd7f0c1 | 2024-01-02 14:37:08 | [diff] [blame] | 831 | #if BUILDFLAG(IS_ANDROID) |
| 832 | TemplateURLService::OwnedTemplateURLDataVector |
| 833 | TemplateURLService::GetTemplateURLsForCountry(const std::string& country_code) { |
| 834 | return TemplateURLPrepopulateData::GetLocalPrepopulatedEngines( |
| 835 | country_code, CHECK_DEREF(prefs_.get())); |
| 836 | } |
| 837 | #endif |
| 838 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 839 | void TemplateURLService::IncrementUsageCount(TemplateURL* url) { |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 840 | DCHECK(url); |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 841 | // Extension-controlled search engines are not persisted. |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 842 | if (url->type() != TemplateURL::NORMAL) |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 843 | return; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 844 | if (!Contains(&template_urls_, url)) |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 845 | return; |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 846 | ++url->data_.usage_count; |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 847 | |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 848 | if (web_data_service_) |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 849 | web_data_service_->UpdateKeyword(url->data()); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 850 | } |
| 851 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 852 | void TemplateURLService::ResetTemplateURL(TemplateURL* url, |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 853 | const std::u16string& title, |
| 854 | const std::u16string& keyword, |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 855 | const std::string& search_url) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 856 | DCHECK(!IsCreatedByExtension(url)); |
| 857 | DCHECK(!keyword.empty()); |
| 858 | DCHECK(!search_url.empty()); |
| 859 | TemplateURLData data(url->data()); |
| 860 | data.SetShortName(title); |
| 861 | data.SetKeyword(keyword); |
| 862 | if (search_url != data.url()) { |
| 863 | data.SetURL(search_url); |
| 864 | // The urls have changed, reset the favicon url. |
| 865 | data.favicon_url = GURL(); |
| 866 | } |
| 867 | data.safe_for_autoreplace = false; |
| 868 | data.last_modified = clock_->Now(); |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 869 | data.is_active = TemplateURLData::ActiveStatus::kTrue; |
| 870 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 871 | Update(url, TemplateURL(data)); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 872 | } |
| 873 | |
Angela Yoeurng | 895f45ac | 2021-08-20 16:26:46 | [diff] [blame] | 874 | void TemplateURLService::SetIsActiveTemplateURL(TemplateURL* url, |
| 875 | bool is_active) { |
| 876 | DCHECK(url); |
| 877 | |
| 878 | TemplateURLData data(url->data()); |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 879 | std::string histogram_name = kKeywordModeUsageByEngineTypeHistogramName; |
| 880 | if (is_active) { |
| 881 | data.is_active = TemplateURLData::ActiveStatus::kTrue; |
Angela Yoeurng | 38806b4 | 2022-10-13 00:20:54 | [diff] [blame] | 882 | data.safe_for_autoreplace = false; |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 883 | histogram_name.append(".Activated"); |
| 884 | } else { |
| 885 | data.is_active = TemplateURLData::ActiveStatus::kFalse; |
| 886 | histogram_name.append(".Deactivated"); |
| 887 | } |
Angela Yoeurng | 895f45ac | 2021-08-20 16:26:46 | [diff] [blame] | 888 | |
| 889 | Update(url, TemplateURL(data)); |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 890 | |
| 891 | base::UmaHistogramEnumeration( |
| 892 | histogram_name, url->GetBuiltinEngineType(), |
| 893 | BuiltinEngineType::KEYWORD_MODE_ENGINE_TYPE_MAX); |
Angela Yoeurng | 895f45ac | 2021-08-20 16:26:46 | [diff] [blame] | 894 | } |
| 895 | |
Tommy Li | a56419a | 2020-12-17 23:40:48 | [diff] [blame] | 896 | TemplateURL* TemplateURLService::CreatePlayAPISearchEngine( |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 897 | const std::u16string& title, |
| 898 | const std::u16string& keyword, |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 899 | const std::string& search_url, |
Pavel Yatsuk | 025b85f | 2019-10-25 15:22:46 | [diff] [blame] | 900 | const std::string& suggestions_url, |
Jens Mueller | 3ef45a3 | 2023-07-05 16:33:13 | [diff] [blame] | 901 | const std::string& favicon_url, |
| 902 | const std::string& new_tab_url, |
| 903 | const std::string& image_url, |
| 904 | const std::string& image_url_post_params, |
| 905 | const std::string& image_translate_url, |
| 906 | const std::string& image_translate_source_language_param_key, |
| 907 | const std::string& image_translate_target_language_param_key) { |
Tommy Li | a56419a | 2020-12-17 23:40:48 | [diff] [blame] | 908 | // It's the caller's responsibility to check that there are no existing |
| 909 | // Play API for engine, but still CHECK this to avoid polluting the database. |
| 910 | // Currently, we never update Play API engine data. If we ever want to do |
| 911 | // that, we need to change how this method behaves. |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 912 | const auto match_range = keyword_to_turl_.equal_range(keyword); |
Tommy Li | a56419a | 2020-12-17 23:40:48 | [diff] [blame] | 913 | for (auto it = match_range.first; it != match_range.second; ++it) { |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 914 | CHECK(!it->second->created_from_play_api()); |
Tommy Li | a56419a | 2020-12-17 23:40:48 | [diff] [blame] | 915 | } |
| 916 | |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 917 | TemplateURLData data; |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 918 | data.SetShortName(title); |
| 919 | data.SetKeyword(keyword); |
| 920 | data.SetURL(search_url); |
Pavel Yatsuk | 025b85f | 2019-10-25 15:22:46 | [diff] [blame] | 921 | data.suggestions_url = suggestions_url; |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 922 | data.favicon_url = GURL(favicon_url); |
Jens Mueller | 3ef45a3 | 2023-07-05 16:33:13 | [diff] [blame] | 923 | data.new_tab_url = new_tab_url; |
| 924 | data.image_url = image_url; |
| 925 | data.image_url_post_params = image_url_post_params; |
| 926 | data.image_translate_url = image_translate_url; |
| 927 | data.image_translate_source_language_param_key = |
| 928 | image_translate_source_language_param_key; |
| 929 | data.image_translate_target_language_param_key = |
| 930 | image_translate_target_language_param_key; |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 931 | data.created_from_play_api = true; |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 932 | // Play API engines are created by explicit user gesture, and should not be |
| 933 | // auto-replaceable by an auto-generated engine as the user browses. |
| 934 | data.safe_for_autoreplace = false; |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 935 | data.is_active = TemplateURLData::ActiveStatus::kTrue; |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 936 | |
Tommy Li | a56419a | 2020-12-17 23:40:48 | [diff] [blame] | 937 | // The Play API search engine is not guaranteed to be the best engine for |
| 938 | // |keyword|, if there are user-defined, extension, or policy engines. |
| 939 | // In practice on Android, this rarely happens, as there is only policy. |
| 940 | return Add(std::make_unique<TemplateURL>(data)); |
Pavel Yatsuk | bec91d2 | 2019-10-07 19:14:55 | [diff] [blame] | 941 | } |
| 942 | |
Tommy C. Li | 2589a7a54 | 2018-05-11 00:44:31 | [diff] [blame] | 943 | void TemplateURLService::UpdateProviderFavicons( |
| 944 | const GURL& potential_search_url, |
| 945 | const GURL& favicon_url) { |
| 946 | DCHECK(loaded_); |
| 947 | DCHECK(potential_search_url.is_valid()); |
| 948 | |
| 949 | const TemplateURLSet* urls_for_host = |
| 950 | provider_map_->GetURLsForHost(potential_search_url.host()); |
| 951 | if (!urls_for_host) |
| 952 | return; |
| 953 | |
Tommy C. Li | 7dc6c9b | 2018-05-24 21:46:14 | [diff] [blame] | 954 | // Make a copy of the container of the matching TemplateURLs, as the original |
| 955 | // container is invalidated as we update the contained TemplateURLs. |
| 956 | TemplateURLSet urls_for_host_copy(*urls_for_host); |
| 957 | |
Tommy C. Li | 2589a7a54 | 2018-05-11 00:44:31 | [diff] [blame] | 958 | Scoper scoper(this); |
Tommy C. Li | 7dc6c9b | 2018-05-24 21:46:14 | [diff] [blame] | 959 | for (TemplateURL* turl : urls_for_host_copy) { |
Tommy C. Li | 2589a7a54 | 2018-05-11 00:44:31 | [diff] [blame] | 960 | if (!IsCreatedByExtension(turl) && |
| 961 | turl->IsSearchURL(potential_search_url, search_terms_data()) && |
| 962 | turl->favicon_url() != favicon_url) { |
| 963 | TemplateURLData data(turl->data()); |
| 964 | data.favicon_url = favicon_url; |
| 965 | Update(turl, TemplateURL(data)); |
| 966 | } |
| 967 | } |
| 968 | } |
| 969 | |
jeffschiller | 9c4df02 | 2017-04-14 00:47:38 | [diff] [blame] | 970 | bool TemplateURLService::CanMakeDefault(const TemplateURL* url) const { |
Igor Ruvinov | f266d2a4 | 2022-06-24 17:52:16 | [diff] [blame] | 971 | return (default_search_provider_source_ == DefaultSearchManager::FROM_USER || |
| 972 | default_search_provider_source_ == |
| 973 | DefaultSearchManager::FROM_POLICY_RECOMMENDED || |
| 974 | default_search_provider_source_ == |
| 975 | DefaultSearchManager::FROM_FALLBACK) && |
| 976 | (url != GetDefaultSearchProvider()) && |
| 977 | url->url_ref().SupportsReplacement(search_terms_data()) && |
Angela Yoeurng | 8f467d95 | 2024-02-14 00:36:31 | [diff] [blame] | 978 | (url->type() == TemplateURL::NORMAL) && (url->starter_pack_id() == 0); |
levin@chromium.org | 2de7e00 | 2010-10-11 22:58:20 | [diff] [blame] | 979 | } |
| 980 | |
erikwright@chromium.org | f1cb558 | 2014-04-25 07:35:26 | [diff] [blame] | 981 | void TemplateURLService::SetUserSelectedDefaultSearchProvider( |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 982 | TemplateURL* url, |
| 983 | search_engines::ChoiceMadeLocation choice_made_location) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 984 | // Omnibox keywords cannot be made default. Extension-controlled search |
| 985 | // engines can be made default only by the extension itself because they |
| 986 | // aren't persisted. |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 987 | DCHECK(!url || !IsCreatedByExtension(url)); |
Angela Yoeurng | eff157d | 2021-10-25 19:49:59 | [diff] [blame] | 988 | if (url) { |
| 989 | url->data_.is_active = TemplateURLData::ActiveStatus::kTrue; |
| 990 | } |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 991 | |
| 992 | bool selection_added = false; |
| 993 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 994 | if (load_failed_) { |
| 995 | // Skip the DefaultSearchManager, which will persist to user preferences. |
| 996 | if ((default_search_provider_source_ == DefaultSearchManager::FROM_USER) || |
| 997 | (default_search_provider_source_ == |
| 998 | DefaultSearchManager::FROM_FALLBACK)) { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 999 | ApplyDefaultSearchChange(url ? &url->data() : nullptr, |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1000 | DefaultSearchManager::FROM_USER); |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 1001 | selection_added = true; |
Nicolas Dossou-Gbete | 709c270 | 2024-02-05 20:03:32 | [diff] [blame] | 1002 | } else { |
| 1003 | // When we are setting the search engine choice from choice screens, |
| 1004 | // the DSP source is expected to allow the search engine to be changed by |
Nicolas Dossou-Gbete | 03549d1 | 2024-04-02 17:13:49 | [diff] [blame] | 1005 | // the user. But theoretically there is a possibility that a policy |
| 1006 | // kicked in after a choice screen was shown, that could be a way to |
| 1007 | // enter this state |
| 1008 | // TODO(crbug.com/328041262): Investigate mitigation options. |
Nicolas Dossou-Gbete | 709c270 | 2024-02-05 20:03:32 | [diff] [blame] | 1009 | CHECK_NE(choice_made_location, search_engines::ChoiceMadeLocation::kOther, |
Nicolas Dossou-Gbete | 03549d1 | 2024-04-02 17:13:49 | [diff] [blame] | 1010 | base::NotFatalUntil::M127); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1011 | } |
| 1012 | } else { |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 1013 | // We rely on the DefaultSearchManager to call ApplyDefaultSearchChange if, |
| 1014 | // in fact, the effective DSE changes. |
Angela Yoeurng | eff157d | 2021-10-25 19:49:59 | [diff] [blame] | 1015 | if (url) { |
Mihai Sardarescu | 27fe06b | 2024-03-12 10:07:46 | [diff] [blame] | 1016 | default_search_manager_.SetUserSelectedDefaultSearchEngine( |
| 1017 | url->data(), choice_made_location); |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 1018 | selection_added = true; |
Angela Yoeurng | eff157d | 2021-10-25 19:49:59 | [diff] [blame] | 1019 | } else { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1020 | default_search_manager_.ClearUserSelectedDefaultSearchEngine(); |
Angela Yoeurng | eff157d | 2021-10-25 19:49:59 | [diff] [blame] | 1021 | } |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1022 | } |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 1023 | |
Nicolas Dossou-Gbete | 5dec0735 | 2024-01-22 16:15:39 | [diff] [blame] | 1024 | if (selection_added && |
| 1025 | // The choice record below should only be done when called from a path |
| 1026 | // associated with a fully featured search engine choice screen. |
| 1027 | choice_made_location != search_engines::ChoiceMadeLocation::kOther) { |
| 1028 | CHECK(search_engine_choice_service_); // See b/321280848. |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1029 | search_engine_choice_service_->RecordChoiceMade(choice_made_location, this); |
Nicolas Dossou-Gbete | 9f5f6f0 | 2024-01-08 17:38:23 | [diff] [blame] | 1030 | } |
| 1031 | |
| 1032 | #if BUILDFLAG(IS_ANDROID) |
| 1033 | if (prefs_) { |
| 1034 | // Commit the pref immediately so it isn't lost if the app is killed. |
| 1035 | // TODO(b/316887441): Investigate removing this. |
| 1036 | prefs_->CommitPendingWrite(); |
| 1037 | } |
| 1038 | #endif |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1039 | } |
| 1040 | |
blundell | d130d59 | 2015-06-21 19:29:13 | [diff] [blame] | 1041 | const TemplateURL* TemplateURLService::GetDefaultSearchProvider() const { |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 1042 | return loaded_ ? default_search_provider_.get() |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 1043 | : pre_loading_providers_->default_search_provider(); |
sky@chromium.org | fca94f2 | 2010-09-04 14:54:20 | [diff] [blame] | 1044 | } |
| 1045 | |
Devlin Cronin | 34f1b63d | 2020-06-04 20:45:34 | [diff] [blame] | 1046 | const TemplateURL* |
| 1047 | TemplateURLService::GetDefaultSearchProviderIgnoringExtensions() const { |
| 1048 | std::unique_ptr<TemplateURLData> next_search = |
| 1049 | default_search_manager_.GetDefaultSearchEngineIgnoringExtensions(); |
| 1050 | if (!next_search) |
| 1051 | return nullptr; |
| 1052 | |
| 1053 | // Find the TemplateURL matching the data retrieved. |
Peter Kasting | 03752ef5 | 2022-09-02 18:58:35 | [diff] [blame] | 1054 | auto iter = base::ranges::find_if( |
| 1055 | template_urls_, [this, &next_search](const auto& turl_to_check) { |
| 1056 | return TemplateURL::MatchesData(turl_to_check.get(), next_search.get(), |
| 1057 | search_terms_data()); |
| 1058 | }); |
Devlin Cronin | 34f1b63d | 2020-06-04 20:45:34 | [diff] [blame] | 1059 | return iter == template_urls_.end() ? nullptr : iter->get(); |
| 1060 | } |
| 1061 | |
rlp@chromium.org | 2328ee2 | 2013-08-08 23:00:19 | [diff] [blame] | 1062 | bool TemplateURLService::IsSearchResultsPageFromDefaultSearchProvider( |
blundell | d130d59 | 2015-06-21 19:29:13 | [diff] [blame] | 1063 | const GURL& url) const { |
| 1064 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 1065 | return default_provider && |
| 1066 | default_provider->IsSearchURL(url, search_terms_data()); |
rlp@chromium.org | 2328ee2 | 2013-08-08 23:00:19 | [diff] [blame] | 1067 | } |
| 1068 | |
Moe Ahmadi | 5ca7afb | 2022-10-04 17:39:02 | [diff] [blame] | 1069 | GURL TemplateURLService::GenerateSearchURLForDefaultSearchProvider( |
| 1070 | const std::u16string& search_terms) const { |
| 1071 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 1072 | return default_provider ? default_provider->GenerateSearchURL( |
| 1073 | search_terms_data(), search_terms) |
| 1074 | : GURL(); |
| 1075 | } |
| 1076 | |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1077 | std::optional<TemplateURLService::SearchMetadata> |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1078 | TemplateURLService::ExtractSearchMetadata(const GURL& url) const { |
Tommy C. Li | d95e648 | 2023-01-30 18:54:24 | [diff] [blame] | 1079 | const TemplateURL* template_url = GetTemplateURLForHost(url.host()); |
| 1080 | if (!template_url) { |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1081 | return std::nullopt; |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1082 | } |
| 1083 | |
Tommy C. Li | d95e648 | 2023-01-30 18:54:24 | [diff] [blame] | 1084 | GURL normalized_url; |
| 1085 | std::u16string normalized_search_terms; |
| 1086 | bool is_valid_search_url = |
| 1087 | template_url && template_url->KeepSearchTermsInURL( |
| 1088 | url, search_terms_data(), |
| 1089 | /*keep_search_intent_params=*/true, |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1090 | |
Tommy C. Li | d95e648 | 2023-01-30 18:54:24 | [diff] [blame] | 1091 | /*normalize_search_terms=*/true, &normalized_url, |
| 1092 | &normalized_search_terms); |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1093 | if (!is_valid_search_url) { |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1094 | return std::nullopt; |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1095 | } |
| 1096 | |
Tommy C. Li | 982c3fee | 2023-02-17 19:36:19 | [diff] [blame] | 1097 | return SearchMetadata{template_url, normalized_url, normalized_search_terms}; |
Tommy C. Li | 088b42f | 2022-11-15 00:51:28 | [diff] [blame] | 1098 | } |
| 1099 | |
Tom Lukaszewicz | 9ca12ba | 2022-02-28 21:31:35 | [diff] [blame] | 1100 | bool TemplateURLService::IsSideSearchSupportedForDefaultSearchProvider() const { |
| 1101 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 1102 | return default_provider && default_provider->IsSideSearchSupported(); |
| 1103 | } |
| 1104 | |
Anudeep Palanki | fd1c54e | 2022-09-13 20:03:09 | [diff] [blame] | 1105 | bool TemplateURLService::IsSideImageSearchSupportedForDefaultSearchProvider() |
| 1106 | const { |
| 1107 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 1108 | return default_provider && default_provider->IsSideImageSearchSupported(); |
| 1109 | } |
| 1110 | |
Tom Lukaszewicz | 9ca12ba | 2022-02-28 21:31:35 | [diff] [blame] | 1111 | GURL TemplateURLService::GenerateSideSearchURLForDefaultSearchProvider( |
| 1112 | const GURL& search_url, |
| 1113 | const std::string& version) const { |
| 1114 | DCHECK(IsSideSearchSupportedForDefaultSearchProvider()); |
| 1115 | return GetDefaultSearchProvider()->GenerateSideSearchURL(search_url, version, |
| 1116 | search_terms_data()); |
| 1117 | } |
| 1118 | |
Pengchao Cai | 470355c0d | 2022-10-21 03:01:29 | [diff] [blame] | 1119 | GURL TemplateURLService::RemoveSideSearchParamFromURL( |
| 1120 | const GURL& search_url) const { |
| 1121 | if (!IsSideSearchSupportedForDefaultSearchProvider()) |
| 1122 | return search_url; |
| 1123 | return GetDefaultSearchProvider()->RemoveSideSearchParamFromURL(search_url); |
| 1124 | } |
| 1125 | |
Anudeep Palanki | fd1c54e | 2022-09-13 20:03:09 | [diff] [blame] | 1126 | GURL TemplateURLService::GenerateSideImageSearchURLForDefaultSearchProvider( |
| 1127 | const GURL& search_url, |
| 1128 | const std::string& version) const { |
| 1129 | DCHECK(IsSideImageSearchSupportedForDefaultSearchProvider()); |
| 1130 | return GetDefaultSearchProvider()->GenerateSideImageSearchURL(search_url, |
| 1131 | version); |
| 1132 | } |
| 1133 | |
| 1134 | GURL TemplateURLService::RemoveSideImageSearchParamFromURL( |
| 1135 | const GURL& search_url) const { |
| 1136 | if (!IsSideImageSearchSupportedForDefaultSearchProvider()) |
| 1137 | return search_url; |
| 1138 | return GetDefaultSearchProvider()->RemoveSideImageSearchParamFromURL( |
| 1139 | search_url); |
| 1140 | } |
| 1141 | |
jeffschiller | 9c4df02 | 2017-04-14 00:47:38 | [diff] [blame] | 1142 | bool TemplateURLService::IsExtensionControlledDefaultSearch() const { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1143 | return default_search_provider_source_ == |
| 1144 | DefaultSearchManager::FROM_EXTENSION; |
avayvod@chromium.org | 75a4eca | 2011-10-26 20:40:09 | [diff] [blame] | 1145 | } |
| 1146 | |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1147 | void TemplateURLService::RepairPrepopulatedSearchEngines() { |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 1148 | // Can't clean DB if it hasn't been loaded. |
| 1149 | DCHECK(loaded()); |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 1150 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1151 | Scoper scoper(this); |
| 1152 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1153 | if ((default_search_provider_source_ == DefaultSearchManager::FROM_USER) || |
| 1154 | (default_search_provider_source_ == |
| 1155 | DefaultSearchManager::FROM_FALLBACK)) { |
| 1156 | // Clear |default_search_provider_| in case we want to remove the engine it |
| 1157 | // points to. This will get reset at the end of the function anyway. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1158 | default_search_provider_ = nullptr; |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1159 | } |
| 1160 | |
avi | e8828f2 | 2016-09-02 18:07:58 | [diff] [blame] | 1161 | std::vector<std::unique_ptr<TemplateURLData>> prepopulated_urls = |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1162 | TemplateURLPrepopulateData::GetPrepopulatedEngines( |
| 1163 | prefs_, search_engine_choice_service_, nullptr); |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1164 | DCHECK(!prepopulated_urls.empty()); |
Angela Yoeurng | 6e3d6b7 | 2022-04-18 21:26:17 | [diff] [blame] | 1165 | ActionsFromCurrentData actions(CreateActionsFromCurrentPrepopulateData( |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1166 | &prepopulated_urls, template_urls_, default_search_provider_)); |
pkasting@chromium.org | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 1167 | |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1168 | // Remove items. |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 1169 | for (auto i = actions.removed_engines.begin(); |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1170 | i < actions.removed_engines.end(); ++i) |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1171 | Remove(*i); |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 1172 | |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1173 | // Edit items. |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 1174 | for (auto i(actions.edited_engines.begin()); i < actions.edited_engines.end(); |
| 1175 | ++i) { |
hashimoto@chromium.org | 168d0872 | 2014-06-18 07:13:28 | [diff] [blame] | 1176 | TemplateURL new_values(i->second); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1177 | Update(i->first, new_values); |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 1178 | } |
| 1179 | |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1180 | // Add items. |
erikwright@chromium.org | c6dea6b | 2014-04-30 18:06:04 | [diff] [blame] | 1181 | for (std::vector<TemplateURLData>::const_iterator i = |
| 1182 | actions.added_engines.begin(); |
| 1183 | i < actions.added_engines.end(); |
| 1184 | ++i) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1185 | Add(std::make_unique<TemplateURL>(*i)); |
erikwright@chromium.org | c6dea6b | 2014-04-30 18:06:04 | [diff] [blame] | 1186 | } |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 1187 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1188 | base::AutoReset<DefaultSearchChangeOrigin> change_origin( |
| 1189 | &dsp_change_origin_, DSP_CHANGE_PROFILE_RESET); |
| 1190 | |
| 1191 | default_search_manager_.ClearUserSelectedDefaultSearchEngine(); |
| 1192 | |
pkasting | a078dc8d | 2017-04-07 18:55:50 | [diff] [blame] | 1193 | if (default_search_provider_) { |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 1194 | // Set fallback engine as user selected, because repair is considered a user |
| 1195 | // action and we are expected to sync new fallback engine to other devices. |
| 1196 | const TemplateURLData* fallback_engine_data = |
| 1197 | default_search_manager_.GetFallbackSearchEngine(); |
| 1198 | if (fallback_engine_data) { |
| 1199 | TemplateURL* fallback_engine = |
| 1200 | FindPrepopulatedTemplateURL(fallback_engine_data->prepopulate_id); |
| 1201 | // The fallback engine is created from built-in/override data that should |
| 1202 | // always have a prepopulate ID, so this engine should always exist after |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 1203 | // a repair. |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 1204 | DCHECK(fallback_engine); |
| 1205 | // Write the fallback engine's GUID to prefs, which will cause |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 1206 | // OnDefaultSearchProviderGUIDChanged() to set it as the new |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 1207 | // user-selected engine. |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 1208 | SetDefaultSearchProviderPrefValue(*prefs_, fallback_engine->sync_guid()); |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 1209 | } |
pkasting | a078dc8d | 2017-04-07 18:55:50 | [diff] [blame] | 1210 | } else { |
| 1211 | // If the default search provider came from a user pref we would have been |
| 1212 | // notified of the new (fallback-provided) value in |
| 1213 | // ClearUserSelectedDefaultSearchEngine() above. Since we are here, the |
| 1214 | // value was presumably originally a fallback value (which may have been |
| 1215 | // repaired). |
| 1216 | DefaultSearchManager::Source source; |
| 1217 | const TemplateURLData* new_dse = |
| 1218 | default_search_manager_.GetDefaultSearchEngine(&source); |
pkasting | a078dc8d | 2017-04-07 18:55:50 | [diff] [blame] | 1219 | ApplyDefaultSearchChange(new_dse, source); |
vasilii@chromium.org | e937a970 | 2013-10-03 22:59:43 | [diff] [blame] | 1220 | } |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 1221 | } |
| 1222 | |
Angela Yoeurng | 54419ec6 | 2022-06-07 18:00:01 | [diff] [blame] | 1223 | void TemplateURLService::RepairStarterPackEngines() { |
| 1224 | DCHECK(loaded()); |
| 1225 | |
| 1226 | Scoper scoper(this); |
| 1227 | |
| 1228 | std::vector<std::unique_ptr<TemplateURLData>> starter_pack_engines = |
| 1229 | TemplateURLStarterPackData::GetStarterPackEngines(); |
| 1230 | DCHECK(!starter_pack_engines.empty()); |
| 1231 | ActionsFromCurrentData actions(CreateActionsFromCurrentStarterPackData( |
| 1232 | &starter_pack_engines, template_urls_)); |
| 1233 | |
| 1234 | // Remove items. |
| 1235 | for (auto i = actions.removed_engines.begin(); |
| 1236 | i < actions.removed_engines.end(); ++i) { |
| 1237 | Remove(*i); |
| 1238 | } |
| 1239 | |
| 1240 | // Edit items. |
| 1241 | for (auto i(actions.edited_engines.begin()); i < actions.edited_engines.end(); |
| 1242 | ++i) { |
| 1243 | Update(i->first, TemplateURL(i->second)); |
| 1244 | } |
| 1245 | |
| 1246 | // Add items. |
| 1247 | for (std::vector<TemplateURLData>::const_iterator i = |
| 1248 | actions.added_engines.begin(); |
| 1249 | i < actions.added_engines.end(); ++i) { |
| 1250 | Add(std::make_unique<TemplateURL>(*i)); |
| 1251 | } |
| 1252 | } |
| 1253 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 1254 | void TemplateURLService::AddObserver(TemplateURLServiceObserver* observer) { |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1255 | model_observers_.AddObserver(observer); |
| 1256 | } |
| 1257 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 1258 | void TemplateURLService::RemoveObserver(TemplateURLServiceObserver* observer) { |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1259 | model_observers_.RemoveObserver(observer); |
| 1260 | } |
| 1261 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 1262 | void TemplateURLService::Load() { |
blundell | 1c4f5c4 | 2015-12-14 11:28:17 | [diff] [blame] | 1263 | if (loaded_ || load_handle_ || disable_load_) |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1264 | return; |
| 1265 | |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 1266 | if (web_data_service_) |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 1267 | load_handle_ = web_data_service_->GetKeywords(this); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1268 | else |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 1269 | ChangeToLoadedState(); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1270 | } |
| 1271 | |
Peter Kasting | 7ba9440c | 2020-11-22 01:49:02 | [diff] [blame] | 1272 | base::CallbackListSubscription TemplateURLService::RegisterOnLoadedCallback( |
Ella Ge | 2ee93535 | 2020-12-22 09:44:37 | [diff] [blame] | 1273 | base::OnceClosure callback) { |
Peter Kasting | 7ba9440c | 2020-11-22 01:49:02 | [diff] [blame] | 1274 | return loaded_ ? base::CallbackListSubscription() |
Ella Ge | 2ee93535 | 2020-12-22 09:44:37 | [diff] [blame] | 1275 | : on_loaded_callbacks_.Add(std::move(callback)); |
caitkp@chromium.org | 3118d34 | 2013-10-08 17:29:03 | [diff] [blame] | 1276 | } |
| 1277 | |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 1278 | void TemplateURLService::EmitTemplateURLActiveOnStartupHistogram( |
| 1279 | OwnedTemplateURLVector* template_urls) { |
| 1280 | DCHECK(template_urls); |
| 1281 | |
| 1282 | for (auto& turl : *template_urls) { |
| 1283 | std::string histogram_name = kKeywordModeUsageByEngineTypeHistogramName; |
| 1284 | histogram_name.append( |
| 1285 | (turl->is_active() == TemplateURLData::ActiveStatus::kTrue) |
| 1286 | ? ".ActiveOnStartup" |
| 1287 | : ".InactiveOnStartup"); |
| 1288 | base::UmaHistogramEnumeration( |
| 1289 | histogram_name, turl->GetBuiltinEngineType(), |
| 1290 | BuiltinEngineType::KEYWORD_MODE_ENGINE_TYPE_MAX); |
| 1291 | } |
| 1292 | } |
| 1293 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 1294 | void TemplateURLService::OnWebDataServiceRequestDone( |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 1295 | KeywordWebDataService::Handle h, |
avi | 1ce1e600 | 2016-10-19 17:25:53 | [diff] [blame] | 1296 | std::unique_ptr<WDTypedResult> result) { |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1297 | // Reset the load_handle so that we don't try and cancel the load in |
| 1298 | // the destructor. |
| 1299 | load_handle_ = 0; |
| 1300 | |
| 1301 | if (!result) { |
sky@chromium.org | b3b2d6e | 2009-12-18 00:19:44 | [diff] [blame] | 1302 | // Results are null if the database went away or (most likely) wasn't |
| 1303 | // loaded. |
sky@chromium.org | b3b2d6e | 2009-12-18 00:19:44 | [diff] [blame] | 1304 | load_failed_ = true; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1305 | web_data_service_ = nullptr; |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 1306 | ChangeToLoadedState(); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1307 | return; |
| 1308 | } |
| 1309 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1310 | std::unique_ptr<OwnedTemplateURLVector> template_urls = |
Jinho Bang | fa6b575 | 2018-01-03 20:52:19 | [diff] [blame] | 1311 | std::make_unique<OwnedTemplateURLVector>(); |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1312 | WDKeywordsResult::Metadata updated_keywords_metadata; |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1313 | { |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1314 | GetSearchProvidersUsingKeywordResult( |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1315 | *result, web_data_service_.get(), prefs_, search_engine_choice_service_, |
| 1316 | template_urls.get(), |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1317 | (default_search_provider_source_ == DefaultSearchManager::FROM_USER) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 1318 | ? pre_loading_providers_->default_search_provider() |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1319 | : nullptr, |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1320 | search_terms_data(), updated_keywords_metadata, &pre_sync_deletes_); |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1321 | } |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1322 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1323 | Scoper scoper(this); |
pkasting@chromium.org | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 1324 | |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1325 | { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1326 | PatchMissingSyncGUIDs(template_urls.get()); |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 1327 | MaybeSetIsActiveSearchEngines(template_urls.get()); |
Angela Yoeurng | a79210e | 2022-08-23 19:59:46 | [diff] [blame] | 1328 | EmitTemplateURLActiveOnStartupHistogram(template_urls.get()); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1329 | SetTemplateURLs(std::move(template_urls)); |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1330 | |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1331 | // This initializes provider_map_ which should be done before |
| 1332 | // calling UpdateKeywordSearchTermsForURL. |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1333 | ChangeToLoadedState(); |
| 1334 | |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1335 | // Index any visits that occurred before we finished loading. |
| 1336 | for (size_t i = 0; i < visits_to_add_.size(); ++i) |
| 1337 | UpdateKeywordSearchTermsForURL(visits_to_add_[i]); |
| 1338 | visits_to_add_.clear(); |
| 1339 | |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1340 | if (updated_keywords_metadata.HasBuiltinKeywordData()) { |
Nicolas Dossou-Gbete | 354c10a5 | 2024-01-22 11:18:37 | [diff] [blame] | 1341 | web_data_service_->SetBuiltinKeywordDataVersion( |
| 1342 | updated_keywords_metadata.builtin_keyword_data_version); |
| 1343 | web_data_service_->SetBuiltinKeywordMilestone( |
| 1344 | updated_keywords_metadata.builtin_keyword_milestone); |
| 1345 | web_data_service_->SetBuiltinKeywordCountry( |
| 1346 | updated_keywords_metadata.builtin_keyword_country); |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1347 | } |
Angela Yoeurng | d8e5493 | 2022-04-27 23:53:16 | [diff] [blame] | 1348 | |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1349 | if (updated_keywords_metadata.HasStarterPackData()) { |
Angela Yoeurng | d8e5493 | 2022-04-27 23:53:16 | [diff] [blame] | 1350 | web_data_service_->SetStarterPackKeywordVersion( |
Nicolas Dossou-Gbete | af259e7 | 2024-01-19 20:53:55 | [diff] [blame] | 1351 | updated_keywords_metadata.starter_pack_version); |
| 1352 | } |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 1353 | } |
caitkp@chromium.org | b504a8e | 2014-05-22 12:34:13 | [diff] [blame] | 1354 | |
| 1355 | if (default_search_provider_) { |
Fabio Tirelo | b8f4349 | 2023-07-18 20:28:24 | [diff] [blame] | 1356 | SearchEngineType engine_type = |
| 1357 | default_search_provider_->GetEngineType(search_terms_data()); |
| 1358 | base::UmaHistogramEnumeration("Search.DefaultSearchProviderType2", |
| 1359 | engine_type, SEARCH_ENGINE_MAX); |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 1360 | if (default_search_provider_->created_by_policy() == |
| 1361 | TemplateURLData::CreatedByPolicy::kDefaultSearchProvider) { |
Fabio Tirelo | b8f4349 | 2023-07-18 20:28:24 | [diff] [blame] | 1362 | base::UmaHistogramEnumeration( |
| 1363 | "Search.DefaultSearchProviderType2.SetByEnterprisePolicy", |
| 1364 | engine_type, SEARCH_ENGINE_MAX); |
| 1365 | } |
caitkp@chromium.org | b504a8e | 2014-05-22 12:34:13 | [diff] [blame] | 1366 | } |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1367 | } |
| 1368 | |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 1369 | std::u16string TemplateURLService::GetKeywordShortName( |
| 1370 | const std::u16string& keyword, |
Angela Yoeurng | 9c58924 | 2024-02-15 05:33:08 | [diff] [blame] | 1371 | bool* is_omnibox_api_extension_keyword, |
| 1372 | bool* is_ask_google_keyword) const { |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 1373 | const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); |
mpcomplete@chromium.org | 56ad379 | 2010-05-28 17:45:33 | [diff] [blame] | 1374 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 1375 | // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService |
mpcomplete@chromium.org | 56ad379 | 2010-05-28 17:45:33 | [diff] [blame] | 1376 | // to track changes to the model, this should become a DCHECK. |
| 1377 | if (template_url) { |
Angela Yoeurng | 9c58924 | 2024-02-15 05:33:08 | [diff] [blame] | 1378 | *is_ask_google_keyword = template_url->starter_pack_id() == |
| 1379 | TemplateURLStarterPackData::kAskGoogle; |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1380 | *is_omnibox_api_extension_keyword = |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 1381 | template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION; |
mpcomplete@chromium.org | 56ad379 | 2010-05-28 17:45:33 | [diff] [blame] | 1382 | return template_url->AdjustedShortNameForLocaleDirection(); |
| 1383 | } |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1384 | *is_omnibox_api_extension_keyword = false; |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 1385 | return std::u16string(); |
mpcomplete@chromium.org | 56ad379 | 2010-05-28 17:45:33 | [diff] [blame] | 1386 | } |
| 1387 | |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 1388 | void TemplateURLService::OnHistoryURLVisited(const URLVisitedDetails& details) { |
blundell@chromium.org | a594a01 | 2014-05-17 19:13:16 | [diff] [blame] | 1389 | if (!loaded_) |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 1390 | visits_to_add_.push_back(details); |
blundell@chromium.org | a594a01 | 2014-05-17 19:13:16 | [diff] [blame] | 1391 | else |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 1392 | UpdateKeywordSearchTermsForURL(details); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 1393 | } |
| 1394 | |
caitkp@google.com | ef0c3ac | 2013-04-16 18:05:59 | [diff] [blame] | 1395 | void TemplateURLService::Shutdown() { |
treib | 9f5ce2d4 | 2017-04-13 09:08:03 | [diff] [blame] | 1396 | for (auto& observer : model_observers_) |
| 1397 | observer.OnTemplateURLServiceShuttingDown(); |
| 1398 | |
sdefresne | bb1e575 | 2014-10-20 12:31:17 | [diff] [blame] | 1399 | if (client_) |
| 1400 | client_->Shutdown(); |
caitkp@google.com | ef0c3ac | 2013-04-16 18:05:59 | [diff] [blame] | 1401 | // This check has to be done at Shutdown() instead of in the dtor to ensure |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 1402 | // that no clients of KeywordWebDataService are holding ptrs to it after the |
| 1403 | // first phase of the KeyedService Shutdown() process. |
caitkp@google.com | ef0c3ac | 2013-04-16 18:05:59 | [diff] [blame] | 1404 | if (load_handle_) { |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 1405 | DCHECK(web_data_service_); |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 1406 | web_data_service_->CancelRequest(load_handle_); |
caitkp@google.com | ef0c3ac | 2013-04-16 18:05:59 | [diff] [blame] | 1407 | } |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1408 | web_data_service_ = nullptr; |
caitkp@google.com | ef0c3ac | 2013-04-16 18:05:59 | [diff] [blame] | 1409 | } |
| 1410 | |
Mikel Astiz | 095de45 | 2019-03-11 06:29:58 | [diff] [blame] | 1411 | void TemplateURLService::WaitUntilReadyToSync(base::OnceClosure done) { |
Mikel Astiz | 5c49e65 | 2019-04-02 19:53:56 | [diff] [blame] | 1412 | DCHECK(!on_loaded_callback_for_sync_); |
| 1413 | |
Mikel Astiz | 095de45 | 2019-03-11 06:29:58 | [diff] [blame] | 1414 | // We force a load here to allow remote updates to be processed, without |
| 1415 | // waiting for the lazy load. |
| 1416 | Load(); |
| 1417 | |
| 1418 | if (loaded_) |
| 1419 | std::move(done).Run(); |
| 1420 | else |
| 1421 | on_loaded_callback_for_sync_ = std::move(done); |
| 1422 | } |
| 1423 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1424 | syncer::SyncDataList TemplateURLService::GetAllSyncData( |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1425 | syncer::ModelType type) const { |
| 1426 | DCHECK_EQ(syncer::SEARCH_ENGINES, type); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1427 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1428 | syncer::SyncDataList current_data; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1429 | for (const auto& turl : template_urls_) { |
stevet@chromium.org | c4296fa | 2011-10-15 00:18:07 | [diff] [blame] | 1430 | // We don't sync keywords managed by policy. |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 1431 | if (turl->created_by_policy() != |
| 1432 | TemplateURLData::CreatedByPolicy::kNoPolicy) { |
stevet@chromium.org | c4296fa | 2011-10-15 00:18:07 | [diff] [blame] | 1433 | continue; |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 1434 | } |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1435 | // We don't sync extension-controlled search engines. |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 1436 | if (turl->type() != TemplateURL::NORMAL) |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1437 | continue; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1438 | current_data.push_back(CreateSyncDataFromTemplateURL(*turl)); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1439 | } |
| 1440 | |
| 1441 | return current_data; |
| 1442 | } |
| 1443 | |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1444 | std::optional<syncer::ModelError> TemplateURLService::ProcessSyncChanges( |
Brett Wilson | 190fd2ac | 2017-09-12 05:04:30 | [diff] [blame] | 1445 | const base::Location& from_here, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1446 | const syncer::SyncChangeList& change_list) { |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1447 | if (!models_associated_) { |
Victor Hugo Vianna Silva | d591a08 | 2020-04-16 10:56:36 | [diff] [blame] | 1448 | return syncer::ModelError(FROM_HERE, "Models not yet associated."); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1449 | } |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1450 | DCHECK(loaded_); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1451 | |
dbeam@chromium.org | 997ec9f | 2012-11-21 04:44:14 | [diff] [blame] | 1452 | base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1453 | |
| 1454 | Scoper scoper(this); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1455 | |
stevet@chromium.org | 7124eee | 2012-06-13 22:04:08 | [diff] [blame] | 1456 | // We've started syncing, so set our origin member to the base Sync value. |
| 1457 | // As we move through Sync Code, we may set this to increasingly specific |
| 1458 | // origins so we can tell what exactly caused a DSP change. |
Peter Kasting | bef7bc52 | 2021-09-08 17:53:30 | [diff] [blame] | 1459 | base::AutoReset<DefaultSearchChangeOrigin> change_origin_unintentional( |
| 1460 | &dsp_change_origin_, DSP_CHANGE_SYNC_UNINTENTIONAL); |
stevet@chromium.org | 7124eee | 2012-06-13 22:04:08 | [diff] [blame] | 1461 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1462 | syncer::SyncChangeList new_changes; |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1463 | std::optional<syncer::ModelError> error; |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 1464 | for (auto iter = change_list.begin(); iter != change_list.end(); ++iter) { |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1465 | DCHECK_EQ(syncer::SEARCH_ENGINES, iter->sync_data().GetDataType()); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1466 | |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 1467 | TemplateURL* existing_turl = GetTemplateURLForGUID( |
| 1468 | iter->sync_data().GetSpecifics().search_engine().sync_guid()); |
| 1469 | std::unique_ptr<TemplateURL> turl = |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 1470 | CreateTemplateURLFromTemplateURLAndSyncData( |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1471 | client_.get(), prefs_, search_engine_choice_service_, |
| 1472 | search_terms_data(), existing_turl, iter->sync_data(), |
| 1473 | &new_changes); |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 1474 | if (!turl) |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1475 | continue; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1476 | |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 1477 | const std::string error_msg = |
| 1478 | "ProcessSyncChanges failed on ChangeType " + |
| 1479 | syncer::SyncChange::ChangeTypeToString(iter->change_type()); |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 1480 | if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { |
| 1481 | if (!existing_turl) { |
Tommy C. Li | 8de3d17 | 2023-06-01 19:36:05 | [diff] [blame] | 1482 | // Can't DELETE a non-existent engine. |
Marc Treib | 7bf627d | 2023-01-18 18:17:56 | [diff] [blame] | 1483 | error = syncer::ModelError(FROM_HERE, error_msg); |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 1484 | continue; |
| 1485 | } |
| 1486 | |
| 1487 | // We can get an ACTION_DELETE for the default search provider if the user |
| 1488 | // has changed the default search provider on a different machine, and we |
| 1489 | // get the search engine update before the preference update. |
| 1490 | // |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 1491 | // In this case, postpone the delete, because we never want to reset the |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 1492 | // default search provider as a result of ACTION_DELETE. If the preference |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 1493 | // update arrives later, the engine will be removed. We still may be stuck |
| 1494 | // with an extra search engine entry in the edge case (due to storing the |
| 1495 | // deletion in memory), but it's better than most alternatives. |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 1496 | // |
| 1497 | // In the past, we tried re-creating the deleted TemplateURL, but it was |
| 1498 | // likely a source of duplicate search engine entries. crbug.com/1022775 |
| 1499 | if (existing_turl != GetDefaultSearchProvider()) { |
| 1500 | Remove(existing_turl); |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 1501 | } else { |
| 1502 | postponed_deleted_default_engine_guid_ = existing_turl->sync_guid(); |
Tommy Li | 9c7646a | 2020-10-28 00:47:49 | [diff] [blame] | 1503 | } |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 1504 | continue; |
| 1505 | } |
| 1506 | |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1507 | // Because TemplateURLService sometimes ignores remote Sync changes which |
| 1508 | // we cannot cleanly apply, we need to handle ADD and UPDATE together. |
| 1509 | // Ignore what the other Sync layers THINK the change type is. Instead: |
| 1510 | // If we have an existing engine, treat as an update. |
| 1511 | DCHECK(iter->change_type() == syncer::SyncChange::ACTION_ADD || |
| 1512 | iter->change_type() == syncer::SyncChange::ACTION_UPDATE); |
stevet@chromium.org | c50d76c | 2012-07-10 23:17:58 | [diff] [blame] | 1513 | |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1514 | if (!existing_turl) { |
Peter Kasting | bef7bc52 | 2021-09-08 17:53:30 | [diff] [blame] | 1515 | base::AutoReset<DefaultSearchChangeOrigin> change_origin_add( |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1516 | &dsp_change_origin_, DSP_CHANGE_SYNC_ADD); |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 1517 | // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 1518 | TemplateURLData data(turl->data()); |
| 1519 | data.id = kInvalidTemplateURLID; |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 1520 | |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1521 | TemplateURL* added = Add(std::make_unique<TemplateURL>(data)); |
| 1522 | if (added) { |
| 1523 | MaybeUpdateDSEViaPrefs(added); |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1524 | } |
| 1525 | } else { |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1526 | // Since we've already found |existing_turl| by GUID, this Update() should |
| 1527 | // always return true, but we still don't want to crash if it fails. |
| 1528 | DCHECK(existing_turl); |
| 1529 | bool update_success = Update(existing_turl, *turl); |
| 1530 | DCHECK(update_success); |
| 1531 | |
Peter Kasting | ebaac297 | 2020-04-10 23:54:41 | [diff] [blame] | 1532 | MaybeUpdateDSEViaPrefs(existing_turl); |
Tommy Li | 81a1da0 | 2020-11-30 22:14:07 | [diff] [blame] | 1533 | } |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1534 | } |
| 1535 | |
stevet@chromium.org | deac4290 | 2011-09-03 23:05:56 | [diff] [blame] | 1536 | // If something went wrong, we want to prematurely exit to avoid pushing |
| 1537 | // inconsistent data to Sync. We return the last error we received. |
Marc Treib | 7bf627d | 2023-01-18 18:17:56 | [diff] [blame] | 1538 | if (error) { |
| 1539 | return error; |
| 1540 | } |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1541 | |
Victor Hugo Vianna Silva | d591a08 | 2020-04-16 10:56:36 | [diff] [blame] | 1542 | return sync_processor_->ProcessSyncChanges(from_here, new_changes); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1543 | } |
| 1544 | |
David Bertoni | 724339a80 | 2024-01-04 23:50:28 | [diff] [blame] | 1545 | base::WeakPtr<syncer::SyncableService> TemplateURLService::AsWeakPtr() { |
| 1546 | return weak_ptr_factory_.GetWeakPtr(); |
| 1547 | } |
| 1548 | |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1549 | std::optional<syncer::ModelError> TemplateURLService::MergeDataAndStartSyncing( |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1550 | syncer::ModelType type, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1551 | const syncer::SyncDataList& initial_sync_data, |
Marc Treib | 7bf627d | 2023-01-18 18:17:56 | [diff] [blame] | 1552 | std::unique_ptr<syncer::SyncChangeProcessor> sync_processor) { |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1553 | DCHECK(loaded_); |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1554 | DCHECK_EQ(type, syncer::SEARCH_ENGINES); |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 1555 | DCHECK(!sync_processor_); |
| 1556 | DCHECK(sync_processor); |
erikwright@chromium.org | c4b2af2 | 2014-05-11 19:48:53 | [diff] [blame] | 1557 | |
| 1558 | // Disable sync if we failed to load. |
| 1559 | if (load_failed_) { |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 1560 | return syncer::ModelError(FROM_HERE, "Local database load failed."); |
erikwright@chromium.org | c4b2af2 | 2014-05-11 19:48:53 | [diff] [blame] | 1561 | } |
| 1562 | |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 1563 | sync_processor_ = std::move(sync_processor); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1564 | |
| 1565 | // We do a lot of calls to Add/Remove/ResetTemplateURL here, so ensure we |
| 1566 | // don't step on our own toes. |
dbeam@chromium.org | 997ec9f | 2012-11-21 04:44:14 | [diff] [blame] | 1567 | base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1568 | |
| 1569 | Scoper scoper(this); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1570 | |
stevet@chromium.org | 7124eee | 2012-06-13 22:04:08 | [diff] [blame] | 1571 | // We've started syncing, so set our origin member to the base Sync value. |
| 1572 | // As we move through Sync Code, we may set this to increasingly specific |
| 1573 | // origins so we can tell what exactly caused a DSP change. |
dbeam@chromium.org | 997ec9f | 2012-11-21 04:44:14 | [diff] [blame] | 1574 | base::AutoReset<DefaultSearchChangeOrigin> change_origin(&dsp_change_origin_, |
stevet@chromium.org | 7124eee | 2012-06-13 22:04:08 | [diff] [blame] | 1575 | DSP_CHANGE_SYNC_UNINTENTIONAL); |
| 1576 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1577 | syncer::SyncChangeList new_changes; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1578 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1579 | // Build maps of our sync GUIDs to syncer::SyncData. |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1580 | SyncDataMap local_data_map = CreateGUIDToSyncDataMap( |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1581 | GetAllSyncData(syncer::SEARCH_ENGINES)); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1582 | SyncDataMap sync_data_map = CreateGUIDToSyncDataMap(initial_sync_data); |
| 1583 | |
| 1584 | for (SyncDataMap::const_iterator iter = sync_data_map.begin(); |
| 1585 | iter != sync_data_map.end(); ++iter) { |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 1586 | TemplateURL* local_turl = GetTemplateURLForGUID(iter->first); |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 1587 | std::unique_ptr<TemplateURL> sync_turl( |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 1588 | CreateTemplateURLFromTemplateURLAndSyncData( |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1589 | client_.get(), prefs_, search_engine_choice_service_, |
| 1590 | search_terms_data(), local_turl, iter->second, &new_changes)); |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 1591 | if (!sync_turl) |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1592 | continue; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1593 | |
stevet@chromium.org | 2eff6b1 | 2012-05-16 20:07:05 | [diff] [blame] | 1594 | if (pre_sync_deletes_.find(sync_turl->sync_guid()) != |
| 1595 | pre_sync_deletes_.end()) { |
| 1596 | // This entry was deleted before the initial sync began (possibly through |
| 1597 | // preprocessing in TemplateURLService's loading code). Ignore it and send |
| 1598 | // an ACTION_DELETE up to the server. |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1599 | new_changes.push_back( |
zea@chromium.org | b78170f | 2012-07-11 03:34:26 | [diff] [blame] | 1600 | syncer::SyncChange(FROM_HERE, |
| 1601 | syncer::SyncChange::ACTION_DELETE, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1602 | iter->second)); |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 1603 | UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName, |
| 1604 | DELETE_ENGINE_PRE_SYNC, DELETE_ENGINE_MAX); |
stevet@chromium.org | 2eff6b1 | 2012-05-16 20:07:05 | [diff] [blame] | 1605 | continue; |
| 1606 | } |
| 1607 | |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1608 | if (local_turl) { |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 1609 | DCHECK(IsFromSync(local_turl, sync_data_map)); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1610 | // This local search engine is already synced. If the timestamp differs |
| 1611 | // from Sync, we need to update locally or to the cloud. Note that if the |
| 1612 | // timestamps are equal, we touch neither. |
| 1613 | if (sync_turl->last_modified() > local_turl->last_modified()) { |
stevet@chromium.org | 5a008263 | 2012-01-25 20:08:45 | [diff] [blame] | 1614 | // We've received an update from Sync. We should replace all synced |
| 1615 | // fields in the local TemplateURL. Note that this includes the |
| 1616 | // TemplateURLID and the TemplateURL may have to be reparsed. This |
stevet@chromium.org | deac4290 | 2011-09-03 23:05:56 | [diff] [blame] | 1617 | // also makes the local data's last_modified timestamp equal to Sync's, |
| 1618 | // avoiding an Update on the next MergeData call. |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1619 | Update(local_turl, *sync_turl); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1620 | } else if (sync_turl->last_modified() < local_turl->last_modified()) { |
stevet@chromium.org | deac4290 | 2011-09-03 23:05:56 | [diff] [blame] | 1621 | // Otherwise, we know we have newer data, so update Sync with our |
| 1622 | // data fields. |
akalin@chromium.org | cb02f61 | 2012-06-27 03:15:50 | [diff] [blame] | 1623 | new_changes.push_back( |
zea@chromium.org | b78170f | 2012-07-11 03:34:26 | [diff] [blame] | 1624 | syncer::SyncChange(FROM_HERE, |
| 1625 | syncer::SyncChange::ACTION_UPDATE, |
| 1626 | local_data_map[local_turl->sync_guid()])); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1627 | } |
| 1628 | local_data_map.erase(iter->first); |
| 1629 | } else { |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 1630 | // The search engine from the cloud has not been synced locally. Merge it |
| 1631 | // into our local model. This will handle any conflicts with local (and |
| 1632 | // already-synced) TemplateURLs. It will prefer to keep entries from Sync |
| 1633 | // over not-yet-synced TemplateURLs. |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1634 | MergeInSyncTemplateURL(sync_turl.get(), sync_data_map, &new_changes, |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 1635 | &local_data_map); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1636 | } |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1637 | } |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1638 | |
Sky Malice | ab7ec09 | 2017-11-16 19:24:57 | [diff] [blame] | 1639 | |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1640 | // The remaining SyncData in local_data_map should be everything that needs to |
| 1641 | // be pushed as ADDs to sync. |
| 1642 | for (SyncDataMap::const_iterator iter = local_data_map.begin(); |
| 1643 | iter != local_data_map.end(); ++iter) { |
akalin@chromium.org | cb02f61 | 2012-06-27 03:15:50 | [diff] [blame] | 1644 | new_changes.push_back( |
zea@chromium.org | b78170f | 2012-07-11 03:34:26 | [diff] [blame] | 1645 | syncer::SyncChange(FROM_HERE, |
| 1646 | syncer::SyncChange::ACTION_ADD, |
| 1647 | iter->second)); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1648 | } |
| 1649 | |
stevet@chromium.org | 612ee494 | 2012-05-14 23:55:54 | [diff] [blame] | 1650 | // Do some post-processing on the change list to ensure that we are sending |
| 1651 | // valid changes to sync_processor_. |
| 1652 | PruneSyncChanges(&sync_data_map, &new_changes); |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1653 | |
stevet@chromium.org | 78a857c | 2012-08-21 20:31:48 | [diff] [blame] | 1654 | LogDuplicatesHistogram(GetTemplateURLs()); |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 1655 | std::optional<syncer::ModelError> error = |
Victor Hugo Vianna Silva | d591a08 | 2020-04-16 10:56:36 | [diff] [blame] | 1656 | sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 1657 | if (!error.has_value()) { |
| 1658 | // The ACTION_DELETEs from this set are processed. Empty it so we don't try |
| 1659 | // to reuse them on the next call to MergeDataAndStartSyncing. |
| 1660 | pre_sync_deletes_.clear(); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1661 | |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 1662 | models_associated_ = true; |
| 1663 | } |
stevet@chromium.org | 2eff6b1 | 2012-05-16 20:07:05 | [diff] [blame] | 1664 | |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 1665 | return error; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1666 | } |
| 1667 | |
akalin@chromium.org | a4a14765 | 2012-07-03 23:41:32 | [diff] [blame] | 1668 | void TemplateURLService::StopSyncing(syncer::ModelType type) { |
| 1669 | DCHECK_EQ(type, syncer::SEARCH_ENGINES); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1670 | models_associated_ = false; |
zea@chromium.org | 0677c695 | 2012-03-23 21:59:00 | [diff] [blame] | 1671 | sync_processor_.reset(); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1672 | } |
| 1673 | |
| 1674 | void TemplateURLService::ProcessTemplateURLChange( |
Brett Wilson | 190fd2ac | 2017-09-12 05:04:30 | [diff] [blame] | 1675 | const base::Location& from_here, |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1676 | const TemplateURL* turl, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1677 | syncer::SyncChange::SyncChangeType type) { |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1678 | DCHECK(turl); |
| 1679 | |
| 1680 | if (!models_associated_) |
| 1681 | return; // Not syncing. |
| 1682 | |
| 1683 | if (processing_syncer_changes_) |
| 1684 | return; // These are changes originating from us. Ignore. |
| 1685 | |
stevet@chromium.org | c4296fa | 2011-10-15 00:18:07 | [diff] [blame] | 1686 | // Avoid syncing keywords managed by policy. |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 1687 | if (turl->created_by_policy() != |
| 1688 | TemplateURLData::CreatedByPolicy::kNoPolicy) { |
stevet@chromium.org | c4296fa | 2011-10-15 00:18:07 | [diff] [blame] | 1689 | return; |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 1690 | } |
stevet@chromium.org | c4296fa | 2011-10-15 00:18:07 | [diff] [blame] | 1691 | |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1692 | // Avoid syncing extension-controlled search engines. |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 1693 | if (turl->type() == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION) |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 1694 | return; |
| 1695 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1696 | syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*turl); |
Sky Malice | ab7ec09 | 2017-11-16 19:24:57 | [diff] [blame] | 1697 | syncer::SyncChangeList changes = { |
| 1698 | syncer::SyncChange(from_here, type, sync_data)}; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1699 | sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
| 1700 | } |
| 1701 | |
Xi Han | 1f4c1c5e | 2023-10-20 00:29:51 | [diff] [blame] | 1702 | bool TemplateURLService::IsEeaChoiceCountry() { |
| 1703 | return search_engines::IsEeaChoiceCountry( |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1704 | search_engine_choice_service_->GetCountryId()); |
Xi Han | 1f4c1c5e | 2023-10-20 00:29:51 | [diff] [blame] | 1705 | } |
| 1706 | |
Nicolas Dossou-Gbete | 409217c | 2024-01-09 13:18:36 | [diff] [blame] | 1707 | #if BUILDFLAG(IS_ANDROID) |
| 1708 | bool TemplateURLService::ShouldShowUpdatedSettings() { |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1709 | return search_engine_choice_service_->ShouldShowUpdatedSettings(); |
Nicolas Dossou-Gbete | 409217c | 2024-01-09 13:18:36 | [diff] [blame] | 1710 | } |
| 1711 | #endif |
| 1712 | |
manukh | 87303639 | 2020-11-09 17:23:29 | [diff] [blame] | 1713 | std::string TemplateURLService::GetSessionToken() { |
| 1714 | base::TimeTicks current_time(base::TimeTicks::Now()); |
| 1715 | // Renew token if it expired. |
| 1716 | if (current_time > token_expiration_time_) { |
| 1717 | const size_t kTokenBytes = 12; |
| 1718 | std::string raw_data; |
| 1719 | base::RandBytes(base::WriteInto(&raw_data, kTokenBytes + 1), kTokenBytes); |
| 1720 | base::Base64UrlEncode(raw_data, |
| 1721 | base::Base64UrlEncodePolicy::INCLUDE_PADDING, |
| 1722 | ¤t_token_); |
| 1723 | } |
| 1724 | |
| 1725 | // Extend expiration time another 60 seconds. |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 1726 | token_expiration_time_ = current_time + base::Seconds(60); |
manukh | 87303639 | 2020-11-09 17:23:29 | [diff] [blame] | 1727 | return current_token_; |
| 1728 | } |
| 1729 | |
| 1730 | void TemplateURLService::ClearSessionToken() { |
| 1731 | token_expiration_time_ = base::TimeTicks(); |
| 1732 | } |
| 1733 | |
sky@chromium.org | 7e03e81 | 2010-11-15 23:01:01 | [diff] [blame] | 1734 | // static |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 1735 | TemplateURLData::ActiveStatus TemplateURLService::ActiveStatusFromSync( |
| 1736 | sync_pb::SearchEngineSpecifics_ActiveStatus is_active) { |
| 1737 | switch (is_active) { |
| 1738 | case sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1739 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_UNSPECIFIED: |
| 1740 | return TemplateURLData::ActiveStatus::kUnspecified; |
| 1741 | case sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1742 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_TRUE: |
| 1743 | return TemplateURLData::ActiveStatus::kTrue; |
| 1744 | case sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1745 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_FALSE: |
| 1746 | return TemplateURLData::ActiveStatus::kFalse; |
| 1747 | } |
| 1748 | } |
| 1749 | |
| 1750 | // static |
| 1751 | sync_pb::SearchEngineSpecifics_ActiveStatus |
| 1752 | TemplateURLService::ActiveStatusToSync( |
| 1753 | TemplateURLData::ActiveStatus is_active) { |
| 1754 | switch (is_active) { |
| 1755 | case TemplateURLData::ActiveStatus::kUnspecified: |
| 1756 | return sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1757 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_UNSPECIFIED; |
| 1758 | case TemplateURLData::ActiveStatus::kTrue: |
| 1759 | return sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1760 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_TRUE; |
| 1761 | case TemplateURLData::ActiveStatus::kFalse: |
| 1762 | return sync_pb::SearchEngineSpecifics_ActiveStatus:: |
| 1763 | SearchEngineSpecifics_ActiveStatus_ACTIVE_STATUS_FALSE; |
| 1764 | } |
| 1765 | } |
| 1766 | |
| 1767 | // static |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1768 | syncer::SyncData TemplateURLService::CreateSyncDataFromTemplateURL( |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1769 | const TemplateURL& turl) { |
| 1770 | sync_pb::EntitySpecifics specifics; |
tim@chromium.org | 4557d22 | 2012-03-04 23:33:36 | [diff] [blame] | 1771 | sync_pb::SearchEngineSpecifics* se_specifics = |
| 1772 | specifics.mutable_search_engine(); |
avi@chromium.org | f911df5 | 2013-12-24 23:24:23 | [diff] [blame] | 1773 | se_specifics->set_short_name(base::UTF16ToUTF8(turl.short_name())); |
| 1774 | se_specifics->set_keyword(base::UTF16ToUTF8(turl.keyword())); |
pkasting@chromium.org | 405aae2 | 2012-03-29 20:36:13 | [diff] [blame] | 1775 | se_specifics->set_favicon_url(turl.favicon_url().spec()); |
pkasting@chromium.org | 360ba05 | 2012-04-04 17:26:13 | [diff] [blame] | 1776 | se_specifics->set_url(turl.url()); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1777 | se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); |
| 1778 | se_specifics->set_originating_url(turl.originating_url().spec()); |
| 1779 | se_specifics->set_date_created(turl.date_created().ToInternalValue()); |
brettw | d94a2214 | 2015-07-15 05:19:26 | [diff] [blame] | 1780 | se_specifics->set_input_encodings( |
| 1781 | base::JoinString(turl.input_encodings(), ";")); |
pkasting@chromium.org | 360ba05 | 2012-04-04 17:26:13 | [diff] [blame] | 1782 | se_specifics->set_suggestions_url(turl.suggestions_url()); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1783 | se_specifics->set_prepopulate_id(turl.prepopulate_id()); |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1784 | if (!turl.image_url().empty()) |
| 1785 | se_specifics->set_image_url(turl.image_url()); |
jered@chromium.org | 041238dd | 2013-08-19 21:05:12 | [diff] [blame] | 1786 | se_specifics->set_new_tab_url(turl.new_tab_url()); |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1787 | if (!turl.search_url_post_params().empty()) |
| 1788 | se_specifics->set_search_url_post_params(turl.search_url_post_params()); |
| 1789 | if (!turl.suggestions_url_post_params().empty()) { |
| 1790 | se_specifics->set_suggestions_url_post_params( |
| 1791 | turl.suggestions_url_post_params()); |
| 1792 | } |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1793 | if (!turl.image_url_post_params().empty()) |
| 1794 | se_specifics->set_image_url_post_params(turl.image_url_post_params()); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1795 | se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); |
| 1796 | se_specifics->set_sync_guid(turl.sync_guid()); |
beaudoin@chromium.org | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 1797 | for (size_t i = 0; i < turl.alternate_urls().size(); ++i) |
| 1798 | se_specifics->add_alternate_urls(turl.alternate_urls()[i]); |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 1799 | se_specifics->set_is_active(ActiveStatusToSync(turl.is_active())); |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 1800 | se_specifics->set_starter_pack_id(turl.starter_pack_id()); |
beaudoin@chromium.org | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 1801 | |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1802 | return syncer::SyncData::CreateLocalData(se_specifics->sync_guid(), |
beaudoin@chromium.org | 008987b0 | 2013-01-03 21:22:43 | [diff] [blame] | 1803 | se_specifics->keyword(), |
| 1804 | specifics); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1805 | } |
| 1806 | |
| 1807 | // static |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 1808 | std::unique_ptr<TemplateURL> |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 1809 | TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData( |
| 1810 | TemplateURLServiceClient* client, |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 1811 | PrefService* prefs, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1812 | search_engines::SearchEngineChoiceService* search_engine_choice_service, |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 1813 | const SearchTermsData& search_terms_data, |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 1814 | const TemplateURL* existing_turl, |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1815 | const syncer::SyncData& sync_data, |
| 1816 | syncer::SyncChangeList* change_list) { |
pkasting@chromium.org | 16fca9b8 | 2012-04-23 18:40:26 | [diff] [blame] | 1817 | DCHECK(change_list); |
| 1818 | |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1819 | sync_pb::SearchEngineSpecifics specifics = |
| 1820 | sync_data.GetSpecifics().search_engine(); |
| 1821 | |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1822 | // Past bugs might have caused either of these fields to be empty. Just |
| 1823 | // delete this data off the server. |
| 1824 | if (specifics.url().empty() || specifics.sync_guid().empty()) { |
akalin@chromium.org | cb02f61 | 2012-06-27 03:15:50 | [diff] [blame] | 1825 | change_list->push_back( |
zea@chromium.org | b78170f | 2012-07-11 03:34:26 | [diff] [blame] | 1826 | syncer::SyncChange(FROM_HERE, |
| 1827 | syncer::SyncChange::ACTION_DELETE, |
| 1828 | sync_data)); |
stevet@chromium.org | c3dd789 | 2012-08-27 21:28:28 | [diff] [blame] | 1829 | UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName, |
| 1830 | DELETE_ENGINE_EMPTY_FIELD, DELETE_ENGINE_MAX); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 1831 | return nullptr; |
pkasting@chromium.org | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 1832 | } |
| 1833 | |
Angela Yoeurng | 6d82e5d | 2024-02-14 22:43:11 | [diff] [blame] | 1834 | // Throw out anything from sync that has an invalid starter pack ID. This |
| 1835 | // might happen occasionally when the starter pack gets new entries that are |
| 1836 | // not yet supported in this version of Chrome. |
| 1837 | if (specifics.starter_pack_id() >= |
| 1838 | TemplateURLStarterPackData::kMaxStarterPackID) { |
| 1839 | return nullptr; |
| 1840 | } |
| 1841 | |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 1842 | TemplateURLData data(existing_turl ? |
| 1843 | existing_turl->data() : TemplateURLData()); |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 1844 | data.SetShortName(base::UTF8ToUTF16(specifics.short_name())); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1845 | data.originating_url = GURL(specifics.originating_url()); |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 1846 | std::u16string keyword(base::UTF8ToUTF16(specifics.keyword())); |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1847 | // NOTE: Once this code has shipped in a couple of stable releases, we can |
| 1848 | // probably remove the migration portion, comment out the |
| 1849 | // "autogenerate_keyword" field entirely in the .proto file, and fold the |
| 1850 | // empty keyword case into the "delete data" block above. |
| 1851 | bool reset_keyword = |
| 1852 | specifics.autogenerate_keyword() || specifics.keyword().empty(); |
| 1853 | if (reset_keyword) |
Jan Wilken Dörrie | 756999e | 2021-03-23 15:05:24 | [diff] [blame] | 1854 | keyword = u"dummy"; // Will be replaced below. |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1855 | DCHECK(!keyword.empty()); |
| 1856 | data.SetKeyword(keyword); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1857 | data.SetURL(specifics.url()); |
| 1858 | data.suggestions_url = specifics.suggestions_url(); |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1859 | data.image_url = specifics.image_url(); |
jered@chromium.org | 041238dd | 2013-08-19 21:05:12 | [diff] [blame] | 1860 | data.new_tab_url = specifics.new_tab_url(); |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1861 | data.search_url_post_params = specifics.search_url_post_params(); |
| 1862 | data.suggestions_url_post_params = specifics.suggestions_url_post_params(); |
jnd@chromium.org | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 1863 | data.image_url_post_params = specifics.image_url_post_params(); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1864 | data.favicon_url = GURL(specifics.favicon_url()); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1865 | data.safe_for_autoreplace = specifics.safe_for_autoreplace(); |
brettw | 8be197d1 | 2015-07-23 23:23:31 | [diff] [blame] | 1866 | data.input_encodings = base::SplitString( |
| 1867 | specifics.input_encodings(), ";", |
| 1868 | base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
pkasting@chromium.org | a262230 | 2012-06-27 03:36:07 | [diff] [blame] | 1869 | // If the server data has duplicate encodings, we'll want to push an update |
| 1870 | // below to correct it. Note that we also fix this in |
| 1871 | // GetSearchProvidersUsingKeywordResult(), since otherwise we'd never correct |
| 1872 | // local problems for clients which have disabled search engine sync. |
| 1873 | bool deduped = DeDupeEncodings(&data.input_encodings); |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 1874 | data.date_created = base::Time::FromInternalValue(specifics.date_created()); |
| 1875 | data.last_modified = base::Time::FromInternalValue(specifics.last_modified()); |
| 1876 | data.prepopulate_id = specifics.prepopulate_id(); |
| 1877 | data.sync_guid = specifics.sync_guid(); |
beaudoin@chromium.org | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 1878 | data.alternate_urls.clear(); |
| 1879 | for (int i = 0; i < specifics.alternate_urls_size(); ++i) |
| 1880 | data.alternate_urls.push_back(specifics.alternate_urls(i)); |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 1881 | data.is_active = ActiveStatusFromSync(specifics.is_active()); |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 1882 | data.starter_pack_id = specifics.starter_pack_id(); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 1883 | |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 1884 | std::unique_ptr<TemplateURL> turl(new TemplateURL(data)); |
beaudoin@chromium.org | 10aeaf1 | 2013-02-05 07:41:46 | [diff] [blame] | 1885 | // If this TemplateURL matches a built-in prepopulated template URL, it's |
| 1886 | // possible that sync is trying to modify fields that should not be touched. |
| 1887 | // Revert these fields to the built-in values. |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 1888 | UpdateTemplateURLIfPrepopulated(turl.get(), prefs, |
| 1889 | search_engine_choice_service); |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 1890 | |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 1891 | DCHECK_EQ(TemplateURL::NORMAL, turl->type()); |
pkasting@chromium.org | a262230 | 2012-06-27 03:36:07 | [diff] [blame] | 1892 | if (reset_keyword || deduped) { |
| 1893 | if (reset_keyword) |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 1894 | turl->ResetKeywordIfNecessary(search_terms_data, true); |
Peter Kasting | bef7bc52 | 2021-09-08 17:53:30 | [diff] [blame] | 1895 | syncer::SyncData updated_sync_data = CreateSyncDataFromTemplateURL(*turl); |
| 1896 | change_list->push_back(syncer::SyncChange( |
| 1897 | FROM_HERE, syncer::SyncChange::ACTION_UPDATE, updated_sync_data)); |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 1898 | } else if (turl->IsGoogleSearchURLWithReplaceableKeyword(search_terms_data)) { |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 1899 | if (!existing_turl) { |
| 1900 | // We're adding a new TemplateURL that uses the Google base URL, so set |
| 1901 | // its keyword appropriately for the local environment. |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 1902 | turl->ResetKeywordIfNecessary(search_terms_data, false); |
| 1903 | } else if (existing_turl->IsGoogleSearchURLWithReplaceableKeyword( |
| 1904 | search_terms_data)) { |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 1905 | // Ignore keyword changes triggered by the Google base URL changing on |
| 1906 | // another client. If the base URL changes in this client as well, we'll |
| 1907 | // pick that up separately at the appropriate time. Otherwise, changing |
| 1908 | // the keyword here could result in having the wrong keyword for the local |
| 1909 | // environment. |
| 1910 | turl->data_.SetKeyword(existing_turl->keyword()); |
| 1911 | } |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 1912 | } |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 1913 | |
dcheng | 51ace48a | 2015-12-26 22:45:17 | [diff] [blame] | 1914 | return turl; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1915 | } |
| 1916 | |
| 1917 | // static |
| 1918 | SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( |
akalin@chromium.org | 65f17355 | 2012-06-28 22:43:58 | [diff] [blame] | 1919 | const syncer::SyncDataList& sync_data) { |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1920 | SyncDataMap data_map; |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 1921 | for (auto i(sync_data.begin()); i != sync_data.end(); ++i) |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 1922 | data_map[i->GetSpecifics().search_engine().sync_guid()] = *i; |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 1923 | return data_map; |
| 1924 | } |
| 1925 | |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1926 | void TemplateURLService::Init() { |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 1927 | if (client_) |
| 1928 | client_->SetOwner(this); |
blundell@chromium.org | a594a01 | 2014-05-17 19:13:16 | [diff] [blame] | 1929 | |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 1930 | if (prefs_) { |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 1931 | pref_change_registrar_.Init(prefs_); |
Jens Mueller | 087e5c4 | 2023-10-05 11:36:05 | [diff] [blame] | 1932 | if (search_engines::IsChoiceScreenFlagEnabled( |
| 1933 | search_engines::ChoicePromo::kAny)) { |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 1934 | pref_change_registrar_.Add( |
| 1935 | prefs::kDefaultSearchProviderGUID, |
| 1936 | base::BindRepeating( |
| 1937 | &TemplateURLService::OnDefaultSearchProviderGUIDChanged, |
| 1938 | base::Unretained(this))); |
| 1939 | } else { |
| 1940 | pref_change_registrar_.Add( |
| 1941 | prefs::kSyncedDefaultSearchProviderGUID, |
| 1942 | base::BindRepeating( |
| 1943 | &TemplateURLService::OnDefaultSearchProviderGUIDChanged, |
| 1944 | base::Unretained(this))); |
| 1945 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1946 | } |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1947 | |
| 1948 | DefaultSearchManager::Source source = DefaultSearchManager::FROM_USER; |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 1949 | const TemplateURLData* dse = |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1950 | default_search_manager_.GetDefaultSearchEngine(&source); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 1951 | |
| 1952 | Scoper scoper(this); |
| 1953 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 1954 | ApplyDefaultSearchChange(dse, source); |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1955 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1956 | |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1957 | void TemplateURLService::ApplyInitializersForTesting( |
| 1958 | base::span<const TemplateURLService::Initializer> initializers) { |
| 1959 | // This path is only hit by test code and is used to simulate a loaded |
| 1960 | // TemplateURLService. |
| 1961 | CHECK_IS_TEST(); |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1962 | |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1963 | if (initializers.empty()) { |
| 1964 | return; |
| 1965 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1966 | |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1967 | ChangeToLoadedState(); |
pkasting@chromium.org | 56fa2959 | 2013-07-02 20:25:53 | [diff] [blame] | 1968 | |
Nicolas Dossou-Gbete | 0a72d073 | 2024-01-04 16:21:54 | [diff] [blame] | 1969 | // Add specific initializers, if any. |
| 1970 | for (size_t i = 0; i < initializers.size(); ++i) { |
| 1971 | CHECK(initializers[i].keyword); |
| 1972 | CHECK(initializers[i].url); |
| 1973 | CHECK(initializers[i].content); |
| 1974 | |
| 1975 | // TemplateURLService ends up owning the TemplateURL, don't try and free |
| 1976 | // it. |
| 1977 | TemplateURLData data; |
| 1978 | data.SetShortName(base::UTF8ToUTF16(initializers[i].content)); |
| 1979 | data.SetKeyword(base::UTF8ToUTF16(initializers[i].keyword)); |
| 1980 | data.SetURL(initializers[i].url); |
| 1981 | // Set all to active by default for testing purposes. |
| 1982 | data.is_active = TemplateURLData::ActiveStatus::kTrue; |
| 1983 | Add(std::make_unique<TemplateURL>(data)); |
| 1984 | |
| 1985 | // Set the first provided identifier to be the default. |
| 1986 | if (i == 0) { |
Mihai Sardarescu | 27fe06b | 2024-03-12 10:07:46 | [diff] [blame] | 1987 | default_search_manager_.SetUserSelectedDefaultSearchEngine( |
| 1988 | data, search_engines::ChoiceMadeLocation::kOther); |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 1989 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1990 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 1991 | } |
| 1992 | |
Kevin Bailey | 499298a | 2018-03-16 14:54:43 | [diff] [blame] | 1993 | void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 1994 | const std::u16string& keyword = template_url->keyword(); |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 1995 | |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 1996 | // Remove from |keyword_to_turl_|. No need to find the best |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 1997 | // fallback. We choose the best one as-needed from the multimap. |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 1998 | const auto match_range = keyword_to_turl_.equal_range(keyword); |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 1999 | for (auto it = match_range.first; it != match_range.second;) { |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2000 | if (it->second == template_url) { |
| 2001 | it = keyword_to_turl_.erase(it); |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2002 | } else { |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 2003 | ++it; |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2004 | } |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2005 | } |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2006 | |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 2007 | if (template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION) |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 2008 | return; |
| 2009 | |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 2010 | if (!template_url->sync_guid().empty()) { |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2011 | guid_to_turl_.erase(template_url->sync_guid()); |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 2012 | if (postponed_deleted_default_engine_guid_ == template_url->sync_guid()) { |
| 2013 | // `template_url` has been updated locally or removed, discard incoming |
| 2014 | // deletion. |
| 2015 | postponed_deleted_default_engine_guid_.clear(); |
| 2016 | } |
| 2017 | } |
| 2018 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2019 | if (template_url->created_by_policy() == |
| 2020 | TemplateURLData::CreatedByPolicy::kSiteSearch) { |
| 2021 | enterprise_site_search_keyword_to_turl_.erase(keyword); |
| 2022 | } |
| 2023 | |
erikwright@chromium.org | 5f13765 | 2014-05-14 00:02:19 | [diff] [blame] | 2024 | // |provider_map_| is only initialized after loading has completed. |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 2025 | if (loaded_) { |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 2026 | provider_map_->Remove(template_url); |
pkasting@chromium.org | 317dec7 | 2012-06-05 20:58:30 | [diff] [blame] | 2027 | } |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 2028 | } |
| 2029 | |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 2030 | void TemplateURLService::AddToMaps(TemplateURL* template_url) { |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 2031 | const std::u16string& keyword = template_url->keyword(); |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2032 | keyword_to_turl_.insert(std::make_pair(keyword, template_url)); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2033 | |
Tommy Li | 70e3528 | 2020-11-11 23:52:56 | [diff] [blame] | 2034 | if (template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION) |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 2035 | return; |
| 2036 | |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2037 | if (!template_url->sync_guid().empty()) |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2038 | guid_to_turl_[template_url->sync_guid()] = template_url; |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2039 | |
| 2040 | if (template_url->created_by_policy() == |
| 2041 | TemplateURLData::CreatedByPolicy::kSiteSearch) { |
| 2042 | enterprise_site_search_keyword_to_turl_[keyword] = template_url; |
| 2043 | } |
| 2044 | |
erikwright@chromium.org | 5f13765 | 2014-05-14 00:02:19 | [diff] [blame] | 2045 | // |provider_map_| is only initialized after loading has completed. |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 2046 | if (loaded_) |
| 2047 | provider_map_->Add(template_url, search_terms_data()); |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 2048 | } |
| 2049 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2050 | void TemplateURLService::SetTemplateURLs( |
| 2051 | std::unique_ptr<OwnedTemplateURLVector> urls) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2052 | Scoper scoper(this); |
| 2053 | |
pkasting@chromium.org | 224cfac | 2013-09-16 21:22:29 | [diff] [blame] | 2054 | // Partition the URLs first, instead of implementing the loops below by simply |
| 2055 | // scanning the input twice. While it's not supposed to happen normally, it's |
| 2056 | // possible for corrupt databases to return multiple entries with the same |
| 2057 | // keyword. In this case, the first loop may delete the first entry when |
| 2058 | // adding the second. If this happens, the second loop must not attempt to |
| 2059 | // access the deleted entry. Partitioning ensures this constraint. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2060 | auto first_invalid = std::partition( |
| 2061 | urls->begin(), urls->end(), [](const std::unique_ptr<TemplateURL>& turl) { |
| 2062 | return turl->id() != kInvalidTemplateURLID; |
| 2063 | }); |
pkasting@chromium.org | 224cfac | 2013-09-16 21:22:29 | [diff] [blame] | 2064 | |
| 2065 | // First, add the items that already have id's, so that the next_id_ gets |
| 2066 | // properly set. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2067 | for (auto i = urls->begin(); i != first_invalid; ++i) { |
pkasting@chromium.org | 224cfac | 2013-09-16 21:22:29 | [diff] [blame] | 2068 | next_id_ = std::max(next_id_, (*i)->id()); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2069 | Add(std::move(*i), false); |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 2070 | } |
levin@chromium.org | e1ddda0 | 2010-08-26 19:43:48 | [diff] [blame] | 2071 | |
| 2072 | // Next add the new items that don't have id's. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2073 | for (auto i = first_invalid; i != urls->end(); ++i) |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2074 | Add(std::move(*i)); |
levin@chromium.org | ce75ec6 | 2010-08-21 00:34:46 | [diff] [blame] | 2075 | } |
| 2076 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 2077 | void TemplateURLService::ChangeToLoadedState() { |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 2078 | DCHECK(!loaded_); |
| 2079 | |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 2080 | provider_map_->Init(template_urls_, search_terms_data()); |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 2081 | loaded_ = true; |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 2082 | |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2083 | ApplyDefaultSearchChangeNoMetrics( |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2084 | pre_loading_providers_->default_search_provider() |
| 2085 | ? &pre_loading_providers_->default_search_provider()->data() |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2086 | : nullptr, |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2087 | default_search_provider_source_); |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2088 | if (base::FeatureList::IsEnabled(omnibox::kSiteSearchSettingsPolicy)) { |
| 2089 | ApplyEnterpriseSiteSearchChanges( |
| 2090 | pre_loading_providers_->TakeSiteSearchEngines()); |
| 2091 | } |
| 2092 | pre_loading_providers_.reset(); |
robliao | 66fe8b19 | 2015-03-13 01:29:18 | [diff] [blame] | 2093 | |
Mikel Astiz | 095de45 | 2019-03-11 06:29:58 | [diff] [blame] | 2094 | if (on_loaded_callback_for_sync_) |
| 2095 | std::move(on_loaded_callback_for_sync_).Run(); |
| 2096 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2097 | on_loaded_callbacks_.Notify(); |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2098 | } |
| 2099 | |
mpearson | 511ce60b | 2015-05-23 23:47:09 | [diff] [blame] | 2100 | bool TemplateURLService::CanAddAutogeneratedKeywordForHost( |
jeffschiller | 9c4df02 | 2017-04-14 00:47:38 | [diff] [blame] | 2101 | const std::string& host) const { |
pkasting@chromium.org | 3613347d | 2012-04-27 20:27:37 | [diff] [blame] | 2102 | const TemplateURLSet* urls = provider_map_->GetURLsForHost(host); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2103 | if (!urls) |
| 2104 | return true; |
Denis Yaroshevskiy | 442ae06 | 2018-03-12 12:35:42 | [diff] [blame] | 2105 | |
Peter Kasting | 913b9b85 | 2022-08-31 13:45:30 | [diff] [blame] | 2106 | return base::ranges::all_of(*urls, [](const TemplateURL* turl) { |
Denis Yaroshevskiy | 442ae06 | 2018-03-12 12:35:42 | [diff] [blame] | 2107 | return turl->safe_for_autoreplace(); |
| 2108 | }); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2109 | } |
| 2110 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2111 | bool TemplateURLService::Update(TemplateURL* existing_turl, |
| 2112 | const TemplateURL& new_values) { |
levin@chromium.org | 98d0f921 | 2010-08-24 05:12:55 | [diff] [blame] | 2113 | DCHECK(existing_turl); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2114 | if (!Contains(&template_urls_, existing_turl)) |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2115 | return false; |
levin@chromium.org | 98d0f921 | 2010-08-24 05:12:55 | [diff] [blame] | 2116 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2117 | Scoper scoper(this); |
| 2118 | model_mutated_notification_pending_ = true; |
| 2119 | |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 2120 | TemplateURLID previous_id = existing_turl->id(); |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 2121 | RemoveFromMaps(existing_turl); |
| 2122 | |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2123 | // Update existing turl with new values and add back to the map. |
| 2124 | // We don't do any keyword conflict handling here, as TemplateURLService |
| 2125 | // already can pick the best engine out of duplicates. Replaceable duplicates |
| 2126 | // will be culled during next startup's Add() loop. We did this to keep |
| 2127 | // Update() simple: it never fails, and never deletes |existing_engine|. |
Alexander Yashkin | a5bb8be | 2018-04-03 06:51:13 | [diff] [blame] | 2128 | existing_turl->CopyFrom(new_values); |
| 2129 | existing_turl->data_.id = previous_id; |
levin@chromium.org | 98d0f921 | 2010-08-24 05:12:55 | [diff] [blame] | 2130 | |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 2131 | AddToMaps(existing_turl); |
| 2132 | |
| 2133 | if (existing_turl->type() == TemplateURL::NORMAL) { |
| 2134 | if (web_data_service_) |
| 2135 | web_data_service_->UpdateKeyword(existing_turl->data()); |
| 2136 | |
| 2137 | // Inform sync of the update. |
| 2138 | ProcessTemplateURLChange(FROM_HERE, existing_turl, |
| 2139 | syncer::SyncChange::ACTION_UPDATE); |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2140 | } |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2141 | |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 2142 | // Even if the DSE is controlled by an extension or policy, update the user |
| 2143 | // preferences as they may take over later. |
| 2144 | if (default_search_provider_source_ != DefaultSearchManager::FROM_FALLBACK) |
| 2145 | MaybeUpdateDSEViaPrefs(existing_turl); |
a-v-y | 9e4f54d | 2017-03-29 14:50:36 | [diff] [blame] | 2146 | |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2147 | return true; |
levin@chromium.org | 98d0f921 | 2010-08-24 05:12:55 | [diff] [blame] | 2148 | } |
| 2149 | |
beaudoin@chromium.org | 10aeaf1 | 2013-02-05 07:41:46 | [diff] [blame] | 2150 | // static |
| 2151 | void TemplateURLService::UpdateTemplateURLIfPrepopulated( |
| 2152 | TemplateURL* template_url, |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 2153 | PrefService* prefs, |
| 2154 | search_engines::SearchEngineChoiceService* search_engine_choice_service) { |
beaudoin@chromium.org | 10aeaf1 | 2013-02-05 07:41:46 | [diff] [blame] | 2155 | int prepopulate_id = template_url->prepopulate_id(); |
| 2156 | if (template_url->prepopulate_id() == 0) |
| 2157 | return; |
| 2158 | |
avi | e8828f2 | 2016-09-02 18:07:58 | [diff] [blame] | 2159 | std::vector<std::unique_ptr<TemplateURLData>> prepopulated_urls = |
Boris Sazonov | 2b77815a | 2024-01-17 15:35:04 | [diff] [blame] | 2160 | TemplateURLPrepopulateData::GetPrepopulatedEngines( |
| 2161 | prefs, search_engine_choice_service, nullptr); |
beaudoin@chromium.org | 10aeaf1 | 2013-02-05 07:41:46 | [diff] [blame] | 2162 | |
avi | e8828f2 | 2016-09-02 18:07:58 | [diff] [blame] | 2163 | for (const auto& url : prepopulated_urls) { |
| 2164 | if (url->prepopulate_id == prepopulate_id) { |
Angela Yoeurng | 6e3d6b7 | 2022-04-18 21:26:17 | [diff] [blame] | 2165 | MergeIntoEngineData(template_url, url.get()); |
avi | e8828f2 | 2016-09-02 18:07:58 | [diff] [blame] | 2166 | template_url->CopyFrom(TemplateURL(*url)); |
beaudoin@chromium.org | 10aeaf1 | 2013-02-05 07:41:46 | [diff] [blame] | 2167 | } |
| 2168 | } |
| 2169 | } |
| 2170 | |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 2171 | void TemplateURLService::MaybeUpdateDSEViaPrefs(TemplateURL* synced_turl) { |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2172 | if (prefs_ && (synced_turl->sync_guid() == |
| 2173 | GetDefaultSearchProviderPrefValue(*prefs_))) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2174 | default_search_manager_.SetUserSelectedDefaultSearchEngine( |
Mihai Sardarescu | 27fe06b | 2024-03-12 10:07:46 | [diff] [blame] | 2175 | synced_turl->data(), search_engines::ChoiceMadeLocation::kOther); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2176 | } |
| 2177 | } |
| 2178 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 2179 | void TemplateURLService::UpdateKeywordSearchTermsForURL( |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2180 | const URLVisitedDetails& details) { |
| 2181 | if (!details.url.is_valid()) |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2182 | return; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2183 | |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 2184 | const TemplateURLSet* urls_for_host = |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2185 | provider_map_->GetURLsForHost(details.url.host()); |
levin@chromium.org | d852274 | 2010-08-27 17:55:44 | [diff] [blame] | 2186 | if (!urls_for_host) |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2187 | return; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2188 | |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 2189 | TemplateURL* visited_url = nullptr; |
jdoerrie | 3feb185 | 2018-10-05 12:16:44 | [diff] [blame] | 2190 | for (auto i = urls_for_host->begin(); i != urls_for_host->end(); ++i) { |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 2191 | std::u16string search_terms; |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2192 | if ((*i)->ExtractSearchTermsFromURL(details.url, search_terms_data(), |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 2193 | &search_terms) && |
beaudoin@chromium.org | 67d8b75 | 2013-04-03 17:33:27 | [diff] [blame] | 2194 | !search_terms.empty()) { |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2195 | if (details.is_keyword_transition) { |
sky@chromium.org | 0bfc29a | 2009-04-27 16:15:44 | [diff] [blame] | 2196 | // The visit is the result of the user entering a keyword, generate a |
| 2197 | // KEYWORD_GENERATED visit for the KEYWORD so that the keyword typed |
| 2198 | // count is boosted. |
| 2199 | AddTabToSearchVisit(**i); |
| 2200 | } |
hashimoto | 3113536 | 2014-08-29 09:19:45 | [diff] [blame] | 2201 | if (client_) { |
| 2202 | client_->SetKeywordSearchTermsForURL( |
| 2203 | details.url, (*i)->id(), search_terms); |
| 2204 | } |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 2205 | // Caches the matched TemplateURL so its last_visited could be updated |
| 2206 | // later after iteration. |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2207 | // Note: Update() will replace the entry from the container of this |
| 2208 | // iterator, so update here directly will cause an error about it. |
a-v-y | 7084ddf | 2017-03-09 13:15:48 | [diff] [blame] | 2209 | if (!IsCreatedByExtension(*i)) |
| 2210 | visited_url = *i; |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2211 | } |
| 2212 | } |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 2213 | if (visited_url) |
| 2214 | UpdateTemplateURLVisitTime(visited_url); |
ben@chromium.org | d82443b | 2009-01-15 19:54:56 | [diff] [blame] | 2215 | } |
| 2216 | |
ltian | 035c572 | 2017-01-10 00:35:39 | [diff] [blame] | 2217 | void TemplateURLService::UpdateTemplateURLVisitTime(TemplateURL* url) { |
| 2218 | TemplateURLData data(url->data()); |
| 2219 | data.last_visited = clock_->Now(); |
| 2220 | Update(url, TemplateURL(data)); |
| 2221 | } |
| 2222 | |
erg@google.com | 8e5c89a | 2011-06-07 18:13:33 | [diff] [blame] | 2223 | void TemplateURLService::AddTabToSearchVisit(const TemplateURL& t_url) { |
sky@chromium.org | 0bfc29a | 2009-04-27 16:15:44 | [diff] [blame] | 2224 | // Only add visits for entries the user hasn't modified. If the user modified |
| 2225 | // the entry the keyword may no longer correspond to the host name. It may be |
| 2226 | // possible to do something more sophisticated here, but it's so rare as to |
| 2227 | // not be worth it. |
| 2228 | if (!t_url.safe_for_autoreplace()) |
| 2229 | return; |
| 2230 | |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2231 | if (!client_) |
sky@chromium.org | 0bfc29a | 2009-04-27 16:15:44 | [diff] [blame] | 2232 | return; |
| 2233 | |
rsleevi | 24f64dc2 | 2015-08-07 21:39:21 | [diff] [blame] | 2234 | GURL url(url_formatter::FixupURL(base::UTF16ToUTF8(t_url.keyword()), |
| 2235 | std::string())); |
sky@chromium.org | 0bfc29a | 2009-04-27 16:15:44 | [diff] [blame] | 2236 | if (!url.is_valid()) |
| 2237 | return; |
| 2238 | |
| 2239 | // Synthesize a visit for the keyword. This ensures the url for the keyword is |
| 2240 | // autocompleted even if the user doesn't type the url in directly. |
hashimoto@chromium.org | 7e31042 | 2014-07-03 12:44:45 | [diff] [blame] | 2241 | client_->AddKeywordGeneratedVisit(url); |
| 2242 | } |
| 2243 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2244 | void TemplateURLService::ApplyDefaultSearchChange( |
| 2245 | const TemplateURLData* data, |
| 2246 | DefaultSearchManager::Source source) { |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2247 | if (!ApplyDefaultSearchChangeNoMetrics(data, source)) |
| 2248 | return; |
| 2249 | |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2250 | if (GetDefaultSearchProvider() && |
hashimoto@chromium.org | 82fe07e | 2014-07-02 07:40:22 | [diff] [blame] | 2251 | GetDefaultSearchProvider()->HasGoogleBaseURLs(search_terms_data()) && |
| 2252 | !dsp_change_callback_.is_null()) |
| 2253 | dsp_change_callback_.Run(); |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2254 | } |
| 2255 | |
Jack Yammine | f973df62 | 2023-09-05 14:57:11 | [diff] [blame] | 2256 | bool TemplateURLService::ApplyDefaultSearchChangeForTesting( |
| 2257 | const TemplateURLData* data, |
| 2258 | DefaultSearchManager::Source source) { |
| 2259 | CHECK_IS_TEST(); |
| 2260 | return ApplyDefaultSearchChangeNoMetrics(data, source); |
| 2261 | } |
| 2262 | |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2263 | bool TemplateURLService::ApplyDefaultSearchChangeNoMetrics( |
| 2264 | const TemplateURLData* data, |
| 2265 | DefaultSearchManager::Source source) { |
Tommy Li | 388759a | 2020-04-17 22:06:06 | [diff] [blame] | 2266 | // We do not want any sort of reentrancy while changing the default search |
| 2267 | // engine. This can occur when resolving conflicting entries. In those cases, |
| 2268 | // it's best to early exit and let the original process finish. |
| 2269 | if (applying_default_search_engine_change_) |
| 2270 | return false; |
| 2271 | base::AutoReset<bool> applying_change(&applying_default_search_engine_change_, |
| 2272 | true); |
| 2273 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2274 | if (!loaded_) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2275 | // Set pre-loading default search provider from the preferences. This is |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2276 | // mainly so we can hold ownership until we get to the point where the list |
| 2277 | // of keywords from Web Data is the owner of everything including the |
| 2278 | // default. |
a-v-y | ef5c7c7 | 2017-04-14 09:06:40 | [diff] [blame] | 2279 | bool changed = !TemplateURL::MatchesData( |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2280 | pre_loading_providers_->default_search_provider(), data, |
| 2281 | search_terms_data()); |
a-v-y | 858416e | 2017-03-01 16:42:45 | [diff] [blame] | 2282 | TemplateURL::Type initial_engine_type = |
| 2283 | (source == DefaultSearchManager::FROM_EXTENSION) |
| 2284 | ? TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION |
| 2285 | : TemplateURL::NORMAL; |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2286 | pre_loading_providers_->set_default_search_provider( |
Jinho Bang | fa6b575 | 2018-01-03 20:52:19 | [diff] [blame] | 2287 | data ? std::make_unique<TemplateURL>(*data, initial_engine_type) |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2288 | : nullptr); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2289 | default_search_provider_source_ = source; |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2290 | return changed; |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2291 | } |
hclam@chromium.org | d63488d | 2014-05-10 20:48:27 | [diff] [blame] | 2292 | |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2293 | // This may be deleted later. Use exclusively for pointer comparison to detect |
| 2294 | // a change. |
| 2295 | TemplateURL* previous_default_search_engine = default_search_provider_; |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2296 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2297 | Scoper scoper(this); |
| 2298 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2299 | if (default_search_provider_source_ == DefaultSearchManager::FROM_POLICY || |
Igor Ruvinov | f266d2a4 | 2022-06-24 17:52:16 | [diff] [blame] | 2300 | default_search_provider_source_ == |
| 2301 | DefaultSearchManager::FROM_POLICY_RECOMMENDED || |
| 2302 | source == DefaultSearchManager::FROM_POLICY || |
| 2303 | source == DefaultSearchManager::FROM_POLICY_RECOMMENDED) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2304 | // We do this both to remove any no-longer-applicable policy-defined DSE as |
| 2305 | // well as to add the new one, if appropriate. |
Fabio Tirelo | 41316deb | 2023-11-24 21:33:11 | [diff] [blame] | 2306 | UpdateDefaultProvidersCreatedByPolicy( |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2307 | &template_urls_, |
Igor Ruvinov | f266d2a4 | 2022-06-24 17:52:16 | [diff] [blame] | 2308 | source == DefaultSearchManager::FROM_POLICY || |
| 2309 | source == DefaultSearchManager::FROM_POLICY_RECOMMENDED |
| 2310 | ? data |
| 2311 | : nullptr, |
| 2312 | /*is_mandatory=*/source == DefaultSearchManager::FROM_POLICY); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2313 | } |
| 2314 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2315 | // |default_search_provider_source_| must be set before calling Update(), |
| 2316 | // since that function needs to know the source of the update in question. |
a-v-y | 02d3f50b | 2017-02-16 12:03:55 | [diff] [blame] | 2317 | default_search_provider_source_ = source; |
| 2318 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2319 | if (!data) { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2320 | default_search_provider_ = nullptr; |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2321 | } else if (source == DefaultSearchManager::FROM_EXTENSION) { |
a-v-y | f4eb435 | 2017-02-25 18:46:59 | [diff] [blame] | 2322 | default_search_provider_ = FindMatchingDefaultExtensionTemplateURL(*data); |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2323 | } else if (source == DefaultSearchManager::FROM_FALLBACK) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2324 | default_search_provider_ = |
| 2325 | FindPrepopulatedTemplateURL(data->prepopulate_id); |
| 2326 | if (default_search_provider_) { |
| 2327 | TemplateURLData update_data(*data); |
| 2328 | update_data.sync_guid = default_search_provider_->sync_guid(); |
Tommy C. Li | 482ddff | 2019-03-09 00:42:23 | [diff] [blame] | 2329 | |
| 2330 | // Now that we are auto-updating the favicon_url as the user browses, |
| 2331 | // respect the favicon_url entry in the database, instead of falling back |
| 2332 | // to the one in the prepopulated list. |
| 2333 | update_data.favicon_url = default_search_provider_->favicon_url(); |
| 2334 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2335 | if (!default_search_provider_->safe_for_autoreplace()) { |
| 2336 | update_data.safe_for_autoreplace = false; |
| 2337 | update_data.SetKeyword(default_search_provider_->keyword()); |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 2338 | update_data.SetShortName(default_search_provider_->short_name()); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2339 | } |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2340 | Update(default_search_provider_, TemplateURL(update_data)); |
hclam@chromium.org | d63488d | 2014-05-10 20:48:27 | [diff] [blame] | 2341 | } else { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2342 | // Normally the prepopulated fallback should be present in |
| 2343 | // |template_urls_|, but in a few cases it might not be: |
| 2344 | // (1) Tests that initialize the TemplateURLService in peculiar ways. |
| 2345 | // (2) If the user deleted the pre-populated default and we subsequently |
| 2346 | // lost their user-selected value. |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2347 | default_search_provider_ = Add(std::make_unique<TemplateURL>(*data)); |
Tommy Li | 2d7174dc | 2021-01-13 19:45:28 | [diff] [blame] | 2348 | DCHECK(default_search_provider_) |
| 2349 | << "Add() to repair the DSE must never fail."; |
hclam@chromium.org | d63488d | 2014-05-10 20:48:27 | [diff] [blame] | 2350 | } |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2351 | } else if (source == DefaultSearchManager::FROM_USER) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2352 | default_search_provider_ = GetTemplateURLForGUID(data->sync_guid); |
| 2353 | if (!default_search_provider_ && data->prepopulate_id) { |
| 2354 | default_search_provider_ = |
| 2355 | FindPrepopulatedTemplateURL(data->prepopulate_id); |
hclam@chromium.org | d63488d | 2014-05-10 20:48:27 | [diff] [blame] | 2356 | } |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2357 | TemplateURLData new_data(*data); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2358 | if (default_search_provider_) { |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2359 | Update(default_search_provider_, TemplateURL(new_data)); |
jeanluc@google.com | 14154f8 | 2010-10-07 00:22:46 | [diff] [blame] | 2360 | } else { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2361 | new_data.id = kInvalidTemplateURLID; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2362 | default_search_provider_ = Add(std::make_unique<TemplateURL>(new_data)); |
Tommy Li | 2d7174dc | 2021-01-13 19:45:28 | [diff] [blame] | 2363 | DCHECK(default_search_provider_) |
| 2364 | << "Add() to repair the DSE must never fail."; |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2365 | } |
hashimoto@chromium.org | 20c0fb30 | 2014-06-28 02:04:12 | [diff] [blame] | 2366 | if (default_search_provider_ && prefs_) { |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2367 | SetDefaultSearchProviderPrefValue(*prefs_, |
| 2368 | default_search_provider_->sync_guid()); |
hclam@chromium.org | d63488d | 2014-05-10 20:48:27 | [diff] [blame] | 2369 | } |
| 2370 | } |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2371 | |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 2372 | if (default_search_provider_ == previous_default_search_engine) { |
| 2373 | // Default search engine hasn't changed. |
| 2374 | return false; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2375 | } |
erikwright@chromium.org | c2de25b | 2014-05-23 01:02:58 | [diff] [blame] | 2376 | |
Rushan Suleymanov | b25693f | 2023-09-22 15:21:32 | [diff] [blame] | 2377 | model_mutated_notification_pending_ = true; |
| 2378 | if (!postponed_deleted_default_engine_guid_.empty()) { |
| 2379 | // There was a postponed deletion for the previous default search engine, |
| 2380 | // remove it now. |
| 2381 | TemplateURL* existing_turl = |
| 2382 | GetTemplateURLForGUID(postponed_deleted_default_engine_guid_); |
| 2383 | if (existing_turl) { |
| 2384 | // Remove() below CHECKs that the current default search engine is not |
| 2385 | // deleted. |
| 2386 | Remove(existing_turl); |
| 2387 | } |
| 2388 | postponed_deleted_default_engine_guid_.clear(); |
| 2389 | } |
| 2390 | |
| 2391 | return true; |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2392 | } |
| 2393 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2394 | void TemplateURLService::ApplyEnterpriseSiteSearchChanges( |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2395 | TemplateURLService::OwnedTemplateURLVector&& policy_site_search_engines) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2396 | CHECK(loaded_); |
| 2397 | |
| 2398 | Scoper scoper(this); |
| 2399 | |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2400 | LogSiteSearchPolicyConflict(policy_site_search_engines); |
| 2401 | |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2402 | base::flat_set<std::u16string> new_keywords; |
| 2403 | base::ranges::transform( |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2404 | policy_site_search_engines, |
| 2405 | std::inserter(new_keywords, new_keywords.begin()), |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2406 | [](const std::unique_ptr<TemplateURL>& turl) { return turl->keyword(); }); |
| 2407 | |
| 2408 | // Remove old site search entries no longer present in the policy's list. |
| 2409 | // |
| 2410 | // Note: auxiliary `keywords_to_remove` is needed to avoid reentry issues |
| 2411 | // while removing elements from |
| 2412 | // `enterprise_site_search_keyword_to_turl_`. |
| 2413 | // |
| 2414 | // Note: This can be made more idiomatic once Chromium style allows |
| 2415 | // `std::views::keys`: |
| 2416 | // std::copy_if( |
| 2417 | // std::views::keys(enterprise_site_search_keyword_to_turl_), |
| 2418 | // std::inserter(keywords_to_remove, keywords_to_remove.begin()), |
| 2419 | // [new_keywords] (const std::u16string& keyword) { |
| 2420 | // new_keywords.find(keyword) == new_keywords.end() |
| 2421 | // }); |
| 2422 | base::flat_set<std::u16string> keywords_to_remove; |
| 2423 | for (auto [keyword, _] : enterprise_site_search_keyword_to_turl_) { |
| 2424 | if (new_keywords.find(keyword) == new_keywords.end()) { |
| 2425 | keywords_to_remove.insert(keyword); |
| 2426 | } |
| 2427 | } |
| 2428 | base::ranges::for_each( |
| 2429 | keywords_to_remove, [this](const std::u16string& keyword) { |
| 2430 | Remove(enterprise_site_search_keyword_to_turl_[keyword]); |
| 2431 | }); |
| 2432 | |
| 2433 | // Either add new site search entries or update existing ones if necessary. |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2434 | for (auto& site_search_engine : policy_site_search_engines) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2435 | const std::u16string& keyword = site_search_engine->keyword(); |
| 2436 | auto it = enterprise_site_search_keyword_to_turl_.find(keyword); |
| 2437 | if (it == enterprise_site_search_keyword_to_turl_.end()) { |
| 2438 | Add(std::move(site_search_engine), /*newly_adding=*/true); |
| 2439 | } else if (ShouldMergeEnterpriseSiteSearchEngines( |
| 2440 | /*existing_turl=*/*it->second, |
| 2441 | /*new_values=*/*site_search_engine)) { |
| 2442 | Update(/*existing_turl=*/it->second, |
| 2443 | /*new_values=*/MergeEnterpriseSiteSearchEngines( |
| 2444 | /*existing_turl=*/*it->second, |
| 2445 | /*new_values=*/*site_search_engine)); |
| 2446 | } |
| 2447 | } |
| 2448 | |
| 2449 | // TODO(b/314162426): Check interaction with DSP not set by policy. |
| 2450 | // TODO(b/309456406): Override existing SE if keywords starts with "@" and |
| 2451 | // this is a featured site search entry. |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2452 | } |
| 2453 | |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 2454 | void TemplateURLService::EnterpriseSiteSearchChanged( |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2455 | OwnedTemplateURLDataVector&& policy_site_search_engines) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2456 | OwnedTemplateURLVector turl_site_search_engines; |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2457 | for (const std::unique_ptr<TemplateURLData>& it : |
| 2458 | policy_site_search_engines) { |
Fabio Tirelo | 07ea7dd | 2023-12-06 02:13:44 | [diff] [blame] | 2459 | turl_site_search_engines.push_back( |
| 2460 | std::make_unique<TemplateURL>(*it, TemplateURL::NORMAL)); |
| 2461 | } |
| 2462 | |
| 2463 | if (loaded_) { |
| 2464 | ApplyEnterpriseSiteSearchChanges(std::move(turl_site_search_engines)); |
| 2465 | } else { |
| 2466 | pre_loading_providers_->set_site_search_engines( |
| 2467 | std::move(turl_site_search_engines)); |
| 2468 | } |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 2469 | } |
| 2470 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2471 | TemplateURL* TemplateURLService::Add(std::unique_ptr<TemplateURL> template_url, |
| 2472 | bool newly_adding) { |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2473 | DCHECK(template_url); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2474 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2475 | Scoper scoper(this); |
| 2476 | |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2477 | if (newly_adding) { |
| 2478 | DCHECK_EQ(kInvalidTemplateURLID, template_url->id()); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2479 | DCHECK(!Contains(&template_urls_, template_url.get())); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2480 | template_url->data_.id = ++next_id_; |
| 2481 | } |
| 2482 | |
Tommy Li | 726e59c4 | 2021-01-07 22:57:00 | [diff] [blame] | 2483 | template_url->ResetKeywordIfNecessary(search_terms_data(), false); |
erikwright@chromium.org | 5f13765 | 2014-05-14 00:02:19 | [diff] [blame] | 2484 | |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2485 | // Early exit if the newly added TemplateURL was a replaceable duplicate. |
| 2486 | // No need to inform either Sync or flag on the model-mutated in that case. |
| 2487 | if (RemoveDuplicateReplaceableEnginesOf(template_url.get())) { |
| 2488 | return nullptr; |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2489 | } |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2490 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2491 | TemplateURL* template_url_ptr = template_url.get(); |
| 2492 | template_urls_.push_back(std::move(template_url)); |
| 2493 | AddToMaps(template_url_ptr); |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2494 | |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 2495 | if (newly_adding && (template_url_ptr->type() == TemplateURL::NORMAL)) { |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 2496 | if (web_data_service_) |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2497 | web_data_service_->AddKeyword(template_url_ptr->data()); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2498 | |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2499 | // Inform sync of the addition. Note that this will assign a GUID to |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2500 | // template_url and add it to the guid_to_turl_. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2501 | ProcessTemplateURLChange(FROM_HERE, template_url_ptr, |
zea@chromium.org | b78170f | 2012-07-11 03:34:26 | [diff] [blame] | 2502 | syncer::SyncChange::ACTION_ADD); |
pkasting@chromium.org | 3954c3a | 2012-04-10 20:17:55 | [diff] [blame] | 2503 | } |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2504 | |
| 2505 | if (template_url_ptr) |
| 2506 | model_mutated_notification_pending_ = true; |
| 2507 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2508 | return template_url_ptr; |
jeanluc@google.com | b6fd1fa7 | 2010-10-05 23:49:31 | [diff] [blame] | 2509 | } |
| 2510 | |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2511 | // |template_urls| are the TemplateURLs loaded from the database. |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2512 | // |default_from_prefs| is the default search provider from the preferences, or |
| 2513 | // NULL if the DSE is not policy-defined. |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2514 | // |
| 2515 | // This function removes from the vector and the database all the TemplateURLs |
Fabio Tirelo | 41316deb | 2023-11-24 21:33:11 | [diff] [blame] | 2516 | // that were set by policy as default provider, unless it is the current default |
| 2517 | // search provider, in which case it is updated with the data from prefs. |
| 2518 | void TemplateURLService::UpdateDefaultProvidersCreatedByPolicy( |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2519 | OwnedTemplateURLVector* template_urls, |
Igor Ruvinov | f266d2a4 | 2022-06-24 17:52:16 | [diff] [blame] | 2520 | const TemplateURLData* default_from_prefs, |
| 2521 | bool is_mandatory) { |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2522 | DCHECK(template_urls); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2523 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2524 | Scoper scoper(this); |
| 2525 | |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2526 | for (auto i = template_urls->begin(); i != template_urls->end();) { |
| 2527 | TemplateURL* template_url = i->get(); |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 2528 | if (template_url->created_by_policy() == |
| 2529 | TemplateURLData::CreatedByPolicy::kDefaultSearchProvider) { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2530 | if (default_from_prefs && |
hashimoto@chromium.org | ce7ee5f | 2014-06-16 23:41:19 | [diff] [blame] | 2531 | TemplateURL::MatchesData(template_url, default_from_prefs, |
| 2532 | search_terms_data())) { |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2533 | // If the database specified a default search provider that was set |
| 2534 | // by policy, and the default search provider from the preferences |
| 2535 | // is also set by policy and they are the same, keep the entry in the |
| 2536 | // database and the |default_search_provider|. |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2537 | default_search_provider_ = template_url; |
| 2538 | // Prevent us from saving any other entries, or creating a new one. |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2539 | default_from_prefs = nullptr; |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2540 | ++i; |
| 2541 | continue; |
| 2542 | } |
| 2543 | |
Igor Ruvinov | ac41f8d | 2023-04-21 14:09:28 | [diff] [blame] | 2544 | // If the previous default search provider was set as a recommended policy |
| 2545 | // and the new provider is not set by policy, keep the previous provider |
| 2546 | // in the database. This allows the recommended provider to remain in the |
| 2547 | // list if the user switches to a different provider. |
| 2548 | if (template_url->enforced_by_policy() || default_from_prefs) { |
| 2549 | TemplateURLID id = template_url->id(); |
| 2550 | RemoveFromMaps(template_url); |
| 2551 | i = template_urls->erase(i); |
| 2552 | if (web_data_service_) { |
| 2553 | web_data_service_->RemoveKeyword(id); |
| 2554 | } |
| 2555 | } else { |
| 2556 | ++i; |
| 2557 | } |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2558 | } else { |
| 2559 | ++i; |
| 2560 | } |
| 2561 | } |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2562 | |
| 2563 | if (default_from_prefs) { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2564 | default_search_provider_ = nullptr; |
Igor Ruvinov | f266d2a4 | 2022-06-24 17:52:16 | [diff] [blame] | 2565 | default_search_provider_source_ = |
| 2566 | is_mandatory ? DefaultSearchManager::FROM_POLICY |
| 2567 | : DefaultSearchManager::FROM_POLICY_RECOMMENDED; |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2568 | TemplateURLData new_data(*default_from_prefs); |
| 2569 | if (new_data.sync_guid.empty()) |
Mikel Astiz | b1c1cac | 2019-04-18 12:51:48 | [diff] [blame] | 2570 | new_data.GenerateSyncGUID(); |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 2571 | new_data.created_by_policy = |
| 2572 | TemplateURLData::CreatedByPolicy::kDefaultSearchProvider; |
Igor Ruvinov | ac41f8d | 2023-04-21 14:09:28 | [diff] [blame] | 2573 | new_data.enforced_by_policy = is_mandatory; |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 2574 | new_data.safe_for_autoreplace = false; |
Angela Yoeurng | ca315d6 | 2021-11-15 19:55:28 | [diff] [blame] | 2575 | new_data.is_active = TemplateURLData::ActiveStatus::kTrue; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2576 | std::unique_ptr<TemplateURL> new_dse_ptr = |
Jinho Bang | fa6b575 | 2018-01-03 20:52:19 | [diff] [blame] | 2577 | std::make_unique<TemplateURL>(new_data); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2578 | TemplateURL* new_dse = new_dse_ptr.get(); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2579 | if (Add(std::move(new_dse_ptr))) |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2580 | default_search_provider_ = new_dse; |
| 2581 | } |
joaodasilva@chromium.org | 18b5f684 | 2011-05-23 11:51:45 | [diff] [blame] | 2582 | } |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2583 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2584 | void TemplateURLService::ResetTemplateURLGUID(TemplateURL* url, |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2585 | const std::string& guid) { |
pkasting@chromium.org | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 2586 | DCHECK(loaded_); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2587 | DCHECK(!guid.empty()); |
| 2588 | |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 2589 | TemplateURLData data(url->data()); |
| 2590 | data.sync_guid = guid; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2591 | Update(url, TemplateURL(data)); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2592 | } |
| 2593 | |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2594 | void TemplateURLService::MergeInSyncTemplateURL( |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2595 | TemplateURL* sync_turl, |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2596 | const SyncDataMap& sync_data, |
| 2597 | syncer::SyncChangeList* change_list, |
Victor Hugo Vianna Silva | 8aad161a | 2020-04-16 10:52:42 | [diff] [blame] | 2598 | SyncDataMap* local_data) { |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2599 | DCHECK(sync_turl); |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2600 | DCHECK(!GetTemplateURLForGUID(sync_turl->sync_guid())); |
| 2601 | DCHECK(IsFromSync(sync_turl, sync_data)); |
stevet@chromium.org | f024fd5 | 2011-12-02 20:43:09 | [diff] [blame] | 2602 | |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2603 | bool should_add_sync_turl = true; |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2604 | |
| 2605 | Scoper scoper(this); |
stevet@chromium.org | f024fd5 | 2011-12-02 20:43:09 | [diff] [blame] | 2606 | |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2607 | // First resolve conflicts with local duplicate keyword NORMAL TemplateURLs, |
| 2608 | // working from best to worst. |
| 2609 | DCHECK(sync_turl->type() == TemplateURL::NORMAL); |
| 2610 | std::vector<TemplateURL*> local_duplicates; |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2611 | const auto match_range = keyword_to_turl_.equal_range(sync_turl->keyword()); |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2612 | for (auto it = match_range.first; it != match_range.second; ++it) { |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2613 | TemplateURL* local_turl = it->second; |
Tommy C. Li | 3156324 | 2023-02-16 16:59:49 | [diff] [blame] | 2614 | // The conflict resolution code below sometimes resets the TemplateURL's |
| 2615 | // GUID, which can trigger deleting any Policy-created engines. Avoid this |
| 2616 | // use-after-free bug by excluding any Policy-created engines. Also exclude |
| 2617 | // Play API created engines, as those also seem local-only and should not |
| 2618 | // be merged into Synced engines. crbug.com/1414224. |
| 2619 | if (local_turl->type() == TemplateURL::NORMAL && |
Fabio Tirelo | 6e6df8bf | 2023-11-22 17:00:15 | [diff] [blame] | 2620 | local_turl->created_by_policy() == |
| 2621 | TemplateURLData::CreatedByPolicy::kNoPolicy && |
Tommy C. Li | 3156324 | 2023-02-16 16:59:49 | [diff] [blame] | 2622 | !local_turl->created_from_play_api()) { |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2623 | local_duplicates.push_back(local_turl); |
| 2624 | } |
| 2625 | } |
| 2626 | base::ranges::sort(local_duplicates, [&](const auto& a, const auto& b) { |
Fabio Tirelo | c0de81c | 2024-01-10 18:07:15 | [diff] [blame] | 2627 | return a->IsBetterThanConflictingEngine(b); |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2628 | }); |
| 2629 | for (TemplateURL* conflicting_turl : local_duplicates) { |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2630 | if (IsFromSync(conflicting_turl, sync_data)) { |
| 2631 | // |conflicting_turl| is already known to Sync, so we're not allowed to |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2632 | // remove it. Just leave it. TemplateURLService can tolerate duplicates. |
| 2633 | // TODO(tommycli): Eventually we should figure out a way to merge |
| 2634 | // substantively identical ones or somehow otherwise cull the herd. |
| 2635 | continue; |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2636 | } |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2637 | |
| 2638 | // |conflicting_turl| is not yet known to Sync. If it is better, then we |
| 2639 | // want to transfer its values up to sync. Otherwise, we remove it and |
| 2640 | // allow the entry from Sync to overtake it in the model. |
| 2641 | const std::string guid = conflicting_turl->sync_guid(); |
| 2642 | if (conflicting_turl == GetDefaultSearchProvider() || |
Fabio Tirelo | c0de81c | 2024-01-10 18:07:15 | [diff] [blame] | 2643 | conflicting_turl->IsBetterThanConflictingEngine(sync_turl)) { |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2644 | ResetTemplateURLGUID(conflicting_turl, sync_turl->sync_guid()); |
Peter Kasting | bef7bc52 | 2021-09-08 17:53:30 | [diff] [blame] | 2645 | syncer::SyncData updated_sync_data = |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2646 | CreateSyncDataFromTemplateURL(*conflicting_turl); |
| 2647 | change_list->push_back(syncer::SyncChange( |
Peter Kasting | bef7bc52 | 2021-09-08 17:53:30 | [diff] [blame] | 2648 | FROM_HERE, syncer::SyncChange::ACTION_UPDATE, updated_sync_data)); |
Tommy Li | 2f7daef | 2020-12-03 21:09:12 | [diff] [blame] | 2649 | // Note that in this case we do not add the Sync TemplateURL to the |
| 2650 | // local model, since we've effectively "merged" it in by updating the |
| 2651 | // local conflicting entry with its sync_guid. |
| 2652 | should_add_sync_turl = false; |
| 2653 | } else { |
| 2654 | // We guarantee that this isn't the local search provider. Otherwise, |
| 2655 | // local would have won. |
| 2656 | DCHECK(conflicting_turl != GetDefaultSearchProvider()); |
| 2657 | Remove(conflicting_turl); |
| 2658 | } |
| 2659 | // This TemplateURL was either removed or overwritten in the local model. |
| 2660 | // Remove the entry from the local data so it isn't pushed up to Sync. |
| 2661 | local_data->erase(guid); |
| 2662 | } |
| 2663 | |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2664 | // Try to take over a local built-in (prepopulated or starter pack) entry, |
| 2665 | // assuming we haven't already run into a keyword conflict. |
| 2666 | if (local_duplicates.empty() && |
| 2667 | (sync_turl->prepopulate_id() != 0 || sync_turl->starter_pack_id() != 0)) { |
pnoland | 8ec6ae8 | 2016-06-15 21:40:22 | [diff] [blame] | 2668 | // Check for a turl with a conflicting prepopulate_id. This detects the case |
| 2669 | // where the user changes a prepopulated engine's keyword on one client, |
| 2670 | // then begins syncing on another client. We want to reflect this keyword |
| 2671 | // change to that prepopulated URL on other clients instead of assuming that |
| 2672 | // the modified TemplateURL is a new entity. |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2673 | TemplateURL* conflicting_built_in_turl = |
| 2674 | (sync_turl->prepopulate_id() != 0) |
| 2675 | ? FindPrepopulatedTemplateURL(sync_turl->prepopulate_id()) |
| 2676 | : FindStarterPackTemplateURL(sync_turl->starter_pack_id()); |
pnoland | 8ec6ae8 | 2016-06-15 21:40:22 | [diff] [blame] | 2677 | |
| 2678 | // If we found a conflict, and the sync entity is better, apply the remote |
| 2679 | // changes locally. We consider |sync_turl| better if it's been modified |
| 2680 | // more recently and the local TemplateURL isn't yet known to sync. We will |
| 2681 | // consider the sync entity better even if the local TemplateURL is the |
| 2682 | // current default, since in this case being default does not necessarily |
| 2683 | // mean the user explicitly set this TemplateURL as default. If we didn't do |
| 2684 | // this, changes to the keywords of prepopulated default engines would never |
| 2685 | // be applied to other clients. |
| 2686 | // If we can't safely replace the local entry with the synced one, or merge |
| 2687 | // the relevant changes in, we give up and leave both intact. |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2688 | if (conflicting_built_in_turl && |
| 2689 | !IsFromSync(conflicting_built_in_turl, sync_data) && |
Fabio Tirelo | c0de81c | 2024-01-10 18:07:15 | [diff] [blame] | 2690 | sync_turl->IsBetterThanConflictingEngine(conflicting_built_in_turl)) { |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2691 | std::string guid = conflicting_built_in_turl->sync_guid(); |
| 2692 | if (conflicting_built_in_turl == default_search_provider_) { |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2693 | bool pref_matched = GetDefaultSearchProviderPrefValue(*prefs_) == |
| 2694 | default_search_provider_->sync_guid(); |
Marc Treib | dd87e8c | 2018-07-10 16:41:02 | [diff] [blame] | 2695 | // Update the existing engine in-place. |
| 2696 | Update(default_search_provider_, TemplateURL(sync_turl->data())); |
| 2697 | // If prefs::kSyncedDefaultSearchProviderGUID matched |
| 2698 | // |default_search_provider_|'s GUID before, then update it to match its |
| 2699 | // new GUID. If the pref didn't match before, then it probably refers to |
| 2700 | // a new search engine from Sync which just hasn't been added locally |
| 2701 | // yet, so leave it alone in that case. |
| 2702 | if (pref_matched) { |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2703 | SetDefaultSearchProviderPrefValue( |
| 2704 | *prefs_, default_search_provider_->sync_guid()); |
Marc Treib | dd87e8c | 2018-07-10 16:41:02 | [diff] [blame] | 2705 | } |
| 2706 | |
Marc Treib | 5367175 | 2018-07-10 09:55:25 | [diff] [blame] | 2707 | should_add_sync_turl = false; |
pnoland | 8ec6ae8 | 2016-06-15 21:40:22 | [diff] [blame] | 2708 | } else { |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2709 | Remove(conflicting_built_in_turl); |
pnoland | 8ec6ae8 | 2016-06-15 21:40:22 | [diff] [blame] | 2710 | } |
| 2711 | // Remove the local data so it isn't written to sync. |
| 2712 | local_data->erase(guid); |
| 2713 | } |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2714 | } |
| 2715 | |
| 2716 | if (should_add_sync_turl) { |
pkasting@chromium.org | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 2717 | // Force the local ID to kInvalidTemplateURLID so we can add it. |
stevet@chromium.org | 7d574f0b | 2012-08-14 21:32:51 | [diff] [blame] | 2718 | TemplateURLData data(sync_turl->data()); |
| 2719 | data.id = kInvalidTemplateURLID; |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2720 | std::unique_ptr<TemplateURL> added_ptr = |
Jinho Bang | fa6b575 | 2018-01-03 20:52:19 | [diff] [blame] | 2721 | std::make_unique<TemplateURL>(data); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2722 | TemplateURL* added = added_ptr.get(); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2723 | base::AutoReset<DefaultSearchChangeOrigin> change_origin( |
| 2724 | &dsp_change_origin_, DSP_CHANGE_SYNC_ADD); |
Esmael El-Moslimany | b4306e0 | 2018-04-18 21:24:33 | [diff] [blame] | 2725 | if (Add(std::move(added_ptr))) |
Vasilii Sukhanov | 9e32af7 | 2018-04-17 18:47:15 | [diff] [blame] | 2726 | MaybeUpdateDSEViaPrefs(added); |
stevet@chromium.org | d88cb20 | 2011-08-17 20:03:01 | [diff] [blame] | 2727 | } |
| 2728 | } |
stevet@chromium.org | a1eecd4 | 2011-11-08 19:52:14 | [diff] [blame] | 2729 | |
| 2730 | void TemplateURLService::PatchMissingSyncGUIDs( |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2731 | OwnedTemplateURLVector* template_urls) { |
stevet@chromium.org | a1eecd4 | 2011-11-08 19:52:14 | [diff] [blame] | 2732 | DCHECK(template_urls); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2733 | for (auto& template_url : *template_urls) { |
stevet@chromium.org | a1eecd4 | 2011-11-08 19:52:14 | [diff] [blame] | 2734 | DCHECK(template_url); |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 2735 | if (template_url->sync_guid().empty() && |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 2736 | (template_url->type() == TemplateURL::NORMAL)) { |
Mikel Astiz | b1c1cac | 2019-04-18 12:51:48 | [diff] [blame] | 2737 | template_url->data_.GenerateSyncGUID(); |
Zinovy Nis | 701103b | 2018-05-10 22:59:38 | [diff] [blame] | 2738 | if (web_data_service_) |
hashimoto@chromium.org | 37b32460 | 2014-07-02 07:30:49 | [diff] [blame] | 2739 | web_data_service_->UpdateKeyword(template_url->data()); |
stevet@chromium.org | a1eecd4 | 2011-11-08 19:52:14 | [diff] [blame] | 2740 | } |
| 2741 | } |
| 2742 | } |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2743 | |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2744 | void TemplateURLService::OnDefaultSearchProviderGUIDChanged() { |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2745 | base::AutoReset<DefaultSearchChangeOrigin> change_origin( |
| 2746 | &dsp_change_origin_, DSP_CHANGE_SYNC_PREF); |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2747 | |
Jack Yammine | abb0ba2 | 2023-07-20 10:46:34 | [diff] [blame] | 2748 | std::string new_guid = GetDefaultSearchProviderPrefValue(*prefs_); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2749 | if (new_guid.empty()) { |
| 2750 | default_search_manager_.ClearUserSelectedDefaultSearchEngine(); |
| 2751 | return; |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2752 | } |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2753 | |
jeffschiller | 612137a | 2017-04-19 04:34:24 | [diff] [blame] | 2754 | const TemplateURL* turl = GetTemplateURLForGUID(new_guid); |
Mihai Sardarescu | 27fe06b | 2024-03-12 10:07:46 | [diff] [blame] | 2755 | if (turl) { |
| 2756 | default_search_manager_.SetUserSelectedDefaultSearchEngine( |
| 2757 | turl->data(), search_engines::ChoiceMadeLocation::kOther); |
| 2758 | } |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2759 | } |
| 2760 | |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 2761 | void TemplateURLService::MaybeSetIsActiveSearchEngines( |
| 2762 | OwnedTemplateURLVector* template_urls) { |
| 2763 | DCHECK(template_urls); |
| 2764 | for (auto& turl : *template_urls) { |
| 2765 | DCHECK(turl); |
| 2766 | // An turl is "active" if it has ever been used or manually added/modified. |
| 2767 | // |safe_for_autoreplace| is false if the entry has been modified. |
| 2768 | if (turl->is_active() == TemplateURLData::ActiveStatus::kUnspecified && |
| 2769 | (!turl->safe_for_autoreplace() || turl->usage_count() > 0)) { |
| 2770 | turl->data_.is_active = TemplateURLData::ActiveStatus::kTrue; |
Angela Yoeurng | 38806b4 | 2022-10-13 00:20:54 | [diff] [blame] | 2771 | turl->data_.safe_for_autoreplace = false; |
Angela Yoeurng | 7ff86ed5 | 2021-08-12 20:03:24 | [diff] [blame] | 2772 | if (web_data_service_) |
| 2773 | web_data_service_->UpdateKeyword(turl->data()); |
| 2774 | } |
| 2775 | } |
| 2776 | } |
| 2777 | |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2778 | template <typename Container> |
| 2779 | void TemplateURLService::AddMatchingKeywordsHelper( |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2780 | const Container& keyword_to_turl, |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 2781 | const std::u16string& prefix, |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2782 | bool supports_replacement_only, |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2783 | TemplateURLVector* matches) { |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2784 | // Sanity check args. |
| 2785 | if (prefix.empty()) |
| 2786 | return; |
| 2787 | DCHECK(matches); |
| 2788 | |
| 2789 | // Find matching keyword range. Searches the element map for keywords |
| 2790 | // beginning with |prefix| and stores the endpoints of the resulting set in |
| 2791 | // |match_range|. |
| 2792 | const auto match_range(std::equal_range( |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2793 | keyword_to_turl.begin(), keyword_to_turl.end(), |
| 2794 | typename Container::value_type(prefix, nullptr), LessWithPrefix())); |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2795 | |
| 2796 | // Add to vector of matching keywords. |
| 2797 | for (typename Container::const_iterator i(match_range.first); |
| 2798 | i != match_range.second; ++i) { |
| 2799 | if (!supports_replacement_only || |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2800 | i->second->url_ref().SupportsReplacement(search_terms_data())) { |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2801 | matches->push_back(i->second); |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2802 | } |
mpearson | 6456fb6 | 2015-11-13 06:44:28 | [diff] [blame] | 2803 | } |
| 2804 | } |
| 2805 | |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2806 | TemplateURL* TemplateURLService::FindPrepopulatedTemplateURL( |
| 2807 | int prepopulated_id) { |
Patrick Noland | c878eec | 2017-10-02 17:32:53 | [diff] [blame] | 2808 | DCHECK(prepopulated_id); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2809 | for (const auto& turl : template_urls_) { |
| 2810 | if (turl->prepopulate_id() == prepopulated_id) |
| 2811 | return turl.get(); |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2812 | } |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2813 | return nullptr; |
vasilii@chromium.org | 4a40facd | 2013-05-29 14:44:56 | [diff] [blame] | 2814 | } |
vasilii@chromium.org | a50e38f | 2013-07-22 16:47:00 | [diff] [blame] | 2815 | |
Angela Yoeurng | 500c310 | 2022-04-26 20:05:53 | [diff] [blame] | 2816 | TemplateURL* TemplateURLService::FindStarterPackTemplateURL( |
| 2817 | int starter_pack_id) { |
| 2818 | DCHECK(starter_pack_id); |
| 2819 | for (const auto& turl : template_urls_) { |
| 2820 | if (turl->starter_pack_id() == starter_pack_id) |
| 2821 | return turl.get(); |
| 2822 | } |
| 2823 | return nullptr; |
| 2824 | } |
| 2825 | |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 2826 | TemplateURL* TemplateURLService::FindTemplateURLForExtension( |
| 2827 | const std::string& extension_id, |
erikwright@chromium.org | 8f1f8ac | 2014-05-11 23:23:05 | [diff] [blame] | 2828 | TemplateURL::Type type) { |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 2829 | DCHECK_NE(TemplateURL::NORMAL, type); |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2830 | for (const auto& turl : template_urls_) { |
ianwen | a27b1df | 2016-09-23 23:08:23 | [diff] [blame] | 2831 | if (turl->type() == type && turl->GetExtensionId() == extension_id) |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2832 | return turl.get(); |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 2833 | } |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2834 | return nullptr; |
vasilii@chromium.org | bdcbcd8 | 2013-10-28 13:40:25 | [diff] [blame] | 2835 | } |
| 2836 | |
a-v-y | f4eb435 | 2017-02-25 18:46:59 | [diff] [blame] | 2837 | TemplateURL* TemplateURLService::FindMatchingDefaultExtensionTemplateURL( |
| 2838 | const TemplateURLData& data) { |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2839 | for (const auto& turl : template_urls_) { |
a-v-y | f4eb435 | 2017-02-25 18:46:59 | [diff] [blame] | 2840 | if (turl->type() == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION && |
| 2841 | turl->extension_info_->wants_to_be_default_engine && |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2842 | TemplateURL::MatchesData(turl.get(), &data, search_terms_data())) |
| 2843 | return turl.get(); |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2844 | } |
avi | 8a64b715b | 2016-09-02 17:30:04 | [diff] [blame] | 2845 | return nullptr; |
erikwright@chromium.org | a80ec96 | 2014-05-12 00:55:38 | [diff] [blame] | 2846 | } |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2847 | |
| 2848 | bool TemplateURLService::RemoveDuplicateReplaceableEnginesOf( |
| 2849 | TemplateURL* candidate) { |
| 2850 | DCHECK(candidate); |
Fabio Tirelo | b64e49b | 2023-12-15 01:41:02 | [diff] [blame] | 2851 | |
| 2852 | // Do not replace existing search engines if `candidate` was created by the |
| 2853 | // `SiteSearchSettings` policy. |
| 2854 | if (candidate->created_by_policy() == |
| 2855 | TemplateURLData::CreatedByPolicy::kSiteSearch) { |
| 2856 | return false; |
| 2857 | } |
| 2858 | |
Jan Wilken Dörrie | fa241ba | 2021-03-11 17:57:01 | [diff] [blame] | 2859 | const std::u16string& keyword = candidate->keyword(); |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2860 | |
| 2861 | // If there's not at least one conflicting TemplateURL, there's nothing to do. |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2862 | const auto match_range = keyword_to_turl_.equal_range(keyword); |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2863 | if (match_range.first == match_range.second) { |
| 2864 | return false; |
| 2865 | } |
| 2866 | |
Tommy Li | c773bad | 2020-12-17 23:51:15 | [diff] [blame] | 2867 | // Gather the replaceable TemplateURLs to be removed. We don't do it in-place, |
| 2868 | // because Remove() invalidates iterators. |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2869 | std::vector<TemplateURL*> replaceable_turls; |
| 2870 | for (auto it = match_range.first; it != match_range.second; ++it) { |
Angela Yoeurng | cec8a464 | 2023-06-15 20:33:59 | [diff] [blame] | 2871 | TemplateURL* turl = it->second; |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2872 | DCHECK_NE(turl, candidate) << "This algorithm runs BEFORE |candidate| is " |
| 2873 | "added to the keyword map."; |
| 2874 | |
Angela Yoeurng | 791a956 | 2022-07-22 02:51:40 | [diff] [blame] | 2875 | // Built-in engines are marked as safe_for_autoreplace(). But because |
Tommy Li | 2d7174dc | 2021-01-13 19:45:28 | [diff] [blame] | 2876 | // they are shown in the Default Search Engines Settings UI, users would |
| 2877 | // find it confusing if they were ever automatically removed. |
| 2878 | // https://crbug.com/1164024 |
Angela Yoeurng | 791a956 | 2022-07-22 02:51:40 | [diff] [blame] | 2879 | if (turl->safe_for_autoreplace() && turl->prepopulate_id() == 0 && |
| 2880 | turl->starter_pack_id() == 0) { |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2881 | replaceable_turls.push_back(turl); |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2882 | } |
| 2883 | } |
Tommy Li | c773bad | 2020-12-17 23:51:15 | [diff] [blame] | 2884 | |
| 2885 | // Find the BEST engine for |keyword| factoring in the new |candidate|. |
| 2886 | TemplateURL* best = GetTemplateURLForKeyword(keyword); |
Fabio Tirelo | c0de81c | 2024-01-10 18:07:15 | [diff] [blame] | 2887 | if (!best || candidate->IsBetterThanConflictingEngine(best)) { |
Tommy Li | c773bad | 2020-12-17 23:51:15 | [diff] [blame] | 2888 | best = candidate; |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2889 | } |
| 2890 | |
Tommy Li | c773bad | 2020-12-17 23:51:15 | [diff] [blame] | 2891 | // Remove all the replaceable TemplateURLs that are not the best. |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2892 | for (TemplateURL* turl : replaceable_turls) { |
Tommy Li | c773bad | 2020-12-17 23:51:15 | [diff] [blame] | 2893 | DCHECK_NE(turl, candidate); |
| 2894 | |
Tommy Li | bf31dec | 2020-12-17 21:26:35 | [diff] [blame] | 2895 | // Never actually remove the DSE during this phase. This handling defers |
| 2896 | // deleting the DSE until it's no longer set as the DSE, analagous to how |
| 2897 | // we handle ACTION_DELETE of the DSE in ProcessSyncChanges(). |
Tommy Li | bc7e63b | 2021-01-14 05:14:24 | [diff] [blame] | 2898 | if (turl != best && !MatchesDefaultSearchProvider(turl)) { |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2899 | Remove(turl); |
| 2900 | } |
| 2901 | } |
| 2902 | |
| 2903 | // Caller needs to know if |candidate| would have been deleted. |
Tommy Li | 2d7174dc | 2021-01-13 19:45:28 | [diff] [blame] | 2904 | // Also always successfully add prepopulated engines, for two reasons: |
| 2905 | // 1. The DSE repair logic in ApplyDefaultSearchChangeNoMetrics() relies on |
| 2906 | // Add()ing back the DSE always succeeding. https://crbug.com/1164024 |
| 2907 | // 2. If we don't do this, we have a weird order-dependence on the |
| 2908 | // replaceability of prepopulated engines, given that we refuse to add |
| 2909 | // prepopulated engines to the |replaceable_engines| vector. |
| 2910 | // |
| 2911 | // Given the necessary special casing of prepopulated engines, we may consider |
| 2912 | // marking prepopulated engines as NOT safe_for_autoreplace(), but there's a |
| 2913 | // few obstacles to this: |
| 2914 | // 1. Prepopulated engines are not user-created, and therefore meet the |
| 2915 | // definition of safe_for_autoreplace(). |
| 2916 | // 2. If we mark them as NOT safe_for_autoreplace(), we can no longer |
| 2917 | // distinguish between prepopulated engines that user has edited, vs. not |
| 2918 | // edited. |
| 2919 | // |
| 2920 | // One more caveat: In 2019, we made prepopulated engines have a |
| 2921 | // deterministically generated Sync GUID in order to prevent duplicate |
| 2922 | // prepopulated engines when two clients start syncing at the same time. |
| 2923 | // When combined with the requirement that we can never fail to add a |
| 2924 | // prepopulated engine, this could leads to two engines having the same GUID. |
| 2925 | // |
| 2926 | // TODO(tommycli): After M89, we need to investigate solving the contradiction |
| 2927 | // above. Most probably: the solution is to stop Syncing prepopulated engines |
| 2928 | // and make the GUIDs actually globally unique again. |
| 2929 | return candidate != best && candidate->safe_for_autoreplace() && |
Angela Yoeurng | 791a956 | 2022-07-22 02:51:40 | [diff] [blame] | 2930 | candidate->prepopulate_id() == 0 && candidate->starter_pack_id() == 0; |
Tommy Li | 276535cc | 2020-11-23 19:11:01 | [diff] [blame] | 2931 | } |
Tommy Li | bc7e63b | 2021-01-14 05:14:24 | [diff] [blame] | 2932 | |
| 2933 | bool TemplateURLService::MatchesDefaultSearchProvider(TemplateURL* turl) const { |
| 2934 | DCHECK(turl); |
| 2935 | const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 2936 | if (!default_provider) |
| 2937 | return false; |
| 2938 | |
| 2939 | return turl->sync_guid() == default_provider->sync_guid(); |
| 2940 | } |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 2941 | |
| 2942 | std::unique_ptr<EnterpriseSiteSearchManager> |
| 2943 | TemplateURLService::GetEnterpriseSiteSearchManager(PrefService* prefs) { |
| 2944 | #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ |
Fabio Tirelo | 9fc885b9 | 2024-01-25 17:19:44 | [diff] [blame] | 2945 | BUILDFLAG(IS_CHROMEOS) |
Fabio Tirelo | 78ca826 | 2023-10-31 14:53:18 | [diff] [blame] | 2946 | return base::FeatureList::IsEnabled(omnibox::kSiteSearchSettingsPolicy) |
| 2947 | ? std::make_unique<EnterpriseSiteSearchManager>( |
| 2948 | prefs, base::BindRepeating( |
| 2949 | &TemplateURLService::EnterpriseSiteSearchChanged, |
| 2950 | base::Unretained(this))) |
| 2951 | : nullptr; |
| 2952 | #else |
| 2953 | return nullptr; |
| 2954 | #endif |
| 2955 | } |
Fabio Tirelo | 5efc04da | 2024-01-04 21:31:37 | [diff] [blame] | 2956 | |
| 2957 | void TemplateURLService::LogSiteSearchPolicyConflict( |
| 2958 | const TemplateURLService::OwnedTemplateURLVector& |
| 2959 | policy_site_search_engines) { |
| 2960 | if (policy_site_search_engines.empty()) { |
| 2961 | // No need to record conflict histograms if the SiteSearchSettings policy |
| 2962 | // doesn't create any search engine. |
| 2963 | return; |
| 2964 | } |
| 2965 | |
| 2966 | bool has_conflict_with_featured = false; |
| 2967 | bool has_conflict_with_non_featured = false; |
| 2968 | for (const auto& policy_turl : policy_site_search_engines) { |
| 2969 | const std::u16string& keyword = policy_turl->keyword(); |
| 2970 | CHECK(!keyword.empty()); |
| 2971 | |
| 2972 | const auto match_range = keyword_to_turl_.equal_range(keyword); |
| 2973 | bool conflicts_with_active = |
| 2974 | std::any_of(match_range.first, match_range.second, |
| 2975 | [](const KeywordToTURL::value_type& entry) { |
| 2976 | return entry.second->created_by_policy() == |
| 2977 | TemplateURLData::CreatedByPolicy::kNoPolicy && |
| 2978 | !entry.second->safe_for_autoreplace(); |
| 2979 | }); |
| 2980 | SiteSearchPolicyConflictType type = |
| 2981 | conflicts_with_active |
| 2982 | ? (policy_turl->featured_by_policy() |
| 2983 | ? SiteSearchPolicyConflictType::kWithFeatured |
| 2984 | : SiteSearchPolicyConflictType::kWithNonFeatured) |
| 2985 | : SiteSearchPolicyConflictType::kNone; |
| 2986 | base::UmaHistogramEnumeration(kSiteSearchPolicyConflictCountHistogramName, |
| 2987 | type); |
| 2988 | |
| 2989 | has_conflict_with_featured |= |
| 2990 | type == SiteSearchPolicyConflictType::kWithFeatured; |
| 2991 | has_conflict_with_non_featured |= |
| 2992 | type == SiteSearchPolicyConflictType::kWithNonFeatured; |
| 2993 | } |
| 2994 | |
| 2995 | base::UmaHistogramBoolean( |
| 2996 | kSiteSearchPolicyHasConflictWithFeaturedHistogramName, |
| 2997 | has_conflict_with_featured); |
| 2998 | base::UmaHistogramBoolean( |
| 2999 | kSiteSearchPolicyHasConflictWithNonFeaturedHistogramName, |
| 3000 | has_conflict_with_non_featured); |
| 3001 | } |