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