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/template_url_service.h" | 5 #include "chrome/browser/search_engines/template_url_service.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/environment.h" | 10 #include "base/environment.h" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 old_base_url(old_base_url) { | 187 old_base_url(old_base_url) { |
188 } | 188 } |
189 | 189 |
190 OldBaseURLSearchTermsData::~OldBaseURLSearchTermsData() { | 190 OldBaseURLSearchTermsData::~OldBaseURLSearchTermsData() { |
191 } | 191 } |
192 | 192 |
193 std::string OldBaseURLSearchTermsData::GoogleBaseURLValue() const { | 193 std::string OldBaseURLSearchTermsData::GoogleBaseURLValue() const { |
194 return old_base_url; | 194 return old_base_url; |
195 } | 195 } |
196 | 196 |
197 // Returns true if |turl|'s GUID is not found inside |sync_data|. This is to be | |
198 // used in MergeDataAndStartSyncing to differentiate between TemplateURLs from | |
199 // Sync and TemplateURLs that were initially local, assuming |sync_data| is the | |
200 // |initial_sync_data| parameter. | |
201 bool IsFromSync(const TemplateURL* turl, const SyncDataMap& sync_data) { | |
202 return (sync_data.find(turl->sync_guid()) != sync_data.end()); | |
203 } | |
204 | |
205 } // namespace | 197 } // namespace |
206 | 198 |
| 199 |
207 class TemplateURLService::LessWithPrefix { | 200 class TemplateURLService::LessWithPrefix { |
208 public: | 201 public: |
209 // We want to find the set of keywords that begin with a prefix. The STL | 202 // We want to find the set of keywords that begin with a prefix. The STL |
210 // algorithms will return the set of elements that are "equal to" the | 203 // algorithms will return the set of elements that are "equal to" the |
211 // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))". When | 204 // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))". When |
212 // cmp() is the typical std::less<>, this results in lexicographic equality; | 205 // cmp() is the typical std::less<>, this results in lexicographic equality; |
213 // we need to extend this to mark a prefix as "not less than" a keyword it | 206 // we need to extend this to mark a prefix as "not less than" a keyword it |
214 // begins, which will cause the desired elements to be considered "equal to" | 207 // begins, which will cause the desired elements to be considered "equal to" |
215 // the prefix. Note: this is still a strict weak ordering, as required by | 208 // the prefix. Note: this is still a strict weak ordering, as required by |
216 // equal_range() (though I will not prove that here). | 209 // equal_range() (though I will not prove that here). |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 Remove(existing_turl); | 1005 Remove(existing_turl); |
1013 } else if (iter->change_type() == syncer::SyncChange::ACTION_ADD) { | 1006 } else if (iter->change_type() == syncer::SyncChange::ACTION_ADD) { |
1014 if (existing_turl) { | 1007 if (existing_turl) { |
1015 NOTREACHED() << "Unexpected sync change state."; | 1008 NOTREACHED() << "Unexpected sync change state."; |
1016 error = sync_error_factory_->CreateAndUploadError( | 1009 error = sync_error_factory_->CreateAndUploadError( |
1017 FROM_HERE, | 1010 FROM_HERE, |
1018 "ProcessSyncChanges failed on ChangeType ACTION_ADD"); | 1011 "ProcessSyncChanges failed on ChangeType ACTION_ADD"); |
1019 LOG(ERROR) << "Trying to add an existing TemplateURL."; | 1012 LOG(ERROR) << "Trying to add an existing TemplateURL."; |
1020 continue; | 1013 continue; |
1021 } | 1014 } |
1022 const std::string guid = turl->sync_guid(); | 1015 std::string guid = turl->sync_guid(); |
1023 if (existing_keyword_turl) { | 1016 if (!existing_keyword_turl || ResolveSyncKeywordConflict(turl.get(), |
1024 // Resolve any conflicts so we can safely add the new entry. | 1017 existing_keyword_turl, &new_changes)) { |
1025 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, | 1018 // Force the local ID to kInvalidTemplateURLID so we can add it. |
1026 &new_changes); | 1019 TemplateURLData data(turl->data()); |
| 1020 data.id = kInvalidTemplateURLID; |
| 1021 Add(new TemplateURL(profile_, data)); |
| 1022 |
| 1023 // Possibly set the newly added |turl| as the default search provider. |
| 1024 SetDefaultSearchProviderIfNewlySynced(guid); |
1027 } | 1025 } |
1028 // Force the local ID to kInvalidTemplateURLID so we can add it. | |
1029 TemplateURLData data(turl->data()); | |
1030 data.id = kInvalidTemplateURLID; | |
1031 Add(new TemplateURL(profile_, data)); | |
1032 | |
1033 // Possibly set the newly added |turl| as the default search provider. | |
1034 SetDefaultSearchProviderIfNewlySynced(guid); | |
1035 } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE) { | 1026 } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE) { |
1036 if (!existing_turl) { | 1027 if (!existing_turl) { |
1037 NOTREACHED() << "Unexpected sync change state."; | 1028 NOTREACHED() << "Unexpected sync change state."; |
1038 error = sync_error_factory_->CreateAndUploadError( | 1029 error = sync_error_factory_->CreateAndUploadError( |
1039 FROM_HERE, | 1030 FROM_HERE, |
1040 "ProcessSyncChanges failed on ChangeType ACTION_UPDATE"); | 1031 "ProcessSyncChanges failed on ChangeType ACTION_UPDATE"); |
1041 LOG(ERROR) << "Trying to update a non-existent TemplateURL."; | 1032 LOG(ERROR) << "Trying to update a non-existent TemplateURL."; |
1042 continue; | 1033 continue; |
1043 } | 1034 } |
1044 if (existing_keyword_turl && (existing_keyword_turl != existing_turl)) { | 1035 // Possibly resolve a keyword conflict if they have the same keywords but |
1045 // Resolve any conflicts with other entries so we can safely update the | 1036 // are not the same entry. |
1046 // keyword. | 1037 if (existing_keyword_turl && (existing_keyword_turl != existing_turl) && |
1047 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, | 1038 !ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, |
1048 &new_changes); | 1039 &new_changes)) { |
| 1040 // Note that because we're processing changes, this Remove() call won't |
| 1041 // generate an ACTION_DELETE; but ResolveSyncKeywordConflict() did |
| 1042 // already, so we should be OK. |
| 1043 Remove(existing_turl); |
| 1044 continue; |
1049 } | 1045 } |
1050 UIThreadSearchTermsData search_terms_data(existing_turl->profile()); | 1046 UIThreadSearchTermsData search_terms_data(existing_turl->profile()); |
1051 if (UpdateNoNotify(existing_turl, *turl, search_terms_data)) | 1047 if (UpdateNoNotify(existing_turl, *turl, search_terms_data)) |
1052 NotifyObservers(); | 1048 NotifyObservers(); |
1053 } else { | 1049 } else { |
1054 // We've unexpectedly received an ACTION_INVALID. | 1050 // We've unexpectedly received an ACTION_INVALID. |
1055 NOTREACHED() << "Unexpected sync change state."; | 1051 NOTREACHED() << "Unexpected sync change state."; |
1056 error = sync_error_factory_->CreateAndUploadError( | 1052 error = sync_error_factory_->CreateAndUploadError( |
1057 FROM_HERE, | 1053 FROM_HERE, |
1058 "ProcessSyncChanges received an ACTION_INVALID"); | 1054 "ProcessSyncChanges received an ACTION_INVALID"); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 // preprocessing in TemplateURLService's loading code). Ignore it and send | 1122 // preprocessing in TemplateURLService's loading code). Ignore it and send |
1127 // an ACTION_DELETE up to the server. | 1123 // an ACTION_DELETE up to the server. |
1128 new_changes.push_back( | 1124 new_changes.push_back( |
1129 syncer::SyncChange(FROM_HERE, | 1125 syncer::SyncChange(FROM_HERE, |
1130 syncer::SyncChange::ACTION_DELETE, | 1126 syncer::SyncChange::ACTION_DELETE, |
1131 iter->second)); | 1127 iter->second)); |
1132 continue; | 1128 continue; |
1133 } | 1129 } |
1134 | 1130 |
1135 if (local_turl) { | 1131 if (local_turl) { |
1136 DCHECK(IsFromSync(local_turl, sync_data_map)); | |
1137 // This local search engine is already synced. If the timestamp differs | 1132 // This local search engine is already synced. If the timestamp differs |
1138 // from Sync, we need to update locally or to the cloud. Note that if the | 1133 // from Sync, we need to update locally or to the cloud. Note that if the |
1139 // timestamps are equal, we touch neither. | 1134 // timestamps are equal, we touch neither. |
1140 if (sync_turl->last_modified() > local_turl->last_modified()) { | 1135 if (sync_turl->last_modified() > local_turl->last_modified()) { |
1141 // We've received an update from Sync. We should replace all synced | 1136 // We've received an update from Sync. We should replace all synced |
1142 // fields in the local TemplateURL. Note that this includes the | 1137 // fields in the local TemplateURL. Note that this includes the |
1143 // TemplateURLID and the TemplateURL may have to be reparsed. This | 1138 // TemplateURLID and the TemplateURL may have to be reparsed. This |
1144 // also makes the local data's last_modified timestamp equal to Sync's, | 1139 // also makes the local data's last_modified timestamp equal to Sync's, |
1145 // avoiding an Update on the next MergeData call. | 1140 // avoiding an Update on the next MergeData call. |
1146 UIThreadSearchTermsData search_terms_data(local_turl->profile()); | 1141 UIThreadSearchTermsData search_terms_data(local_turl->profile()); |
1147 if (UpdateNoNotify(local_turl, *sync_turl, search_terms_data)) | 1142 if (UpdateNoNotify(local_turl, *sync_turl, search_terms_data)) |
1148 NotifyObservers(); | 1143 NotifyObservers(); |
1149 } else if (sync_turl->last_modified() < local_turl->last_modified()) { | 1144 } else if (sync_turl->last_modified() < local_turl->last_modified()) { |
1150 // Otherwise, we know we have newer data, so update Sync with our | 1145 // Otherwise, we know we have newer data, so update Sync with our |
1151 // data fields. | 1146 // data fields. |
1152 new_changes.push_back( | 1147 new_changes.push_back( |
1153 syncer::SyncChange(FROM_HERE, | 1148 syncer::SyncChange(FROM_HERE, |
1154 syncer::SyncChange::ACTION_UPDATE, | 1149 syncer::SyncChange::ACTION_UPDATE, |
1155 local_data_map[local_turl->sync_guid()])); | 1150 local_data_map[local_turl->sync_guid()])); |
1156 } | 1151 } |
1157 local_data_map.erase(iter->first); | 1152 local_data_map.erase(iter->first); |
1158 } else { | 1153 } else { |
1159 // The search engine from the cloud has not been synced locally. Merge it | 1154 // The search engine from the cloud has not been synced locally, but there |
1160 // into our local model. This will handle any conflicts with local (and | 1155 // might be a local search engine that is a duplicate that needs to be |
1161 // already-synced) TemplateURLs. It will prefer to keep entries from Sync | 1156 // merged. |
1162 // over not-yet-synced TemplateURLs. | 1157 TemplateURL* dupe_turl = FindDuplicateOfSyncTemplateURL(*sync_turl); |
1163 MergeInSyncTemplateURL(sync_turl.get(), sync_data_map, &new_changes, | 1158 if (dupe_turl) { |
1164 &local_data_map); | 1159 // Merge duplicates and remove the processed local TURL from the map. |
| 1160 std::string old_guid = dupe_turl->sync_guid(); |
| 1161 MergeSyncAndLocalURLDuplicates(sync_turl.release(), dupe_turl, |
| 1162 &new_changes); |
| 1163 local_data_map.erase(old_guid); |
| 1164 } else { |
| 1165 std::string guid = sync_turl->sync_guid(); |
| 1166 // Keyword conflict is possible in this case. Resolve it first before |
| 1167 // adding the new TemplateURL. Note that we don't remove the local TURL |
| 1168 // from local_data_map in this case as it may still need to be pushed to |
| 1169 // the cloud. We also explicitly don't resolve conflicts against |
| 1170 // extension keywords; see comments in ProcessSyncChanges(). |
| 1171 TemplateURL* existing_keyword_turl = |
| 1172 FindNonExtensionTemplateURLForKeyword(sync_turl->keyword()); |
| 1173 if (!existing_keyword_turl || ResolveSyncKeywordConflict( |
| 1174 sync_turl.get(), existing_keyword_turl, &new_changes)) { |
| 1175 // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 1176 TemplateURLData data(sync_turl->data()); |
| 1177 data.id = kInvalidTemplateURLID; |
| 1178 Add(new TemplateURL(profile_, data)); |
| 1179 |
| 1180 // Possibly set the newly added |turl| as the default search provider. |
| 1181 SetDefaultSearchProviderIfNewlySynced(guid); |
| 1182 } |
| 1183 } |
1165 } | 1184 } |
1166 } | 1185 } |
1167 | 1186 |
1168 // The remaining SyncData in local_data_map should be everything that needs to | 1187 // The remaining SyncData in local_data_map should be everything that needs to |
1169 // be pushed as ADDs to sync. | 1188 // be pushed as ADDs to sync. |
1170 for (SyncDataMap::const_iterator iter = local_data_map.begin(); | 1189 for (SyncDataMap::const_iterator iter = local_data_map.begin(); |
1171 iter != local_data_map.end(); ++iter) { | 1190 iter != local_data_map.end(); ++iter) { |
1172 new_changes.push_back( | 1191 new_changes.push_back( |
1173 syncer::SyncChange(FROM_HERE, | 1192 syncer::SyncChange(FROM_HERE, |
1174 syncer::SyncChange::ACTION_ADD, | 1193 syncer::SyncChange::ACTION_ADD, |
(...skipping 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2298 // This is a best-effort approach where we try to preserve the original | 2317 // This is a best-effort approach where we try to preserve the original |
2299 // keyword and let the user do what they will after our attempt. | 2318 // keyword and let the user do what they will after our attempt. |
2300 string16 keyword_candidate(turl.keyword()); | 2319 string16 keyword_candidate(turl.keyword()); |
2301 do { | 2320 do { |
2302 keyword_candidate.append(ASCIIToUTF16("_")); | 2321 keyword_candidate.append(ASCIIToUTF16("_")); |
2303 } while (GetTemplateURLForKeyword(keyword_candidate)); | 2322 } while (GetTemplateURLForKeyword(keyword_candidate)); |
2304 | 2323 |
2305 return keyword_candidate; | 2324 return keyword_candidate; |
2306 } | 2325 } |
2307 | 2326 |
2308 bool TemplateURLService::IsLocalTemplateURLBetter( | 2327 bool TemplateURLService::ResolveSyncKeywordConflict( |
2309 const TemplateURL* local_turl, | 2328 TemplateURL* sync_turl, |
2310 const TemplateURL* sync_turl) { | 2329 TemplateURL* local_turl, |
2311 DCHECK(GetTemplateURLForGUID(local_turl->sync_guid())); | 2330 syncer::SyncChangeList* change_list) { |
2312 return local_turl->last_modified() > sync_turl->last_modified() || | 2331 DCHECK(loaded_); |
2313 local_turl->created_by_policy() || | 2332 DCHECK(sync_turl); |
2314 local_turl== GetDefaultSearchProvider(); | 2333 DCHECK(local_turl); |
| 2334 DCHECK(sync_turl->sync_guid() != local_turl->sync_guid()); |
| 2335 DCHECK(!local_turl->IsExtensionKeyword()); |
| 2336 DCHECK(change_list); |
| 2337 |
| 2338 const bool local_is_better = |
| 2339 (local_turl->last_modified() > sync_turl->last_modified()) || |
| 2340 local_turl->created_by_policy() || |
| 2341 (local_turl == GetDefaultSearchProvider()); |
| 2342 const bool can_replace_local = CanReplace(local_turl); |
| 2343 if (CanReplace(sync_turl) && (local_is_better || !can_replace_local)) { |
| 2344 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); |
| 2345 change_list->push_back(syncer::SyncChange(FROM_HERE, |
| 2346 syncer::SyncChange::ACTION_DELETE, |
| 2347 sync_data)); |
| 2348 return false; |
| 2349 } |
| 2350 if (can_replace_local) { |
| 2351 // Since we're processing sync changes, the upcoming Remove() won't generate |
| 2352 // an ACTION_DELETE. We need to do it manually to keep the server in sync |
| 2353 // with us. Note that if we're being called from |
| 2354 // MergeDataAndStartSyncing(), and this TemplateURL was pre-existing rather |
| 2355 // than having just been brought down, then this is wrong, because the |
| 2356 // server doesn't yet know about this entity; but in this case, |
| 2357 // PruneSyncChanges() will prune out the ACTION_DELETE we create here. |
| 2358 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); |
| 2359 change_list->push_back(syncer::SyncChange(FROM_HERE, |
| 2360 syncer::SyncChange::ACTION_DELETE, |
| 2361 sync_data)); |
| 2362 Remove(local_turl); |
| 2363 } else if (local_is_better) { |
| 2364 string16 new_keyword = UniquifyKeyword(*sync_turl, false); |
| 2365 DCHECK(!GetTemplateURLForKeyword(new_keyword)); |
| 2366 sync_turl->data_.SetKeyword(new_keyword); |
| 2367 // If we update the cloud TURL, we need to push an update back to sync |
| 2368 // informing it that something has changed. |
| 2369 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); |
| 2370 change_list->push_back(syncer::SyncChange(FROM_HERE, |
| 2371 syncer::SyncChange::ACTION_UPDATE, |
| 2372 sync_data)); |
| 2373 } else { |
| 2374 string16 new_keyword = UniquifyKeyword(*local_turl, false); |
| 2375 TemplateURLData data(local_turl->data()); |
| 2376 data.SetKeyword(new_keyword); |
| 2377 TemplateURL new_turl(local_turl->profile(), data); |
| 2378 UIThreadSearchTermsData search_terms_data(local_turl->profile()); |
| 2379 if (UpdateNoNotify(local_turl, new_turl, search_terms_data)) |
| 2380 NotifyObservers(); |
| 2381 // Since we're processing sync changes, the UpdateNoNotify() above didn't |
| 2382 // generate an ACTION_UPDATE. We need to do it manually to keep the server |
| 2383 // in sync with us. Note that if we're being called from |
| 2384 // MergeDataAndStartSyncing(), and this TemplateURL was pre-existing rather |
| 2385 // than having just been brought down, then this is wrong, because the |
| 2386 // server won't know about this entity until it processes the ACTION_ADD our |
| 2387 // caller will later generate; but in this case, PruneSyncChanges() will |
| 2388 // prune out the ACTION_UPDATE we create here. |
| 2389 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); |
| 2390 change_list->push_back(syncer::SyncChange(FROM_HERE, |
| 2391 syncer::SyncChange::ACTION_UPDATE, |
| 2392 sync_data)); |
| 2393 } |
| 2394 return true; |
2315 } | 2395 } |
2316 | 2396 |
2317 void TemplateURLService::ResolveSyncKeywordConflict( | 2397 TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( |
2318 TemplateURL* unapplied_sync_turl, | 2398 const TemplateURL& sync_turl) { |
2319 TemplateURL* applied_sync_turl, | 2399 TemplateURL* existing_turl = GetTemplateURLForKeyword(sync_turl.keyword()); |
| 2400 return existing_turl && (existing_turl->url() == sync_turl.url()) ? |
| 2401 existing_turl : NULL; |
| 2402 } |
| 2403 |
| 2404 void TemplateURLService::MergeSyncAndLocalURLDuplicates( |
| 2405 TemplateURL* sync_turl, |
| 2406 TemplateURL* local_turl, |
2320 syncer::SyncChangeList* change_list) { | 2407 syncer::SyncChangeList* change_list) { |
2321 DCHECK(loaded_); | 2408 DCHECK(loaded_); |
2322 DCHECK(unapplied_sync_turl); | 2409 DCHECK(sync_turl); |
2323 DCHECK(applied_sync_turl); | 2410 DCHECK(local_turl); |
2324 DCHECK(change_list); | 2411 DCHECK(change_list); |
2325 DCHECK_EQ(applied_sync_turl->keyword(), unapplied_sync_turl->keyword()); | 2412 scoped_ptr<TemplateURL> scoped_sync_turl(sync_turl); |
2326 DCHECK(!applied_sync_turl->IsExtensionKeyword()); | 2413 if (sync_turl->last_modified() > local_turl->last_modified()) { |
| 2414 // Fully replace local_url with Sync's copy. Note that because use Add |
| 2415 // rather than ResetTemplateURL, |sync_url| is added with a fresh |
| 2416 // TemplateURLID. We don't need to sync the new ID back to the server since |
| 2417 // it's only relevant locally. |
| 2418 bool delete_default = (local_turl == GetDefaultSearchProvider()); |
| 2419 DCHECK(!delete_default || !is_default_search_managed_); |
| 2420 if (delete_default) |
| 2421 default_search_provider_ = NULL; |
2327 | 2422 |
2328 // Both |unapplied_sync_turl| and |applied_sync_turl| are known to Sync, so | 2423 // See comments in ResolveSyncKeywordConflict() regarding generating an |
2329 // don't delete either of them. Instead, determine which is "better" and | 2424 // ACTION_DELETE manually since Remove() won't do it. |
2330 // uniquify the other one, sending an update to the server for the updated | 2425 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); |
2331 // entry. | 2426 change_list->push_back(syncer::SyncChange(FROM_HERE, |
2332 const bool applied_turl_is_better = | 2427 syncer::SyncChange::ACTION_DELETE, |
2333 IsLocalTemplateURLBetter(applied_sync_turl, unapplied_sync_turl); | 2428 sync_data)); |
2334 TemplateURL* loser = applied_turl_is_better ? | 2429 Remove(local_turl); |
2335 unapplied_sync_turl : applied_sync_turl; | 2430 |
2336 string16 new_keyword = UniquifyKeyword(*loser, false); | 2431 // Force the local ID to kInvalidTemplateURLID so we can add it. |
2337 DCHECK(!GetTemplateURLForKeyword(new_keyword)); | 2432 sync_turl->data_.id = kInvalidTemplateURLID; |
2338 if (applied_turl_is_better) { | 2433 Add(scoped_sync_turl.release()); |
2339 // Just set the keyword of |unapplied_sync_turl|. The caller is responsible | 2434 if (delete_default) |
2340 // for adding or updating unapplied_sync_turl in the local model. | 2435 SetDefaultSearchProvider(sync_turl); |
2341 unapplied_sync_turl->data_.SetKeyword(new_keyword); | |
2342 } else { | 2436 } else { |
2343 // Update |applied_sync_turl| in the local model with the new keyword. | 2437 // Change the local TURL's GUID to the server's GUID and push an update to |
2344 TemplateURLData data(applied_sync_turl->data()); | 2438 // Sync. This ensures that the rest of local_url's fields are sync'd up to |
2345 data.SetKeyword(new_keyword); | 2439 // the server, and the next time local_url is synced, it is recognized by |
2346 TemplateURL new_turl(applied_sync_turl->profile(), data); | 2440 // having the same GUID. |
2347 UIThreadSearchTermsData search_terms_data(applied_sync_turl->profile()); | 2441 ResetTemplateURLGUID(local_turl, sync_turl->sync_guid()); |
2348 if (UpdateNoNotify(applied_sync_turl, new_turl, search_terms_data)) | 2442 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); |
2349 NotifyObservers(); | 2443 change_list->push_back(syncer::SyncChange(FROM_HERE, |
2350 } | 2444 syncer::SyncChange::ACTION_UPDATE, |
2351 // The losing TemplateURL should have their keyword updated. Send a change to | 2445 sync_data)); |
2352 // the server to reflect this change. | |
2353 syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*loser); | |
2354 change_list->push_back(syncer::SyncChange(FROM_HERE, | |
2355 syncer::SyncChange::ACTION_UPDATE, | |
2356 sync_data)); | |
2357 } | |
2358 | |
2359 void TemplateURLService::MergeInSyncTemplateURL( | |
2360 TemplateURL* sync_turl, | |
2361 const SyncDataMap& sync_data, | |
2362 syncer::SyncChangeList* change_list, | |
2363 SyncDataMap* local_data) { | |
2364 DCHECK(sync_turl); | |
2365 DCHECK(!GetTemplateURLForGUID(sync_turl->sync_guid())); | |
2366 DCHECK(IsFromSync(sync_turl, sync_data)); | |
2367 | |
2368 TemplateURL* conflicting_turl = | |
2369 FindNonExtensionTemplateURLForKeyword(sync_turl->keyword()); | |
2370 bool should_add_sync_turl = true; | |
2371 | |
2372 // If there was no TemplateURL in the local model that conflicts with | |
2373 // |sync_turl|, skip the following preparation steps and just add |sync_turl| | |
2374 // directly. Otherwise, modify |conflicting_turl| to make room for | |
2375 // |sync_turl|. | |
2376 if (conflicting_turl) { | |
2377 DCHECK(conflicting_turl); | |
2378 | |
2379 if (IsFromSync(conflicting_turl, sync_data)) { | |
2380 // |conflicting_turl| is already known to Sync, so we're not allowed to | |
2381 // remove it. In this case, we want to uniquify the worse one and send an | |
2382 // update for the changed keyword to sync. We can reuse the logic from | |
2383 // ResolveSyncKeywordConflict for this. | |
2384 ResolveSyncKeywordConflict(sync_turl, conflicting_turl, change_list); | |
2385 } else { | |
2386 // |conflicting_turl| is not yet known to Sync. If it is better, then we | |
2387 // want to transfer its values up to sync. Otherwise, we remove it and | |
2388 // allow the entry from Sync to overtake it in the model. | |
2389 const std::string guid = conflicting_turl->sync_guid(); | |
2390 if (IsLocalTemplateURLBetter(conflicting_turl, sync_turl)) { | |
2391 ResetTemplateURLGUID(conflicting_turl, sync_turl->sync_guid()); | |
2392 syncer::SyncData sync_data = | |
2393 CreateSyncDataFromTemplateURL(*conflicting_turl); | |
2394 change_list->push_back(syncer::SyncChange( | |
2395 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data)); | |
2396 if (conflicting_turl == GetDefaultSearchProvider() && | |
2397 !pending_synced_default_search_) { | |
2398 // If we're not waiting for the Synced default to come in, we should | |
2399 // override the pref with our new GUID. If we are waiting for the | |
2400 // arrival of a synced default, setting the pref here would cause us | |
2401 // to lose the GUID we are waiting on. | |
2402 PrefService* prefs = GetPrefs(); | |
2403 if (prefs) { | |
2404 prefs->SetString(prefs::kSyncedDefaultSearchProviderGUID, | |
2405 conflicting_turl->sync_guid()); | |
2406 } | |
2407 } | |
2408 // Note that in this case we do not add the Sync TemplateURL to the | |
2409 // local model, since we've effectively "merged" it in by updating the | |
2410 // local conflicting entry with its sync_guid. | |
2411 should_add_sync_turl = false; | |
2412 } else { | |
2413 // We guarantee that this isn't the local search provider. Otherwise, | |
2414 // local would have won. | |
2415 DCHECK(conflicting_turl != GetDefaultSearchProvider()); | |
2416 Remove(conflicting_turl); | |
2417 } | |
2418 // This TemplateURL was either removed or overwritten in the local model. | |
2419 // Remove the entry from the local data so it isn't pushed up to Sync. | |
2420 local_data->erase(guid); | |
2421 } | |
2422 } | |
2423 | |
2424 if (should_add_sync_turl) { | |
2425 const std::string guid = sync_turl->sync_guid(); | |
2426 // Force the local ID to kInvalidTemplateURLID so we can add it. | |
2427 TemplateURLData data(sync_turl->data()); | |
2428 data.id = kInvalidTemplateURLID; | |
2429 Add(new TemplateURL(profile_, data)); | |
2430 | |
2431 // Possibly set the newly added |turl| as the default search provider. | |
2432 SetDefaultSearchProviderIfNewlySynced(guid); | |
2433 } | 2446 } |
2434 } | 2447 } |
2435 | 2448 |
2436 void TemplateURLService::SetDefaultSearchProviderIfNewlySynced( | 2449 void TemplateURLService::SetDefaultSearchProviderIfNewlySynced( |
2437 const std::string& guid) { | 2450 const std::string& guid) { |
2438 // If we're not syncing or if default search is managed by policy, ignore. | 2451 // If we're not syncing or if default search is managed by policy, ignore. |
2439 if (!sync_processor_.get() || is_default_search_managed_) | 2452 if (!sync_processor_.get() || is_default_search_managed_) |
2440 return; | 2453 return; |
2441 | 2454 |
2442 PrefService* prefs = GetPrefs(); | 2455 PrefService* prefs = GetPrefs(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2475 // TODO(mpcomplete): If we allow editing extension keywords, then those | 2488 // TODO(mpcomplete): If we allow editing extension keywords, then those |
2476 // should be persisted to disk and synced. | 2489 // should be persisted to disk and synced. |
2477 if (template_url->sync_guid().empty() && | 2490 if (template_url->sync_guid().empty() && |
2478 !template_url->IsExtensionKeyword()) { | 2491 !template_url->IsExtensionKeyword()) { |
2479 template_url->data_.sync_guid = base::GenerateGUID(); | 2492 template_url->data_.sync_guid = base::GenerateGUID(); |
2480 if (service_.get()) | 2493 if (service_.get()) |
2481 service_->UpdateKeyword(template_url->data()); | 2494 service_->UpdateKeyword(template_url->data()); |
2482 } | 2495 } |
2483 } | 2496 } |
2484 } | 2497 } |
OLD | NEW |