1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// found in the LICENSE file. 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/typed_url_syncable_service.h" 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/auto_reset.h" 8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/logging.h" 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/metrics/histogram.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/history_backend.h" 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/base/net_util.h" 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "sync/protocol/typed_url_specifics.pb.h" 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace { 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// The server backend can't handle arbitrarily large node sizes, so to keep 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// the size under control we limit the visit array. 20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static const int kMaxTypedUrlVisits = 100; 21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// There's no limit on how many visits the history DB could have for a given 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// typed URL, so we limit how many we fetch from the DB to avoid crashes due to 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// running out of memory (http://crbug.com/89793). This value is different 25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// from kMaxTypedUrlVisits, as some of the visits fetched from the DB may be 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// RELOAD visits, which will be stripped. 27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static const int kMaxVisitsToFetch = 1000; 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// This is the threshold at which we start throttling sync updates for typed 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// URLs - any URLs with a typed_count >= this threshold will be throttled. 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static const int kTypedUrlVisitThrottleThreshold = 10; 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// This is the multiple we use when throttling sync updates. If the multiple is 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// N, we sync up every Nth update (i.e. when typed_count % N == 0). 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static const int kTypedUrlVisitThrottleMultiple = 10; 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} // namespace 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace history { 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kTypedUrlTag[] = "google_chrome_typed_urls"; 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static bool CheckVisitOrdering(const VisitVector& visits) { 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int64 previous_visit_time = 0; 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (VisitVector::const_iterator visit = visits.begin(); 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit != visits.end(); ++visit) { 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (visit != visits.begin()) { 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We allow duplicate visits here - they shouldn't really be allowed, but 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // they still seem to show up sometimes and we haven't figured out the 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // source, so we just log an error instead of failing an assertion. 51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // (http://crbug.com/91473). 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (previous_visit_time == visit->visit_time.ToInternalValue()) 53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Duplicate visit time encountered"; 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else if (previous_visit_time > visit->visit_time.ToInternalValue()) 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) previous_visit_time = visit->visit_time.ToInternalValue(); 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService::TypedUrlSyncableService( 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) HistoryBackend* history_backend) 65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) : history_backend_(history_backend), 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) processing_syncer_changes_(false), 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_loop_(base::MessageLoop::current()) { 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(history_backend_); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService::~TypedUrlSyncableService() { 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)syncer::SyncMergeResult TypedUrlSyncableService::MergeDataAndStartSyncing( 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::ModelType type, 78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!sync_processor_.get()); 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(sync_processor.get()); 84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(error_handler.get()); 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(type, syncer::TYPED_URLS); 86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncMergeResult merge_result(type); 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_processor_ = sync_processor.Pass(); 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_error_handler_ = error_handler.Pass(); 90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(mgist): Add implementation 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return merge_result; 94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::StopSyncing(syncer::ModelType type) { 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(type, syncer::TYPED_URLS); 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_processor_.reset(); 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_error_handler_.reset(); 102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)syncer::SyncDataList TypedUrlSyncableService::GetAllSyncData( 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::ModelType type) const { 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncDataList list; 108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(mgist): Add implementation 110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return list; 112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)syncer::SyncError TypedUrlSyncableService::ProcessSyncChanges( 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const tracked_objects::Location& from_here, 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const syncer::SyncChangeList& change_list) { 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(mgist): Add implementation 120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return syncer::SyncError(FROM_HERE, 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch syncer::SyncError::DATATYPE_ERROR, 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) "Typed url syncable service is not implemented.", 124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::TYPED_URLS); 125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::OnUrlsModified(URLRows* changed_urls) { 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(changed_urls); 130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (processing_syncer_changes_) 132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // These are changes originating from us, ignore. 133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!sync_processor_.get()) 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // Sync processor not yet initialized, don't sync. 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Create SyncChangeList. 137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChangeList changes; 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (URLRows::iterator url = changed_urls->begin(); 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url != changed_urls->end(); ++url) { 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Only care if the modified URL is typed. 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (url->typed_count() > 0) { 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If there were any errors updating the sync node, just ignore them and 144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // continue on to process the next URL. 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CreateOrUpdateSyncNode(*url, &changes); 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Send SyncChangeList to server if there are any changes. 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (changes.size() > 0) 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::OnUrlVisited(content::PageTransition transition, 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRow* row) { 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(row); 158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (processing_syncer_changes_) 160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // These are changes originating from us, ignore. 161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!sync_processor_.get()) 162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // Sync processor not yet initialized, don't sync. 163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!ShouldSyncVisit(transition, row)) 164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Create SyncChangeList. 167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChangeList changes; 168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CreateOrUpdateSyncNode(*row, &changes); 170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Send SyncChangeList to server if there are any changes. 172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (changes.size() > 0) 173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::OnUrlsDeleted(bool all_history, 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool expired, 178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(expected_loop_ == base::MessageLoop::current()); 180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (processing_syncer_changes_) 182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // These are changes originating from us, ignore. 183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!sync_processor_.get()) 184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; // Sync processor not yet initialized, don't sync. 185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Ignore URLs expired due to old age (we don't want to sync them as deletions 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // to avoid extra traffic up to the server, and also to make sure that a 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // client with a bad clock setting won't go on an expiration rampage and 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // delete all history from every client). The server will gracefully age out 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // the sync DB entries when they've been idle for long enough. 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (expired) 192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Create SyncChangeList. 195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChangeList changes; 196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (all_history) { 198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Delete all synced typed urls. 199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (std::set<GURL>::const_iterator url = synced_typed_urls_.begin(); 200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url != synced_typed_urls_.end(); ++url) { 201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) VisitVector visits; 202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRow row(*url); 203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) AddTypedUrlToChangeList(syncer::SyncChange::ACTION_DELETE, 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) row, visits, url->spec(), &changes); 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Clear cache of server state. 207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) synced_typed_urls_.clear(); 208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(rows); 210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Delete rows. 211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (URLRows::const_iterator row = rows->begin(); 212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) row != rows->end(); ++row) { 213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Add specifics to change list for all synced urls that were deleted. 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (synced_typed_urls_.find(row->url()) != synced_typed_urls_.end()) { 215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) VisitVector visits; 216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) AddTypedUrlToChangeList(syncer::SyncChange::ACTION_DELETE, 217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *row, visits, row->url().spec(), &changes); 218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Delete typed url from cache. 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) synced_typed_urls_.erase(row->url()); 220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Send SyncChangeList to server if there are any changes. 225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (changes.size() > 0) 226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool TypedUrlSyncableService::ShouldIgnoreUrl(const GURL& url) { 230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Ignore empty URLs. Not sure how this can happen (maybe import from other 231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // busted browsers, or misuse of the history API, or just plain bugs) but we 232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // can't deal with them. 233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (url.spec().empty()) 234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Ignore local file URLs. 237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (url.SchemeIsFile()) 238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Ignore localhost URLs. 241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (net::IsLocalhost(url.host())) 242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool TypedUrlSyncableService::ShouldSyncVisit( 248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) content::PageTransition page_transition, 249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRow* row) { 250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!row) 251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int typed_count = row->typed_count(); 253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) content::PageTransition transition = static_cast<content::PageTransition>( 254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) page_transition & content::PAGE_TRANSITION_CORE_MASK); 255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Just use an ad-hoc criteria to determine whether to ignore this 257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // notification. For most users, the distribution of visits is roughly a bell 258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // curve with a long tail - there are lots of URLs with < 5 visits so we want 259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // to make sure we sync up every visit to ensure the proper ordering of 260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // suggestions. But there are relatively few URLs with > 10 visits, and those 261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // tend to be more broadly distributed such that there's no need to sync up 262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // every visit to preserve their relative ordering. 263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return (transition == content::PAGE_TRANSITION_TYPED && 264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_count > 0 && 265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) (typed_count < kTypedUrlVisitThrottleThreshold || 266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) (typed_count % kTypedUrlVisitThrottleMultiple) == 0)); 267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool TypedUrlSyncableService::CreateOrUpdateSyncNode( 270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRow url, 271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChangeList* changes) { 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_GT(url.typed_count(), 0); 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (ShouldIgnoreUrl(url.url())) 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Get the visits for this node. 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) VisitVector visit_vector; 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!FixupURLAndGetVisits(&url, &visit_vector)) { 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DLOG(ERROR) << "Could not load visits for url: " << url.url(); 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!visit_vector.empty()); 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) std::string title = url.url().spec(); 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type; 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If server already has URL, then send a sync update, else add it. 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) change_type = 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) (synced_typed_urls_.find(url.url()) != synced_typed_urls_.end()) ? 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE : 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChange::ACTION_ADD; 293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Ensure cache of server state is up to date. 295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) synced_typed_urls_.insert(url.url()); 296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) AddTypedUrlToChangeList(change_type, url, visit_vector, title, changes); 298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::AddTypedUrlToChangeList( 303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChange::SyncChangeType change_type, 304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const URLRow& row, 305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const VisitVector& visits, 306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) std::string title, 307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChangeList* change_list) { 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_pb::EntitySpecifics entity_specifics; 309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url(); 310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (change_type == syncer::SyncChange::ACTION_DELETE) { 312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->set_url(row.url().spec()); 313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) WriteToTypedUrlSpecifics(row, visits, typed_url); 315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) change_list->push_back( 318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncChange(FROM_HERE, change_type, 319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) syncer::SyncData::CreateLocalData( 320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kTypedUrlTag, title, entity_specifics))); 321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TypedUrlSyncableService::WriteToTypedUrlSpecifics( 324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const URLRow& url, 325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const VisitVector& visits, 326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sync_pb::TypedUrlSpecifics* typed_url) { 327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!url.last_visit().is_null()); 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!visits.empty()); 330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(url.last_visit().ToInternalValue(), 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visits.back().visit_time.ToInternalValue()); 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->set_url(url.url().spec()); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typed_url->set_title(base::UTF16ToUTF8(url.title())); 335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->set_hidden(url.hidden()); 336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(CheckVisitOrdering(visits)); 338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool only_typed = false; 340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int skip_count = 0; 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (visits.size() > static_cast<size_t>(kMaxTypedUrlVisits)) { 343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int typed_count = 0; 344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int total = 0; 345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Walk the passed-in visit vector and count the # of typed visits. 346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (VisitVector::const_iterator visit = visits.begin(); 347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit != visits.end(); ++visit) { 348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) content::PageTransition transition = content::PageTransitionFromInt( 349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit->transition & content::PAGE_TRANSITION_CORE_MASK); 350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We ignore reload visits. 351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (transition == content::PAGE_TRANSITION_RELOAD) 352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++total; 354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (transition == content::PAGE_TRANSITION_TYPED) 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++typed_count; 356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We should have at least one typed visit. This can sometimes happen if 358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // the history DB has an inaccurate count for some reason (there's been 359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // bugs in the history code in the past which has left users in the wild 360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // with incorrect counts - http://crbug.com/84258). 361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(typed_count > 0); 362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_count > kMaxTypedUrlVisits) { 364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) only_typed = true; 365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) skip_count = typed_count - kMaxTypedUrlVisits; 366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (total > kMaxTypedUrlVisits) { 367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) skip_count = total - kMaxTypedUrlVisits; 368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (VisitVector::const_iterator visit = visits.begin(); 372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit != visits.end(); ++visit) { 373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) content::PageTransition transition = content::PageTransitionFromInt( 374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit->transition & content::PAGE_TRANSITION_CORE_MASK); 375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Skip reload visits. 376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (transition == content::PAGE_TRANSITION_RELOAD) 377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If we only have room for typed visits, then only add typed visits. 380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (only_typed && transition != content::PAGE_TRANSITION_TYPED) 381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (skip_count > 0) { 384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We have too many entries to fit, so we need to skip the oldest ones. 385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Only skip typed URLs if there are too many typed URLs to fit. 386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (only_typed || transition != content::PAGE_TRANSITION_TYPED) { 387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) --skip_count; 388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) continue; 389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->add_visits(visit->visit_time.ToInternalValue()); 392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->add_visit_transitions(visit->transition); 393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(skip_count, 0); 395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url->visits_size() == 0) { 397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If we get here, it's because we don't actually have any TYPED visits 398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // even though the visit's typed_count > 0 (corrupted typed_count). So 399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // let's go ahead and add a RELOAD visit at the most recent visit since 400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // it's not legal to have an empty visit array (yet another workaround 401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // for http://crbug.com/84258). 402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->add_visits(url.last_visit().ToInternalValue()); 403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url->add_visit_transitions(content::PAGE_TRANSITION_RELOAD); 404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK_GT(typed_url->visits_size(), 0); 406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK_LE(typed_url->visits_size(), kMaxTypedUrlVisits); 407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK_EQ(typed_url->visits_size(), typed_url->visit_transitions_size()); 408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool TypedUrlSyncableService::FixupURLAndGetVisits( 411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRow* url, 412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) VisitVector* visits) { 413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++num_db_accesses_; 414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK(history_backend_); 415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!history_backend_->GetMostRecentVisitsForURL( 416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url->id(), kMaxVisitsToFetch, visits)) { 417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ++num_db_errors_; 418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Sometimes (due to a bug elsewhere in the history or sync code, or due to 422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // a crash between adding a URL to the history database and updating the 423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // visit DB) the visit vector for a URL can be empty. If this happens, just 424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // create a new visit whose timestamp is the same as the last_visit time. 425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // This is a workaround for http://crbug.com/84258. 426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (visits->empty()) { 427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DVLOG(1) << "Found empty visits for URL: " << url->url(); 428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) VisitRow visit( 429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url->id(), url->last_visit(), 0, content::PAGE_TRANSITION_TYPED, 0); 430b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visits->push_back(visit); 431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 433b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // GetMostRecentVisitsForURL() returns the data in the opposite order that 434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // we need it, so reverse it. 435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) std::reverse(visits->begin(), visits->end()); 436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Sometimes, the last_visit field in the URL doesn't match the timestamp of 438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // the last visit in our visit array (they come from different tables, so 439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // crashes/bugs can cause them to mismatch), so just set it here. 440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) url->set_last_visit(visits->back().visit_time); 441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(CheckVisitOrdering(*visits)); 442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} // namespace history 446