Index: chrome/browser/sync/glue/typed_url_model_associator.cc |
diff --git a/chrome/browser/sync/glue/typed_url_model_associator.cc b/chrome/browser/sync/glue/typed_url_model_associator.cc |
index 080a5981b9c81b7cc54f4aafb6370b746ab7e8a5..1415ffeafbe9bbfe98621052f7f6091ae5bf3d4e 100644 |
--- a/chrome/browser/sync/glue/typed_url_model_associator.cc |
+++ b/chrome/browser/sync/glue/typed_url_model_associator.cc |
@@ -42,94 +42,101 @@ bool TypedUrlModelAssociator::AssociateModels() { |
return false; |
} |
- sync_api::WriteTransaction trans( |
- sync_service_->backend()->GetUserShareHandle()); |
- sync_api::ReadNode typed_url_root(&trans); |
- if (!typed_url_root.InitByTagLookup(kTypedUrlTag)) { |
- LOG(ERROR) << "Server did not create the top-level typed_url node. We " |
- << "might be running against an out-of-date server."; |
- return false; |
- } |
- |
- std::set<std::string> current_urls; |
TypedUrlTitleVector titles; |
TypedUrlVector new_urls; |
TypedUrlUpdateVector updated_urls; |
- for (std::vector<history::URLRow>::iterator ix = typed_urls.begin(); |
- ix != typed_urls.end(); ++ix) { |
- std::string tag = ix->url().spec(); |
- |
- sync_api::ReadNode node(&trans); |
- if (node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { |
- const sync_pb::TypedUrlSpecifics& typed_url(node.GetTypedUrlSpecifics()); |
- DCHECK_EQ(tag, typed_url.url()); |
+ { |
+ sync_api::WriteTransaction trans( |
+ sync_service_->backend()->GetUserShareHandle()); |
+ sync_api::ReadNode typed_url_root(&trans); |
+ if (!typed_url_root.InitByTagLookup(kTypedUrlTag)) { |
+ LOG(ERROR) << "Server did not create the top-level typed_url node. We " |
+ << "might be running against an out-of-date server."; |
+ return false; |
+ } |
- history::URLRow new_url(ix->url()); |
+ std::set<std::string> current_urls; |
+ for (std::vector<history::URLRow>::iterator ix = typed_urls.begin(); |
+ ix != typed_urls.end(); ++ix) { |
+ std::string tag = ix->url().spec(); |
+ |
+ sync_api::ReadNode node(&trans); |
+ if (node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { |
+ const sync_pb::TypedUrlSpecifics& typed_url(node.GetTypedUrlSpecifics()); |
+ DCHECK_EQ(tag, typed_url.url()); |
+ |
+ history::URLRow new_url(ix->url()); |
+ |
+ int difference = MergeUrls(typed_url, *ix, &new_url); |
+ if (difference & DIFF_NODE_CHANGED) { |
+ sync_api::WriteNode write_node(&trans); |
+ if (!write_node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { |
+ LOG(ERROR) << "Failed to edit typed_url sync node."; |
+ return false; |
+ } |
+ WriteToSyncNode(new_url, &write_node); |
+ } |
+ if (difference & DIFF_TITLE_CHANGED) { |
+ titles.push_back(std::pair<GURL, std::wstring>(new_url.url(), |
+ new_url.title())); |
+ } |
+ if (difference & DIFF_ROW_CHANGED) { |
+ updated_urls.push_back( |
+ std::pair<history::URLID, history::URLRow>(ix->id(), new_url)); |
+ } |
- int difference = MergeUrls(typed_url, *ix, &new_url); |
- if (difference & DIFF_NODE_CHANGED) { |
- sync_api::WriteNode write_node(&trans); |
- if (!write_node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { |
- LOG(ERROR) << "Failed to edit typed_url sync node."; |
+ Associate(&tag, node.GetId()); |
+ } else { |
+ sync_api::WriteNode node(&trans); |
+ if (!node.InitUniqueByCreation(syncable::TYPED_URLS, |
+ typed_url_root, tag)) { |
+ LOG(ERROR) << "Failed to create typed_url sync node."; |
return false; |
} |
- WriteToSyncNode(new_url, &write_node); |
- } |
- if (difference & DIFF_TITLE_CHANGED) { |
- titles.push_back(std::pair<GURL, std::wstring>(new_url.url(), |
- new_url.title())); |
- } |
- if (difference & DIFF_ROW_CHANGED) { |
- updated_urls.push_back( |
- std::pair<history::URLID, history::URLRow>(ix->id(), new_url)); |
- } |
- Associate(&tag, node.GetId()); |
- } else { |
- sync_api::WriteNode node(&trans); |
- if (!node.InitUniqueByCreation(syncable::TYPED_URLS, |
- typed_url_root, tag)) { |
- LOG(ERROR) << "Failed to create typed_url sync node."; |
- return false; |
- } |
+ node.SetTitle(UTF8ToWide(tag)); |
+ WriteToSyncNode(*ix, &node); |
- node.SetTitle(UTF8ToWide(tag)); |
- WriteToSyncNode(*ix, &node); |
+ Associate(&tag, node.GetId()); |
+ } |
- Associate(&tag, node.GetId()); |
+ current_urls.insert(tag); |
} |
- current_urls.insert(tag); |
- } |
+ int64 sync_child_id = typed_url_root.GetFirstChildId(); |
+ while (sync_child_id != sync_api::kInvalidId) { |
+ sync_api::ReadNode sync_child_node(&trans); |
+ if (!sync_child_node.InitByIdLookup(sync_child_id)) { |
+ LOG(ERROR) << "Failed to fetch child node."; |
+ return false; |
+ } |
+ const sync_pb::TypedUrlSpecifics& typed_url( |
+ sync_child_node.GetTypedUrlSpecifics()); |
- int64 sync_child_id = typed_url_root.GetFirstChildId(); |
- while (sync_child_id != sync_api::kInvalidId) { |
- sync_api::ReadNode sync_child_node(&trans); |
- if (!sync_child_node.InitByIdLookup(sync_child_id)) { |
- LOG(ERROR) << "Failed to fetch child node."; |
- return false; |
- } |
- const sync_pb::TypedUrlSpecifics& typed_url( |
- sync_child_node.GetTypedUrlSpecifics()); |
+ if (current_urls.find(typed_url.url()) == current_urls.end()) { |
+ history::URLRow new_url(GURL(typed_url.url())); |
- if (current_urls.find(typed_url.url()) == current_urls.end()) { |
- history::URLRow new_url(GURL(typed_url.url())); |
+ new_url.set_title(UTF8ToWide(typed_url.title())); |
+ new_url.set_visit_count(typed_url.visit_count()); |
+ new_url.set_typed_count(typed_url.typed_count()); |
+ new_url.set_last_visit( |
+ base::Time::FromInternalValue(typed_url.last_visit())); |
+ new_url.set_hidden(typed_url.hidden()); |
- new_url.set_title(UTF8ToWide(typed_url.title())); |
- new_url.set_visit_count(typed_url.visit_count()); |
- new_url.set_typed_count(typed_url.typed_count()); |
- new_url.set_last_visit( |
- base::Time::FromInternalValue(typed_url.last_visit())); |
- new_url.set_hidden(typed_url.hidden()); |
+ Associate(&typed_url.url(), sync_child_node.GetId()); |
+ new_urls.push_back(new_url); |
+ } |
- Associate(&typed_url.url(), sync_child_node.GetId()); |
- new_urls.push_back(new_url); |
+ sync_child_id = sync_child_node.GetSuccessorId(); |
} |
- |
- sync_child_id = sync_child_node.GetSuccessorId(); |
} |
+ // Since we're on the history thread, we don't have to worry about updating |
+ // the history database after closing the write transaction, since |
+ // this is the only thread that writes to the database. We also don't have |
+ // to worry about the sync model getting out of sync, because changes are |
+ // propogated to the ChangeProcessor on this thread. |
WriteToHistoryBackend(&titles, &new_urls, &updated_urls); |
return true; |