typed_url_model_associator.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/typed_url_model_associator.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_backend.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncapi.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_service.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kTypedUrlTag[] = "google_chrome_typed_urls"; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTypedUrlModelAssociator::TypedUrlModelAssociator( 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileSyncService* sync_service, 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::HistoryBackend* history_backend) 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : sync_service_(sync_service), 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_backend_(history_backend), 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url_node_id_(sync_api::kInvalidId), 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expected_loop_(MessageLoop::current()) { 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(sync_service_); 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(history_backend_); 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::UI)); 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::AssociateModels() { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(INFO) << "Associating TypedUrl Models"; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<history::URLRow> typed_urls; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_backend_->GetAllTypedURLs(&typed_urls)) { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not get the typed_url entries."; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get all the visits. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<history::URLID, history::VisitVector> visit_vectors; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<history::URLRow>::iterator ix = typed_urls.begin(); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ix != typed_urls.end(); ++ix) { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_backend_->GetVisitsForURL(ix->id(), 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(visit_vectors[ix->id()]))) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not get the url's visits."; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!visit_vectors[ix->id()].empty()); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TypedUrlTitleVector titles; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TypedUrlVector new_urls; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TypedUrlVisitVector new_visits; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TypedUrlUpdateVector updated_urls; 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteTransaction trans( 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->backend()->GetUserShareHandle()); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode typed_url_root(&trans); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!typed_url_root.InitByTagLookup(kTypedUrlTag)) { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Server did not create the top-level typed_url node. We " 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "might be running against an out-of-date server."; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<std::string> current_urls; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<history::URLRow>::iterator ix = typed_urls.begin(); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ix != typed_urls.end(); ++ix) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string tag = ix->url().spec(); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::VisitVector& visits = visit_vectors[ix->id()]; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(visits.size() == static_cast<size_t>(ix->visit_count())); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visits.size() != static_cast<size_t>(ix->visit_count())) { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Visit count does not match."; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode node(&trans); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& typed_url( 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node.GetTypedUrlSpecifics()); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(tag, typed_url.url()); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::URLRow new_url(ix->url()); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::Time> added_visits; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int difference = MergeUrls(typed_url, *ix, &visits, &new_url, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &added_visits); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (difference & DIFF_NODE_CHANGED) { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode write_node(&trans); 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!write_node.InitByClientTagLookup(syncable::TYPED_URLS, tag)) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Failed to edit typed_url sync node."; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteToSyncNode(new_url, visits, &write_node); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (difference & DIFF_TITLE_CHANGED) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch titles.push_back(std::pair<GURL, string16>(new_url.url(), 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.title())); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (difference & DIFF_ROW_CHANGED) { 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch updated_urls.push_back( 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<history::URLID, history::URLRow>(ix->id(), new_url)); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (difference & DIFF_VISITS_ADDED) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits.push_back( 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<GURL, std::vector<base::Time> >(ix->url(), 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch added_visits)); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Associate(&tag, node.GetId()); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode node(&trans); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!node.InitUniqueByCreation(syncable::TYPED_URLS, 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url_root, tag)) { 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Failed to create typed_url sync node."; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node.SetTitle(UTF8ToWide(tag)); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteToSyncNode(*ix, visits, &node); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Associate(&tag, node.GetId()); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_urls.insert(tag); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 sync_child_id = typed_url_root.GetFirstChildId(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (sync_child_id != sync_api::kInvalidId) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode sync_child_node(&trans); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!sync_child_node.InitByIdLookup(sync_child_id)) { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Failed to fetch child node."; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& typed_url( 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_child_node.GetTypedUrlSpecifics()); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_urls.find(typed_url.url()) == current_urls.end()) { 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits.push_back( 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<GURL, std::vector<base::Time> >( 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL(typed_url.url()), 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::Time>())); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::Time>& visits = new_visits.back().second; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::URLRow new_url(GURL(typed_url.url())); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.set_title(UTF8ToUTF16(typed_url.title())); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we add a new url, the last visit is always added, thus we set 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the initial visit count to one. This value will be automatically 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // incremented as visits are added. 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.set_visit_count(1); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.set_typed_count(typed_url.typed_count()); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.set_hidden(typed_url.hidden()); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The latest visit gets added automatically, so skip it. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int c = 0; c < typed_url.visit_size() - 1; ++c) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(typed_url.visit(c) < typed_url.visit(c + 1)); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visits.push_back(base::Time::FromInternalValue(typed_url.visit(c))); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url.set_last_visit(base::Time::FromInternalValue( 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.visit(typed_url.visit_size() - 1))); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Associate(&typed_url.url(), sync_child_node.GetId()); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_urls.push_back(new_url); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_child_id = sync_child_node.GetSuccessorId(); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since we're on the history thread, we don't have to worry about updating 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the history database after closing the write transaction, since 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this is the only thread that writes to the database. We also don't have 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to worry about the sync model getting out of sync, because changes are 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // propogated to the ChangeProcessor on this thread. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return WriteToHistoryBackend(&titles, &new_urls, &updated_urls, 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &new_visits, NULL); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::DeleteAllNodes( 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteTransaction* trans) { 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (TypedUrlToSyncIdMap::iterator node_id = id_map_.begin(); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node_id != id_map_.end(); ++node_id) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode sync_node(trans); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!sync_node.InitByIdLookup(node_id->second)) { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Typed url node lookup failed."; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_node.Remove(); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_.clear(); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.clear(); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::DisassociateModels() { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_.clear(); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.clear(); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(has_nodes); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *has_nodes = false; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 typed_url_sync_id; 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetSyncIdForTaggedNode(kTypedUrlTag, &typed_url_sync_id)) { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Server did not create the top-level typed_url node. We " 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "might be running against an out-of-date server."; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadTransaction trans( 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->backend()->GetUserShareHandle()); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode typed_url_node(&trans); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!typed_url_node.InitByIdLookup(typed_url_sync_id)) { 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Server did not create the top-level typed_url node. We " 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "might be running against an out-of-date server."; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The sync model has user created nodes if the typed_url folder has any 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // children. 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *has_nodes = sync_api::kInvalidId != typed_url_node.GetFirstChildId(); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 TypedUrlModelAssociator::GetSyncIdFromChromeId( 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string typed_url) { 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TypedUrlToSyncIdMap::const_iterator iter = id_map_.find(typed_url); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TypedUrlModelAssociator::Associate( 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string* typed_url, int64 sync_id) { 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(sync_api::kInvalidId, sync_id); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(id_map_.find(*typed_url) == id_map_.end()); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_[*typed_url] = sync_id; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_[sync_id] = *typed_url; 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TypedUrlModelAssociator::Disassociate(int64 sync_id) { 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncIdToTypedUrlMap::iterator iter = id_map_inverse_.find(sync_id); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (iter == id_map_inverse_.end()) 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(id_map_.erase(iter->second)); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.erase(iter); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::GetSyncIdForTaggedNode(const std::string& tag, 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64* sync_id) { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadTransaction trans( 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->backend()->GetUserShareHandle()); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode sync_node(&trans); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!sync_node.InitByTagLookup(tag.c_str())) 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *sync_id = sync_node.GetId(); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TypedUrlModelAssociator::WriteToHistoryBackend( 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TypedUrlTitleVector* titles, 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TypedUrlVector* new_urls, 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TypedUrlUpdateVector* updated_urls, 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TypedUrlVisitVector* new_visits, 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::VisitVector* deleted_visits) { 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (titles) { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (TypedUrlTitleVector::const_iterator title = titles->begin(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title != titles->end(); ++title) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_backend_->SetPageTitle(title->first, title->second); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_urls) { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_backend_->AddPagesWithDetails(*new_urls); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (updated_urls) { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (TypedUrlUpdateVector::const_iterator url = updated_urls->begin(); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url != updated_urls->end(); ++url) { 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_backend_->UpdateURL(url->first, url->second)) { 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not update page: " << url->second.url().spec(); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_visits) { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (TypedUrlVisitVector::const_iterator visits = new_visits->begin(); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visits != new_visits->end(); ++visits) { 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_backend_->AddVisits(visits->first, visits->second)) { 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not add visits."; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (deleted_visits) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_backend_->RemoveVisits(*deleted_visits)) { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not remove visits."; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TypedUrlModelAssociator::MergeUrls( 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& typed_url, 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::URLRow& url, 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::VisitVector* visits, 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::URLRow* new_url, 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::Time>* new_visits) { 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(new_url); 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!typed_url.url().compare(url.url().spec())); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!typed_url.url().compare(new_url->url().spec())); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(visits->size()); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_visit_count(visits->size()); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Convert these values only once. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 typed_title(UTF8ToUTF16(typed_url.title())); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time typed_visit = 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time::FromInternalValue( 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.visit(typed_url.visit_size() - 1)); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is a bitfield represting what we'll need to update with the output 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // value. 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int different = DIFF_NONE; 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if the non-incremented values changed. 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((typed_title.compare(url.title()) != 0) || 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (typed_url.hidden() != url.hidden())) { 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Use the values from the most recent visit. 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (typed_visit >= url.last_visit()) { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_title(typed_title); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_hidden(typed_url.hidden()); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_ROW_CHANGED; 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're changing the local title, note this. 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_url->title().compare(url.title()) != 0) { 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_TITLE_CHANGED; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_title(url.title()); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_hidden(url.hidden()); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_NODE_CHANGED; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No difference. 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_title(url.title()); 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_hidden(url.hidden()); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For typed count, we just select the maximum value. 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (typed_url.typed_count() > url.typed_count()) { 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_typed_count(typed_url.typed_count()); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_ROW_CHANGED; 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (typed_url.typed_count() < url.typed_count()) { 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_typed_count(url.typed_count()); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_NODE_CHANGED; 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No difference. 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_typed_count(typed_url.typed_count()); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t left_visit_count = typed_url.visit_size(); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t right_visit_count = visits->size(); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t left = 0; 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t right = 0; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (left < left_visit_count && right < right_visit_count) { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time left_time = base::Time::FromInternalValue(typed_url.visit(left)); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (left_time < (*visits)[right].visit_time) { 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_VISITS_ADDED; 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits->push_back(left_time); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This visit is added to visits below. 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++left; 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (left_time > (*visits)[right].visit_time) { 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_NODE_CHANGED; 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++right; 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++left; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++right; 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for ( ; left < left_visit_count; ++left) { 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch different |= DIFF_VISITS_ADDED; 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time left_time = base::Time::FromInternalValue(typed_url.visit(left)); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits->push_back(left_time); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This visit is added to visits below. 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (different & DIFF_VISITS_ADDED) { 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::VisitVector::iterator visit_ix = visits->begin(); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<base::Time>::iterator new_visit = new_visits->begin(); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visit != new_visits->end(); ++new_visit) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (visit_ix != visits->end() && *new_visit > visit_ix->visit_time) { 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++visit_ix; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_ix = visits->insert(visit_ix, 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::VisitRow(url.id(), *new_visit, 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 0, 0)); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++visit_ix; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_url->set_last_visit(visits->back().visit_time); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(static_cast<size_t>(new_url->visit_count()) == 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (visits->size() - new_visits->size())); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return different; 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TypedUrlModelAssociator::WriteToSyncNode( 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::URLRow& url, 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::VisitVector& visits, 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode* node) { 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!url.last_visit().is_null()); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!visits.empty()); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(url.last_visit() == visits.back().visit_time); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::TypedUrlSpecifics typed_url; 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.set_url(url.url().spec()); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.set_title(UTF16ToUTF8(url.title())); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.set_typed_count(url.typed_count()); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.set_hidden(url.hidden()); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (history::VisitVector::const_iterator visit = visits.begin(); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit != visits.end(); ++visit) { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url.add_visit(visit->visit_time.ToInternalValue()); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node->SetTypedUrlSpecifics(typed_url); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TypedUrlModelAssociator::DiffVisits( 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::VisitVector& old_visits, 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& new_url, 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::Time>* new_visits, 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::VisitVector* removed_visits) { 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t left_visit_count = old_visits.size(); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t right_visit_count = new_url.visit_size(); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t left = 0; 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t right = 0; 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (left < left_visit_count && right < right_visit_count) { 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time right_time = base::Time::FromInternalValue(new_url.visit(right)); 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (old_visits[left].visit_time < right_time) { 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch removed_visits->push_back(old_visits[left]); 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++left; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (old_visits[left].visit_time > right_time) { 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits->push_back(right_time); 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++right; 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++left; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++right; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for ( ; left < left_visit_count; ++left) { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch removed_visits->push_back(old_visits[left]); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for ( ; right < right_visit_count; ++right) { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_visits->push_back(base::Time::FromInternalValue(new_url.visit(right))); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 477