OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/search_engines/util.h" | 5 #include "chrome/browser/search_engines/util.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 // Delete the others from the service and from memory. | 91 // Delete the others from the service and from memory. |
92 while (!unchecked_urls.empty()) { | 92 while (!unchecked_urls.empty()) { |
93 // Find the best URL. | 93 // Find the best URL. |
94 int prepopulate_id = unchecked_urls.begin()->first; | 94 int prepopulate_id = unchecked_urls.begin()->first; |
95 PrepopulatedURLMap::const_iterator prepopulated_url = | 95 PrepopulatedURLMap::const_iterator prepopulated_url = |
96 prepopulated_url_map.find(prepopulate_id); | 96 prepopulated_url_map.find(prepopulate_id); |
97 UncheckedURLMap::iterator end = unchecked_urls.upper_bound(prepopulate_id); | 97 UncheckedURLMap::iterator end = unchecked_urls.upper_bound(prepopulate_id); |
98 UncheckedURLMap::iterator best = unchecked_urls.begin(); | 98 UncheckedURLMap::iterator best = unchecked_urls.begin(); |
99 bool matched_keyword = false; | 99 bool matched_keyword = false; |
100 for (UncheckedURLMap::iterator i = unchecked_urls.begin(); i != end; ++i) { | 100 for (UncheckedURLMap::iterator i = unchecked_urls.begin(); i != end; ++i) { |
101 // If the user-selected DSE is a prepopulated engine its properties will | 101 // A URL is automatically the best if it's the default search engine. |
102 // either come from the prepopulation origin or from the user preferences | 102 if (i->second == default_search_provider) { |
103 // file (see DefaultSearchManager). Those properties will end up | |
104 // overwriting whatever we load now anyway. If we are eliminating | |
105 // duplicates, then, we err on the side of keeping the thing that looks | |
106 // more like the value we will end up with in the end. | |
107 if (default_search_provider && | |
108 (default_search_provider->prepopulate_id() == | |
109 i->second->prepopulate_id()) && | |
110 default_search_provider->HasSameKeywordAs(i->second->data())) { | |
111 best = i; | 103 best = i; |
112 break; | 104 break; |
113 } | 105 } |
114 | 106 |
115 // Otherwise, a URL is best if it matches the prepopulated data's keyword; | 107 // Otherwise, a URL is best if it matches the prepopulated data's keyword; |
116 // if none match, just fall back to using the one with the lowest ID. | 108 // if none match, just fall back to using the one with the lowest ID. |
117 if (matched_keyword) | 109 if (matched_keyword) |
118 continue; | 110 continue; |
119 if ((prepopulated_url != prepopulated_url_map.end()) && | 111 if ((prepopulated_url != prepopulated_url_map.end()) && |
120 i->second->HasSameKeywordAs(*prepopulated_url->second)) { | 112 i->second->HasSameKeywordAs(*prepopulated_url->second)) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 // This is invoked when the version of the prepopulate data changes. | 184 // This is invoked when the version of the prepopulate data changes. |
193 // If |removed_keyword_guids| is not NULL, the Sync GUID of each item removed | 185 // If |removed_keyword_guids| is not NULL, the Sync GUID of each item removed |
194 // from the DB will be added to it. Note that this function will take | 186 // from the DB will be added to it. Note that this function will take |
195 // ownership of |prepopulated_urls| and will clear the vector. | 187 // ownership of |prepopulated_urls| and will clear the vector. |
196 void MergeEnginesFromPrepopulateData( | 188 void MergeEnginesFromPrepopulateData( |
197 Profile* profile, | 189 Profile* profile, |
198 WebDataService* service, | 190 WebDataService* service, |
199 ScopedVector<TemplateURLData>* prepopulated_urls, | 191 ScopedVector<TemplateURLData>* prepopulated_urls, |
200 size_t default_search_index, | 192 size_t default_search_index, |
201 TemplateURLService::TemplateURLVector* template_urls, | 193 TemplateURLService::TemplateURLVector* template_urls, |
202 TemplateURL* default_search_provider, | 194 TemplateURL** default_search_provider, |
203 std::set<std::string>* removed_keyword_guids) { | 195 std::set<std::string>* removed_keyword_guids) { |
204 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); | 196 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); |
205 DCHECK(prepopulated_urls); | 197 DCHECK(prepopulated_urls); |
206 DCHECK(template_urls); | 198 DCHECK(template_urls); |
| 199 DCHECK(default_search_provider); |
207 | 200 |
| 201 int default_prepopulated_id = |
| 202 (*prepopulated_urls)[default_search_index]->prepopulate_id; |
208 ActionsFromPrepopulateData actions(CreateActionsFromCurrentPrepopulateData( | 203 ActionsFromPrepopulateData actions(CreateActionsFromCurrentPrepopulateData( |
209 prepopulated_urls, *template_urls, default_search_provider)); | 204 prepopulated_urls, *template_urls, *default_search_provider)); |
210 | 205 |
211 // Remove items. | 206 // Remove items. |
212 for (std::vector<TemplateURL*>::iterator i = actions.removed_engines.begin(); | 207 for (std::vector<TemplateURL*>::iterator i = actions.removed_engines.begin(); |
213 i < actions.removed_engines.end(); ++i) { | 208 i < actions.removed_engines.end(); ++i) { |
214 scoped_ptr<TemplateURL> template_url(*i); | 209 scoped_ptr<TemplateURL> template_url(*i); |
215 TemplateURLService::TemplateURLVector::iterator j = | 210 TemplateURLService::TemplateURLVector::iterator j = |
216 std::find(template_urls->begin(), template_urls->end(), template_url); | 211 std::find(template_urls->begin(), template_urls->end(), template_url); |
217 DCHECK(j != template_urls->end()); | 212 DCHECK(j != template_urls->end()); |
218 DCHECK(!default_search_provider || | 213 DCHECK(*j != *default_search_provider); |
219 (*j)->prepopulate_id() != default_search_provider->prepopulate_id()); | |
220 template_urls->erase(j); | 214 template_urls->erase(j); |
221 if (service) { | 215 if (service) { |
222 service->RemoveKeyword(template_url->id()); | 216 service->RemoveKeyword(template_url->id()); |
223 if (removed_keyword_guids) | 217 if (removed_keyword_guids) |
224 removed_keyword_guids->insert(template_url->sync_guid()); | 218 removed_keyword_guids->insert(template_url->sync_guid()); |
225 } | 219 } |
226 } | 220 } |
227 | 221 |
228 // Edit items. | 222 // Edit items. |
229 for (EditedEngines::iterator i(actions.edited_engines.begin()); | 223 for (EditedEngines::iterator i(actions.edited_engines.begin()); |
230 i < actions.edited_engines.end(); ++i) { | 224 i < actions.edited_engines.end(); ++i) { |
231 TemplateURLData& data = i->second; | 225 TemplateURLData& data = i->second; |
232 scoped_ptr<TemplateURL> existing_url(i->first); | 226 scoped_ptr<TemplateURL> existing_url(i->first); |
233 if (service) | 227 if (service) |
234 service->UpdateKeyword(data); | 228 service->UpdateKeyword(data); |
235 | 229 |
236 // Replace the entry in |template_urls| with the updated one. | 230 // Replace the entry in |template_urls| with the updated one. |
237 TemplateURLService::TemplateURLVector::iterator j = std::find( | 231 TemplateURLService::TemplateURLVector::iterator j = std::find( |
238 template_urls->begin(), template_urls->end(), existing_url.get()); | 232 template_urls->begin(), template_urls->end(), existing_url.get()); |
239 *j = new TemplateURL(profile, data); | 233 *j = new TemplateURL(profile, data); |
| 234 if (*default_search_provider == existing_url.get()) |
| 235 *default_search_provider = *j; |
240 } | 236 } |
241 | 237 |
242 // Add items. | 238 // Add items. |
243 for (std::vector<TemplateURLData>::const_iterator it = | 239 for (std::vector<TemplateURLData>::const_iterator it = |
244 actions.added_engines.begin(); | 240 actions.added_engines.begin(); |
245 it != actions.added_engines.end(); | 241 it != actions.added_engines.end(); |
246 ++it) { | 242 ++it) { |
247 template_urls->push_back(new TemplateURL(profile, *it)); | 243 template_urls->push_back(new TemplateURL(profile, *it)); |
248 } | 244 } |
| 245 |
| 246 if (!*default_search_provider) { |
| 247 // The user had no existing default search provider, so set the |
| 248 // default to the default prepopulated engine. |
| 249 *default_search_provider = FindURLByPrepopulateID(*template_urls, |
| 250 default_prepopulated_id); |
| 251 } |
249 } | 252 } |
250 | 253 |
251 ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData( | 254 ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData( |
252 ScopedVector<TemplateURLData>* prepopulated_urls, | 255 ScopedVector<TemplateURLData>* prepopulated_urls, |
253 const TemplateURLService::TemplateURLVector& existing_urls, | 256 const TemplateURLService::TemplateURLVector& existing_urls, |
254 const TemplateURL* default_search_provider) { | 257 const TemplateURL* default_search_provider) { |
255 // Create a map to hold all provided |template_urls| that originally came from | 258 // Create a map to hold all provided |template_urls| that originally came from |
256 // prepopulate data (i.e. have a non-zero prepopulate_id()). | 259 // prepopulate data (i.e. have a non-zero prepopulate_id()). |
257 typedef std::map<int, TemplateURL*> IDMap; | 260 typedef std::map<int, TemplateURL*> IDMap; |
258 IDMap id_to_turl; | 261 IDMap id_to_turl; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 } | 295 } |
293 } | 296 } |
294 // The above loop takes ownership of all the contents of prepopulated_urls. | 297 // The above loop takes ownership of all the contents of prepopulated_urls. |
295 // Clear the pointers. | 298 // Clear the pointers. |
296 prepopulated_urls->weak_erase(prepopulated_urls->begin(), | 299 prepopulated_urls->weak_erase(prepopulated_urls->begin(), |
297 prepopulated_urls->end()); | 300 prepopulated_urls->end()); |
298 | 301 |
299 // The block above removed all the URLs from the |id_to_turl| map that were | 302 // The block above removed all the URLs from the |id_to_turl| map that were |
300 // found in the prepopulate data. Any remaining URLs that haven't been | 303 // found in the prepopulate data. Any remaining URLs that haven't been |
301 // user-edited or made default can be removed from the data store. | 304 // user-edited or made default can be removed from the data store. |
302 // We assume that this entry is equivalent to the DSE if its prepopulate ID | |
303 // and keyword both match. If the prepopulate ID _does_ match all properties | |
304 // will be replaced with those from |default_search_provider| anyway. | |
305 for (IDMap::iterator i(id_to_turl.begin()); i != id_to_turl.end(); ++i) { | 305 for (IDMap::iterator i(id_to_turl.begin()); i != id_to_turl.end(); ++i) { |
306 TemplateURL* template_url = i->second; | 306 TemplateURL* template_url = i->second; |
307 if ((template_url->safe_for_autoreplace()) && | 307 if ((template_url->safe_for_autoreplace()) && |
308 (!default_search_provider || | 308 (template_url != default_search_provider)) |
309 (template_url->prepopulate_id() != | |
310 default_search_provider->prepopulate_id()) || | |
311 (template_url->keyword() != default_search_provider->keyword()))) | |
312 actions.removed_engines.push_back(template_url); | 309 actions.removed_engines.push_back(template_url); |
313 } | 310 } |
314 | 311 |
315 return actions; | 312 return actions; |
316 } | 313 } |
317 | 314 |
318 void GetSearchProvidersUsingKeywordResult( | 315 void GetSearchProvidersUsingKeywordResult( |
319 const WDTypedResult& result, | 316 const WDTypedResult& result, |
320 WebDataService* service, | 317 WebDataService* service, |
321 Profile* profile, | 318 Profile* profile, |
322 TemplateURLService::TemplateURLVector* template_urls, | 319 TemplateURLService::TemplateURLVector* template_urls, |
323 TemplateURL* default_search_provider, | 320 TemplateURL** default_search_provider, |
324 int* new_resource_keyword_version, | 321 int* new_resource_keyword_version, |
325 std::set<std::string>* removed_keyword_guids) { | 322 std::set<std::string>* removed_keyword_guids) { |
326 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); | 323 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); |
327 DCHECK(template_urls); | 324 DCHECK(template_urls); |
328 DCHECK(template_urls->empty()); | 325 DCHECK(template_urls->empty()); |
| 326 DCHECK(default_search_provider); |
| 327 DCHECK(*default_search_provider == NULL); |
329 DCHECK_EQ(KEYWORDS_RESULT, result.GetType()); | 328 DCHECK_EQ(KEYWORDS_RESULT, result.GetType()); |
330 DCHECK(new_resource_keyword_version); | 329 DCHECK(new_resource_keyword_version); |
331 | 330 |
332 WDKeywordsResult keyword_result = reinterpret_cast< | 331 WDKeywordsResult keyword_result = reinterpret_cast< |
333 const WDResult<WDKeywordsResult>*>(&result)->GetValue(); | 332 const WDResult<WDKeywordsResult>*>(&result)->GetValue(); |
334 | 333 |
335 for (KeywordTable::Keywords::iterator i(keyword_result.keywords.begin()); | 334 for (KeywordTable::Keywords::iterator i(keyword_result.keywords.begin()); |
336 i != keyword_result.keywords.end(); ++i) { | 335 i != keyword_result.keywords.end(); ++i) { |
337 // Fix any duplicate encodings in the local database. Note that we don't | 336 // Fix any duplicate encodings in the local database. Note that we don't |
338 // adjust the last_modified time of this keyword; this way, we won't later | 337 // adjust the last_modified time of this keyword; this way, we won't later |
339 // overwrite any changes on the sync server that happened to this keyword | 338 // overwrite any changes on the sync server that happened to this keyword |
340 // since the last time we synced. Instead, we also run a de-duping pass on | 339 // since the last time we synced. Instead, we also run a de-duping pass on |
341 // the server-provided data in | 340 // the server-provided data in |
342 // TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData() and | 341 // TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData() and |
343 // update the server with the merged, de-duped results at that time. We | 342 // update the server with the merged, de-duped results at that time. We |
344 // still fix here, though, to correct problems in clients that have disabled | 343 // still fix here, though, to correct problems in clients that have disabled |
345 // search engine sync, since in that case that code will never be reached. | 344 // search engine sync, since in that case that code will never be reached. |
346 if (DeDupeEncodings(&i->input_encodings) && service) | 345 if (DeDupeEncodings(&i->input_encodings) && service) |
347 service->UpdateKeyword(*i); | 346 service->UpdateKeyword(*i); |
348 template_urls->push_back(new TemplateURL(profile, *i)); | 347 template_urls->push_back(new TemplateURL(profile, *i)); |
349 } | 348 } |
350 | 349 |
| 350 int64 default_search_provider_id = keyword_result.default_search_provider_id; |
| 351 if (default_search_provider_id) { |
| 352 *default_search_provider = |
| 353 GetTemplateURLByID(*template_urls, default_search_provider_id); |
| 354 } |
| 355 |
351 *new_resource_keyword_version = keyword_result.builtin_keyword_version; | 356 *new_resource_keyword_version = keyword_result.builtin_keyword_version; |
352 GetSearchProvidersUsingLoadedEngines(service, profile, template_urls, | 357 GetSearchProvidersUsingLoadedEngines(service, profile, template_urls, |
353 default_search_provider, | 358 default_search_provider, |
354 new_resource_keyword_version, | 359 new_resource_keyword_version, |
355 removed_keyword_guids); | 360 removed_keyword_guids); |
356 } | 361 } |
357 | 362 |
358 void GetSearchProvidersUsingLoadedEngines( | 363 void GetSearchProvidersUsingLoadedEngines( |
359 WebDataService* service, | 364 WebDataService* service, |
360 Profile* profile, | 365 Profile* profile, |
361 TemplateURLService::TemplateURLVector* template_urls, | 366 TemplateURLService::TemplateURLVector* template_urls, |
362 TemplateURL* default_search_provider, | 367 TemplateURL** default_search_provider, |
363 int* resource_keyword_version, | 368 int* resource_keyword_version, |
364 std::set<std::string>* removed_keyword_guids) { | 369 std::set<std::string>* removed_keyword_guids) { |
365 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); | 370 DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); |
366 DCHECK(template_urls); | 371 DCHECK(template_urls); |
| 372 DCHECK(default_search_provider); |
367 DCHECK(resource_keyword_version); | 373 DCHECK(resource_keyword_version); |
368 PrefService* prefs = profile ? profile->GetPrefs() : NULL; | 374 PrefService* prefs = profile ? profile->GetPrefs() : NULL; |
369 size_t default_search_index; | 375 size_t default_search_index; |
370 ScopedVector<TemplateURLData> prepopulated_urls = | 376 ScopedVector<TemplateURLData> prepopulated_urls = |
371 TemplateURLPrepopulateData::GetPrepopulatedEngines(prefs, | 377 TemplateURLPrepopulateData::GetPrepopulatedEngines(prefs, |
372 &default_search_index); | 378 &default_search_index); |
373 RemoveDuplicatePrepopulateIDs(service, prepopulated_urls, | 379 RemoveDuplicatePrepopulateIDs(service, prepopulated_urls, |
374 default_search_provider, template_urls, | 380 *default_search_provider, template_urls, |
375 removed_keyword_guids); | 381 removed_keyword_guids); |
376 | 382 |
377 const int prepopulate_resource_keyword_version = | 383 const int prepopulate_resource_keyword_version = |
378 TemplateURLPrepopulateData::GetDataVersion(prefs); | 384 TemplateURLPrepopulateData::GetDataVersion(prefs); |
379 if (*resource_keyword_version < prepopulate_resource_keyword_version) { | 385 if (*resource_keyword_version < prepopulate_resource_keyword_version) { |
380 MergeEnginesFromPrepopulateData(profile, service, &prepopulated_urls, | 386 MergeEnginesFromPrepopulateData(profile, service, &prepopulated_urls, |
381 default_search_index, template_urls, default_search_provider, | 387 default_search_index, template_urls, default_search_provider, |
382 removed_keyword_guids); | 388 removed_keyword_guids); |
383 *resource_keyword_version = prepopulate_resource_keyword_version; | 389 *resource_keyword_version = prepopulate_resource_keyword_version; |
384 } else { | 390 } else { |
385 *resource_keyword_version = 0; | 391 *resource_keyword_version = 0; |
386 } | 392 } |
387 } | 393 } |
388 | 394 |
389 bool DeDupeEncodings(std::vector<std::string>* encodings) { | 395 bool DeDupeEncodings(std::vector<std::string>* encodings) { |
390 std::vector<std::string> deduped_encodings; | 396 std::vector<std::string> deduped_encodings; |
391 std::set<std::string> encoding_set; | 397 std::set<std::string> encoding_set; |
392 for (std::vector<std::string>::const_iterator i(encodings->begin()); | 398 for (std::vector<std::string>::const_iterator i(encodings->begin()); |
393 i != encodings->end(); ++i) { | 399 i != encodings->end(); ++i) { |
394 if (encoding_set.insert(*i).second) | 400 if (encoding_set.insert(*i).second) |
395 deduped_encodings.push_back(*i); | 401 deduped_encodings.push_back(*i); |
396 } | 402 } |
397 encodings->swap(deduped_encodings); | 403 encodings->swap(deduped_encodings); |
398 return encodings->size() != deduped_encodings.size(); | 404 return encodings->size() != deduped_encodings.size(); |
399 } | 405 } |
OLD | NEW |