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