Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: components/history/core/browser/typed_url_sync_bridge.cc

Issue 2961723003: [USS] Implement ApplySyncChanges and OnURLVisited/Modified/Deleted. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/history/core/browser/typed_url_sync_bridge.h" 5 #include "components/history/core/browser/typed_url_sync_bridge.h"
6 6
7 #include "base/big_endian.h" 7 #include "base/big_endian.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 18 matching lines...) Expand all
29 // the size under control we limit the visit array. 29 // the size under control we limit the visit array.
30 static const int kMaxTypedUrlVisits = 100; 30 static const int kMaxTypedUrlVisits = 100;
31 31
32 // There's no limit on how many visits the history DB could have for a given 32 // There's no limit on how many visits the history DB could have for a given
33 // typed URL, so we limit how many we fetch from the DB to avoid crashes due to 33 // typed URL, so we limit how many we fetch from the DB to avoid crashes due to
34 // running out of memory (http://crbug.com/89793). This value is different 34 // running out of memory (http://crbug.com/89793). This value is different
35 // from kMaxTypedUrlVisits, as some of the visits fetched from the DB may be 35 // from kMaxTypedUrlVisits, as some of the visits fetched from the DB may be
36 // RELOAD visits, which will be stripped. 36 // RELOAD visits, which will be stripped.
37 static const int kMaxVisitsToFetch = 1000; 37 static const int kMaxVisitsToFetch = 1000;
38 38
39 // This is the threshold at which we start throttling sync updates for typed
40 // URLs - any URLs with a typed_count >= this threshold will be throttled.
41 static const int kTypedUrlVisitThrottleThreshold = 10;
42
43 // This is the multiple we use when throttling sync updates. If the multiple is
44 // N, we sync up every Nth update (i.e. when typed_count % N == 0).
45 static const int kTypedUrlVisitThrottleMultiple = 10;
46
39 // Enforce oldest to newest visit order. 47 // Enforce oldest to newest visit order.
40 static bool CheckVisitOrdering(const VisitVector& visits) { 48 static bool CheckVisitOrdering(const VisitVector& visits) {
41 int64_t previous_visit_time = 0; 49 int64_t previous_visit_time = 0;
42 for (VisitVector::const_iterator visit = visits.begin(); 50 for (VisitVector::const_iterator visit = visits.begin();
43 visit != visits.end(); ++visit) { 51 visit != visits.end(); ++visit) {
44 if (visit != visits.begin() && 52 if (visit != visits.begin() &&
45 previous_visit_time > visit->visit_time.ToInternalValue()) 53 previous_visit_time > visit->visit_time.ToInternalValue())
46 return false; 54 return false;
47 55
48 previous_visit_time = visit->visit_time.ToInternalValue(); 56 previous_visit_time = visit->visit_time.ToInternalValue();
49 } 57 }
50 return true; 58 return true;
51 } 59 }
52 60
53 std::string GetStorageKeyFromURLRow(const URLRow& row) { 61 std::string GetStorageKeyFromURLRow(const URLRow& row) {
62 DCHECK_NE(row.id(), 0);
54 std::string storage_key(sizeof(row.id()), 0); 63 std::string storage_key(sizeof(row.id()), 0);
55 base::WriteBigEndian<URLID>(&storage_key[0], row.id()); 64 base::WriteBigEndian<URLID>(&storage_key[0], row.id());
56 return storage_key; 65 return storage_key;
57 } 66 }
58 67
59 bool HasTypedUrl(const VisitVector& visits) { 68 bool HasTypedUrl(const VisitVector& visits) {
60 auto typed_url_visit = std::find_if( 69 auto typed_url_visit = std::find_if(
61 visits.begin(), visits.end(), [](const history::VisitRow& visit) { 70 visits.begin(), visits.end(), [](const history::VisitRow& visit) {
62 return ui::PageTransitionCoreTypeIs(visit.transition, 71 return ui::PageTransitionCoreTypeIs(visit.transition,
63 ui::PAGE_TRANSITION_TYPED); 72 ui::PAGE_TRANSITION_TYPED);
(...skipping 27 matching lines...) Expand all
91 return base::MakeUnique<syncer::SyncMetadataStoreChangeList>( 100 return base::MakeUnique<syncer::SyncMetadataStoreChangeList>(
92 sync_metadata_database_, syncer::TYPED_URLS); 101 sync_metadata_database_, syncer::TYPED_URLS);
93 } 102 }
94 103
95 base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData( 104 base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
96 std::unique_ptr<MetadataChangeList> metadata_change_list, 105 std::unique_ptr<MetadataChangeList> metadata_change_list,
97 EntityChangeList entity_data) { 106 EntityChangeList entity_data) {
98 DCHECK(sequence_checker_.CalledOnValidSequence()); 107 DCHECK(sequence_checker_.CalledOnValidSequence());
99 108
100 // Create a mapping of all local data by URLID. These will be narrowed down 109 // Create a mapping of all local data by URLID. These will be narrowed down
101 // by CreateOrUpdateUrl() to include only the entries different from sync 110 // by MergeURLWithSync() to include only the entries different from sync
102 // server data. 111 // server data.
103 TypedURLMap new_db_urls; 112 TypedURLMap new_db_urls;
104 113
105 // Get all the visits and map the URLRows by URL. 114 // Get all the visits and map the URLRows by URL.
106 URLVisitVectorMap local_visit_vectors; 115 URLVisitVectorMap local_visit_vectors;
107 116
108 if (!GetValidURLsAndVisits(&local_visit_vectors, &new_db_urls)) { 117 if (!GetValidURLsAndVisits(&local_visit_vectors, &new_db_urls)) {
109 return ModelError( 118 return ModelError(
110 FROM_HERE, "Could not get the typed_url entries from HistoryBackend."); 119 FROM_HERE, "Could not get the typed_url entries from HistoryBackend.");
111 } 120 }
112 121
113 // New sync data organized for different write operations to history backend. 122 // New sync data organized for different write operations to history backend.
114 history::URLRows new_synced_urls; 123 history::URLRows new_synced_urls;
115 history::URLRows updated_synced_urls; 124 history::URLRows updated_synced_urls;
116 TypedURLVisitVector new_synced_visits; 125 TypedURLVisitVector new_synced_visits;
117 126
118 // Iterate through entity_data and check for all the urls that 127 // Iterate through entity_data and check for all the urls that
119 // sync already knows about. CreateOrUpdateUrl() will remove urls that 128 // sync already knows about. MergeURLWithSync() will remove urls that
120 // are the same as the synced ones from |new_db_urls|. 129 // are the same as the synced ones from |new_db_urls|.
121 for (const EntityChange& entity_change : entity_data) { 130 for (const EntityChange& entity_change : entity_data) {
122 DCHECK(entity_change.data().specifics.has_typed_url()); 131 DCHECK(entity_change.data().specifics.has_typed_url());
123 const TypedUrlSpecifics& specifics = 132 const TypedUrlSpecifics& specifics =
124 entity_change.data().specifics.typed_url(); 133 entity_change.data().specifics.typed_url();
125 if (ShouldIgnoreUrl(GURL(specifics.url()))) 134 if (ShouldIgnoreUrl(GURL(specifics.url())))
126 continue; 135 continue;
127 136
128 // Ignore old sync urls that don't have any transition data stored with 137 // Ignore old sync urls that don't have any transition data stored with
129 // them, or transition data that does not match the visit data (will be 138 // them, or transition data that does not match the visit data (will be
130 // deleted below). 139 // deleted below).
131 if (specifics.visit_transitions_size() == 0 || 140 if (specifics.visit_transitions_size() == 0 ||
132 specifics.visit_transitions_size() != specifics.visits_size()) { 141 specifics.visit_transitions_size() != specifics.visits_size()) {
133 // Generate a debug assertion to help track down http://crbug.com/91473, 142 // Generate a debug assertion to help track down http://crbug.com/91473,
134 // even though we gracefully handle this case by overwriting this node. 143 // even though we gracefully handle this case by overwriting this node.
135 DCHECK_EQ(specifics.visits_size(), specifics.visit_transitions_size()); 144 DCHECK_EQ(specifics.visits_size(), specifics.visit_transitions_size());
136 DVLOG(1) << "Ignoring obsolete sync url with no visit transition info."; 145 DVLOG(1) << "Ignoring obsolete sync url with no visit transition info.";
137 146
138 continue; 147 continue;
139 } 148 }
140 UpdateUrlFromServer(specifics, &new_db_urls, &local_visit_vectors, 149 MergeURLWithSync(specifics, &new_db_urls, &local_visit_vectors,
141 &new_synced_urls, &new_synced_visits, 150 &new_synced_urls, &new_synced_visits,
142 &updated_synced_urls); 151 &updated_synced_urls);
143 } 152 }
144 153
145 for (const auto& kv : new_db_urls) { 154 for (const auto& kv : new_db_urls) {
146 if (!HasTypedUrl(local_visit_vectors[kv.first])) { 155 if (!HasTypedUrl(local_visit_vectors[kv.first])) {
147 // This URL has no TYPED visits, don't sync it 156 // This URL has no TYPED visits, don't sync it
148 continue; 157 continue;
149 } 158 }
150 std::string storage_key = GetStorageKeyFromURLRow(kv.second); 159 std::string storage_key = GetStorageKeyFromURLRow(kv.second);
151 change_processor()->Put( 160 change_processor()->Put(
152 storage_key, CreateEntityData(kv.second, local_visit_vectors[kv.first]), 161 storage_key, CreateEntityData(kv.second, local_visit_vectors[kv.first]),
(...skipping 24 matching lines...) Expand all
177 186
178 return static_cast<syncer::SyncMetadataStoreChangeList*>( 187 return static_cast<syncer::SyncMetadataStoreChangeList*>(
179 metadata_change_list.get()) 188 metadata_change_list.get())
180 ->TakeError(); 189 ->TakeError();
181 } 190 }
182 191
183 base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges( 192 base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
184 std::unique_ptr<MetadataChangeList> metadata_change_list, 193 std::unique_ptr<MetadataChangeList> metadata_change_list,
185 EntityChangeList entity_changes) { 194 EntityChangeList entity_changes) {
186 DCHECK(sequence_checker_.CalledOnValidSequence()); 195 DCHECK(sequence_checker_.CalledOnValidSequence());
187 NOTIMPLEMENTED(); 196 DCHECK(sync_metadata_database_);
197
198 std::vector<GURL> pending_deleted_urls;
199 TypedURLVisitVector new_synced_visits;
200 history::VisitVector deleted_visits;
201 history::URLRows updated_synced_urls;
202 history::URLRows new_synced_urls;
203
204 for (const EntityChange& entity_change : entity_changes) {
pavely 2017/07/06 19:28:29 You need to call UpdateStorageKey for ACTION_ADD s
Gang Wu 2017/07/10 19:53:25 Done.
205 if (entity_change.type() == EntityChange::ACTION_DELETE) {
206 URLRow url_row;
207 int64_t url_id = sync_metadata_database_->StorageKeyToURLID(
208 entity_change.storage_key());
209 if (!history_backend_->GetURLByID(url_id, &url_row)) {
210 // Ignoring the case which no matching URLRow with URLID |url_id|.
211 continue;
212 }
213 if (url_row.url().is_empty()) {
214 // Ignoring empty URL in sync DB;
pavely 2017/07/06 19:28:29 url_row comes from history, not sync db. Dot at th
Gang Wu 2017/07/10 19:53:25 Done.
215 continue;
216 }
217
218 pending_deleted_urls.push_back(url_row.url());
219 continue;
220 }
221
222 DCHECK(entity_change.data().specifics.has_typed_url());
223 const TypedUrlSpecifics& specifics =
224 entity_change.data().specifics.typed_url();
225
226 GURL url(specifics.url());
227
228 if (ShouldIgnoreUrl(url))
229 continue;
230
231 DCHECK(specifics.visits_size());
232 sync_pb::TypedUrlSpecifics filtered_url = FilterExpiredVisits(specifics);
233 if (filtered_url.visits_size() == 0)
234 continue;
235
236 UpdateFromSync(filtered_url, &new_synced_visits, &deleted_visits,
237 &updated_synced_urls, &new_synced_urls);
238 }
239
240 WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls,
241 &pending_deleted_urls, &new_synced_visits,
242 &deleted_visits);
188 return {}; 243 return {};
189 } 244 }
190 245
191 void TypedURLSyncBridge::GetData(StorageKeyList storage_keys, 246 void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
192 DataCallback callback) { 247 DataCallback callback) {
193 DCHECK(sequence_checker_.CalledOnValidSequence()); 248 DCHECK(sequence_checker_.CalledOnValidSequence());
194 NOTIMPLEMENTED(); 249 DCHECK(sync_metadata_database_);
250
251 auto batch = base::MakeUnique<MutableDataBatch>();
252 for (const std::string& key : storage_keys) {
253 URLRow url_row;
254 URLID url_id = sync_metadata_database_->StorageKeyToURLID(key);
255
256 ++num_db_accesses_;
257 if (!history_backend_->GetURLByID(url_id, &url_row)) {
258 // Ignoring the case which no matching URLRow with URLID |url_id|.
pavely 2017/07/06 19:28:29 which => with?
Gang Wu 2017/07/10 19:53:24 Done.
259 continue;
pavely 2017/07/06 19:28:29 Now that sync metadata lives in history db not fin
Gang Wu 2017/07/10 19:53:24 Done.
260 }
261 if (url_row.url().is_empty()) {
262 // Ignoring empty URL in sync DB;
pavely 2017/07/06 19:28:29 Why do we expect and ignore rows with empty urls f
Gang Wu 2017/07/10 19:53:24 Done.
263 continue;
264 }
265
266 VisitVector visits_vector;
267 FixupURLAndGetVisits(&url_row, &visits_vector);
268 batch->Put(key, CreateEntityData(url_row, visits_vector));
269 }
270
271 callback.Run(std::move(batch));
195 } 272 }
196 273
197 void TypedURLSyncBridge::GetAllData(DataCallback callback) { 274 void TypedURLSyncBridge::GetAllData(DataCallback callback) {
198 DCHECK(sequence_checker_.CalledOnValidSequence()); 275 DCHECK(sequence_checker_.CalledOnValidSequence());
199 276
200 history::URLRows typed_urls; 277 history::URLRows typed_urls;
201 ++num_db_accesses_; 278 ++num_db_accesses_;
202 if (!history_backend_->GetAllTypedURLs(&typed_urls)) { 279 if (!history_backend_->GetAllTypedURLs(&typed_urls)) {
203 ++num_db_errors_; 280 ++num_db_errors_;
204 change_processor()->ReportError(FROM_HERE, 281 change_processor()->ReportError(FROM_HERE,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 bool TypedURLSyncBridge::SupportsGetStorageKey() const { 315 bool TypedURLSyncBridge::SupportsGetStorageKey() const {
239 return false; 316 return false;
240 } 317 }
241 318
242 void TypedURLSyncBridge::OnURLVisited(history::HistoryBackend* history_backend, 319 void TypedURLSyncBridge::OnURLVisited(history::HistoryBackend* history_backend,
243 ui::PageTransition transition, 320 ui::PageTransition transition,
244 const history::URLRow& row, 321 const history::URLRow& row,
245 const history::RedirectList& redirects, 322 const history::RedirectList& redirects,
246 base::Time visit_time) { 323 base::Time visit_time) {
247 DCHECK(sequence_checker_.CalledOnValidSequence()); 324 DCHECK(sequence_checker_.CalledOnValidSequence());
248 NOTIMPLEMENTED(); 325
326 if (!change_processor())
327 return; // Sync processor not yet initialized, don't sync.
pavely 2017/07/06 19:28:29 change_processor() always returns valid pointer. Y
Gang Wu 2017/07/10 19:53:25 Done.
328 if (!ShouldSyncVisit(row.typed_count(), transition))
329 return;
330
331 std::unique_ptr<MetadataChangeList> metadata_change_list =
332 CreateMetadataChangeList();
333
334 UpdateSyncFromLocal(row, metadata_change_list.get());
249 } 335 }
250 336
251 void TypedURLSyncBridge::OnURLsModified( 337 void TypedURLSyncBridge::OnURLsModified(
252 history::HistoryBackend* history_backend, 338 history::HistoryBackend* history_backend,
253 const history::URLRows& changed_urls) { 339 const history::URLRows& changed_urls) {
254 DCHECK(sequence_checker_.CalledOnValidSequence()); 340 DCHECK(sequence_checker_.CalledOnValidSequence());
255 NOTIMPLEMENTED(); 341
342 if (!change_processor())
343 return; // Sync processor not yet initialized, don't sync.
344
345 std::unique_ptr<MetadataChangeList> metadata_change_list =
346 CreateMetadataChangeList();
347
348 for (const auto& row : changed_urls) {
349 // Only care if the modified URL is typed.
350 if (row.typed_count() >= 0) {
351 // If there were any errors updating the sync node, just ignore them and
352 // continue on to process the next URL.
353 UpdateSyncFromLocal(row, metadata_change_list.get());
354 }
355 }
256 } 356 }
257 357
258 void TypedURLSyncBridge::OnURLsDeleted(history::HistoryBackend* history_backend, 358 void TypedURLSyncBridge::OnURLsDeleted(history::HistoryBackend* history_backend,
259 bool all_history, 359 bool all_history,
260 bool expired, 360 bool expired,
261 const history::URLRows& deleted_rows, 361 const history::URLRows& deleted_rows,
262 const std::set<GURL>& favicon_urls) { 362 const std::set<GURL>& favicon_urls) {
263 DCHECK(sequence_checker_.CalledOnValidSequence()); 363 DCHECK(sequence_checker_.CalledOnValidSequence());
264 NOTIMPLEMENTED(); 364 if (!change_processor())
365 return; // Sync processor not yet initialized, don't sync.
366
367 // Ignore URLs expired due to old age (we don't want to sync them as deletions
368 // to avoid extra traffic up to the server, and also to make sure that a
369 // client with a bad clock setting won't go on an expiration rampage and
370 // delete all history from every client). The server will gracefully age out
371 // the sync DB entries when they've been idle for long enough.
372 if (expired)
373 return;
374
375 std::unique_ptr<MetadataChangeList> metadata_change_list =
376 CreateMetadataChangeList();
377
378 if (all_history) {
379 auto batch = base::MakeUnique<syncer::MetadataBatch>();
380 if (!sync_metadata_database_->GetAllSyncMetadata(batch.get())) {
381 change_processor()->ReportError(FROM_HERE,
382 "Failed reading typed url metadata from "
383 "TypedURLSyncMetadataDatabase.");
384 return;
385 }
386
387 syncer::EntityMetadataMap metadata_map(batch->TakeAllMetadata());
388 for (const auto& kv : metadata_map) {
389 change_processor()->Delete(kv.first, metadata_change_list.get());
390 }
391 } else {
392 // Delete rows.
393 for (const auto& row : deleted_rows) {
394 std::string storage_key = GetStorageKeyFromURLRow(row);
395 change_processor()->Delete(storage_key, metadata_change_list.get());
396 }
397 }
265 } 398 }
266 399
267 void TypedURLSyncBridge::Init() { 400 void TypedURLSyncBridge::Init() {
268 DCHECK(sequence_checker_.CalledOnValidSequence()); 401 DCHECK(sequence_checker_.CalledOnValidSequence());
269 402
270 history_backend_observer_.Add(history_backend_); 403 history_backend_observer_.Add(history_backend_);
271 LoadMetadata(); 404 LoadMetadata();
272 } 405 }
273 406
274 int TypedURLSyncBridge::GetErrorPercentage() const { 407 int TypedURLSyncBridge::GetErrorPercentage() const {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 ++visit_ix; 611 ++visit_ix;
479 } 612 }
480 } 613 }
481 DCHECK(CheckVisitOrdering(*visits)); 614 DCHECK(CheckVisitOrdering(*visits));
482 615
483 new_url->set_last_visit(visits->back().visit_time); 616 new_url->set_last_visit(visits->back().visit_time);
484 return different; 617 return different;
485 } 618 }
486 619
487 // static 620 // static
621 void TypedURLSyncBridge::DiffVisits(
622 const history::VisitVector& history_visits,
623 const sync_pb::TypedUrlSpecifics& sync_specifics,
624 std::vector<history::VisitInfo>* new_visits,
625 history::VisitVector* removed_visits) {
626 DCHECK(new_visits);
627 size_t old_visit_count = history_visits.size();
628 size_t new_visit_count = sync_specifics.visits_size();
629 size_t old_index = 0;
630 size_t new_index = 0;
631 while (old_index < old_visit_count && new_index < new_visit_count) {
632 base::Time new_visit_time =
633 base::Time::FromInternalValue(sync_specifics.visits(new_index));
634 if (history_visits[old_index].visit_time < new_visit_time) {
635 if (new_index > 0 && removed_visits) {
636 // If there are visits missing from the start of the node, that
637 // means that they were probably clipped off due to our code that
638 // limits the size of the sync nodes - don't delete them from our
639 // local history.
640 removed_visits->push_back(history_visits[old_index]);
641 }
642 ++old_index;
643 } else if (history_visits[old_index].visit_time > new_visit_time) {
644 new_visits->push_back(history::VisitInfo(
645 new_visit_time, ui::PageTransitionFromInt(
646 sync_specifics.visit_transitions(new_index))));
647 ++new_index;
648 } else {
649 ++old_index;
650 ++new_index;
651 }
652 }
653
654 if (removed_visits) {
655 for (; old_index < old_visit_count; ++old_index) {
656 removed_visits->push_back(history_visits[old_index]);
657 }
658 }
659
660 for (; new_index < new_visit_count; ++new_index) {
661 new_visits->push_back(history::VisitInfo(
662 base::Time::FromInternalValue(sync_specifics.visits(new_index)),
663 ui::PageTransitionFromInt(
664 sync_specifics.visit_transitions(new_index))));
665 }
666 }
667
668 // static
488 void TypedURLSyncBridge::UpdateURLRowFromTypedUrlSpecifics( 669 void TypedURLSyncBridge::UpdateURLRowFromTypedUrlSpecifics(
489 const TypedUrlSpecifics& typed_url, 670 const TypedUrlSpecifics& typed_url,
490 history::URLRow* new_url) { 671 history::URLRow* new_url) {
491 DCHECK_GT(typed_url.visits_size(), 0); 672 DCHECK_GT(typed_url.visits_size(), 0);
492 CHECK_EQ(typed_url.visit_transitions_size(), typed_url.visits_size()); 673 CHECK_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
493 if (!new_url->url().is_valid()) { 674 if (!new_url->url().is_valid()) {
494 new_url->set_url(GURL(typed_url.url())); 675 new_url->set_url(GURL(typed_url.url()));
495 } 676 }
496 new_url->set_title(base::UTF8ToUTF16(typed_url.title())); 677 new_url->set_title(base::UTF8ToUTF16(typed_url.title()));
497 new_url->set_hidden(typed_url.hidden()); 678 new_url->set_hidden(typed_url.hidden());
(...skipping 20 matching lines...) Expand all
518 return; 699 return;
519 } 700 }
520 change_processor()->ModelReadyToSync(std::move(batch)); 701 change_processor()->ModelReadyToSync(std::move(batch));
521 } 702 }
522 703
523 void TypedURLSyncBridge::ClearErrorStats() { 704 void TypedURLSyncBridge::ClearErrorStats() {
524 num_db_accesses_ = 0; 705 num_db_accesses_ = 0;
525 num_db_errors_ = 0; 706 num_db_errors_ = 0;
526 } 707 }
527 708
528 void TypedURLSyncBridge::UpdateUrlFromServer( 709 void TypedURLSyncBridge::MergeURLWithSync(
529 const sync_pb::TypedUrlSpecifics& server_typed_url, 710 const sync_pb::TypedUrlSpecifics& server_typed_url,
530 TypedURLMap* local_typed_urls, 711 TypedURLMap* local_typed_urls,
531 URLVisitVectorMap* local_visit_vectors, 712 URLVisitVectorMap* local_visit_vectors,
532 history::URLRows* new_synced_urls, 713 history::URLRows* new_synced_urls,
533 TypedURLVisitVector* new_synced_visits, 714 TypedURLVisitVector* new_synced_visits,
534 history::URLRows* updated_synced_urls) { 715 history::URLRows* updated_synced_urls) {
535 DCHECK(server_typed_url.visits_size() != 0); 716 DCHECK(server_typed_url.visits_size() != 0);
536 DCHECK_EQ(server_typed_url.visits_size(), 717 DCHECK_EQ(server_typed_url.visits_size(),
537 server_typed_url.visit_transitions_size()); 718 server_typed_url.visit_transitions_size());
538 719
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 new_synced_visits->push_back( 835 new_synced_visits->push_back(
655 std::pair<GURL, std::vector<history::VisitInfo>>(it->first, 836 std::pair<GURL, std::vector<history::VisitInfo>>(it->first,
656 added_visits)); 837 added_visits));
657 } 838 }
658 } else { 839 } else {
659 // No difference in urls, erase from map 840 // No difference in urls, erase from map
660 local_typed_urls->erase(it); 841 local_typed_urls->erase(it);
661 } 842 }
662 } 843 }
663 844
845 void TypedURLSyncBridge::UpdateFromSync(
846 const sync_pb::TypedUrlSpecifics& typed_url,
847 TypedURLVisitVector* visits_to_add,
848 history::VisitVector* visits_to_remove,
849 history::URLRows* updated_urls,
850 history::URLRows* new_urls) {
851 history::URLRow new_url(GURL(typed_url.url()));
852 history::VisitVector existing_visits;
853 bool existing_url = history_backend_->GetURL(new_url.url(), &new_url);
854 if (existing_url) {
855 // This URL already exists locally - fetch the visits so we can
856 // merge them below.
857 if (!FixupURLAndGetVisits(&new_url, &existing_visits)) {
858 return;
859 }
860 }
861 visits_to_add->push_back(std::pair<GURL, std::vector<history::VisitInfo>>(
862 new_url.url(), std::vector<history::VisitInfo>()));
863
864 // Update the URL with information from the typed URL.
865 UpdateURLRowFromTypedUrlSpecifics(typed_url, &new_url);
866
867 // Figure out which visits we need to add.
868 DiffVisits(existing_visits, typed_url, &visits_to_add->back().second,
869 visits_to_remove);
870
871 if (existing_url) {
872 updated_urls->push_back(new_url);
873 } else {
874 new_urls->push_back(new_url);
875 }
876 }
877
878 bool TypedURLSyncBridge::UpdateSyncFromLocal(
879 URLRow row,
880 MetadataChangeList* metadata_change_list) {
881 DCHECK_GE(row.typed_count(), 0);
882
883 if (ShouldIgnoreUrl(row.url()))
884 return false;
885
886 // Get the visits for this node.
887 VisitVector visit_vector;
888 if (!FixupURLAndGetVisits(&row, &visit_vector)) {
889 return false;
890 }
891
892 DCHECK(!visit_vector.empty());
893
894 std::unique_ptr<syncer::EntityData> entity_data =
895 CreateEntityData(row, visit_vector);
896 if (!entity_data->specifics.has_typed_url()) {
897 // Cannot create EntityData, ex. no TYPED visits.
898 return false;
899 }
900
901 std::string storage_key = GetStorageKeyFromURLRow(row);
902 change_processor()->Put(storage_key, std::move(entity_data),
903 metadata_change_list);
904
905 return true;
906 }
907
664 base::Optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend( 908 base::Optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend(
665 const history::URLRows* new_urls, 909 const history::URLRows* new_urls,
666 const history::URLRows* updated_urls, 910 const history::URLRows* updated_urls,
667 const std::vector<GURL>* deleted_urls, 911 const std::vector<GURL>* deleted_urls,
668 const TypedURLVisitVector* new_visits, 912 const TypedURLVisitVector* new_visits,
669 const history::VisitVector* deleted_visits) { 913 const history::VisitVector* deleted_visits) {
670 if (deleted_urls && !deleted_urls->empty()) 914 if (deleted_urls && !deleted_urls->empty())
671 history_backend_->DeleteURLs(*deleted_urls); 915 history_backend_->DeleteURLs(*deleted_urls);
672 916
673 if (new_urls) { 917 if (new_urls) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 return true; 985 return true;
742 986
743 // Ignore local file URLs. 987 // Ignore local file URLs.
744 if (url.SchemeIsFile()) 988 if (url.SchemeIsFile())
745 return true; 989 return true;
746 990
747 // Ignore localhost URLs. 991 // Ignore localhost URLs.
748 if (net::IsLocalhost(url.host_piece())) 992 if (net::IsLocalhost(url.host_piece()))
749 return true; 993 return true;
750 994
751 // Ignore username and password, sonce history backend will remove user name 995 // Ignore username and password, sonce history backend will remove user name
pavely 2017/07/06 19:28:29 sonce => since
Gang Wu 2017/07/10 19:53:24 Done.
752 // and password in URLDatabase::GURLToDatabaseURL and send username/password 996 // and password in URLDatabase::GURLToDatabaseURL and send username/password
753 // removed url to sync later. 997 // removed url to sync later.
754 if (url.has_username() || url.has_password()) 998 if (url.has_username() || url.has_password())
755 return true; 999 return true;
756 1000
757 return false; 1001 return false;
758 } 1002 }
759 1003
760 bool TypedURLSyncBridge::ShouldIgnoreVisits( 1004 bool TypedURLSyncBridge::ShouldIgnoreVisits(
761 const history::VisitVector& visits) { 1005 const history::VisitVector& visits) {
762 // We ignore URLs that were imported, but have never been visited by 1006 // We ignore URLs that were imported, but have never been visited by
763 // chromium. 1007 // chromium.
764 static const int kFirstImportedSource = history::SOURCE_FIREFOX_IMPORTED; 1008 static const int kFirstImportedSource = history::SOURCE_FIREFOX_IMPORTED;
765 history::VisitSourceMap map; 1009 history::VisitSourceMap map;
766 if (!history_backend_->GetVisitsSource(visits, &map)) 1010 if (!history_backend_->GetVisitsSource(visits, &map))
767 return false; // If we can't read the visit, assume it's not imported. 1011 return false; // If we can't read the visit, assume it's not imported.
768 1012
769 // Walk the list of visits and look for a non-imported item. 1013 // Walk the list of visits and look for a non-imported item.
770 for (const auto& visit : visits) { 1014 for (const auto& visit : visits) {
771 if (map.count(visit.visit_id) == 0 || 1015 if (map.count(visit.visit_id) == 0 ||
772 map[visit.visit_id] < kFirstImportedSource) { 1016 map[visit.visit_id] < kFirstImportedSource) {
773 return false; 1017 return false;
774 } 1018 }
775 } 1019 }
776 // We only saw imported visits, so tell the caller to ignore them. 1020 // We only saw imported visits, so tell the caller to ignore them.
777 return true; 1021 return true;
778 } 1022 }
779 1023
1024 bool TypedURLSyncBridge::ShouldSyncVisit(int typed_count,
1025 ui::PageTransition transition) {
1026 // Just use an ad-hoc criteria to determine whether to ignore this
1027 // notification. For most users, the distribution of visits is roughly a bell
1028 // curve with a long tail - there are lots of URLs with < 5 visits so we want
1029 // to make sure we sync up every visit to ensure the proper ordering of
1030 // suggestions. But there are relatively few URLs with > 10 visits, and those
1031 // tend to be more broadly distributed such that there's no need to sync up
1032 // every visit to preserve their relative ordering.
1033 return (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
1034 typed_count >= 0 &&
1035 (typed_count < kTypedUrlVisitThrottleThreshold ||
1036 (typed_count % kTypedUrlVisitThrottleMultiple) == 0));
1037 }
1038
780 bool TypedURLSyncBridge::FixupURLAndGetVisits(URLRow* url, 1039 bool TypedURLSyncBridge::FixupURLAndGetVisits(URLRow* url,
781 VisitVector* visits) { 1040 VisitVector* visits) {
782 ++num_db_accesses_; 1041 ++num_db_accesses_;
783 if (!history_backend_->GetMostRecentVisitsForURL(url->id(), kMaxVisitsToFetch, 1042 if (!history_backend_->GetMostRecentVisitsForURL(url->id(), kMaxVisitsToFetch,
784 visits)) { 1043 visits)) {
785 ++num_db_errors_; 1044 ++num_db_errors_;
786 // Couldn't load the visits for this URL due to some kind of DB error. 1045 // Couldn't load the visits for this URL due to some kind of DB error.
787 // Don't bother writing this URL to the history DB (if we ignore the 1046 // Don't bother writing this URL to the history DB (if we ignore the
788 // error and continue, we might end up duplicating existing visits). 1047 // error and continue, we might end up duplicating existing visits).
789 DLOG(ERROR) << "Could not load visits for url: " << url->url(); 1048 DLOG(ERROR) << "Could not load visits for url: " << url->url();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 1104 }
846 1105
847 std::unique_ptr<EntityData> TypedURLSyncBridge::CreateEntityData( 1106 std::unique_ptr<EntityData> TypedURLSyncBridge::CreateEntityData(
848 const URLRow& row, 1107 const URLRow& row,
849 const VisitVector& visits) { 1108 const VisitVector& visits) {
850 auto entity_data = base::MakeUnique<EntityData>(); 1109 auto entity_data = base::MakeUnique<EntityData>();
851 TypedUrlSpecifics* specifics = entity_data->specifics.mutable_typed_url(); 1110 TypedUrlSpecifics* specifics = entity_data->specifics.mutable_typed_url();
852 1111
853 if (!WriteToTypedUrlSpecifics(row, visits, specifics)) { 1112 if (!WriteToTypedUrlSpecifics(row, visits, specifics)) {
854 // Cannot write to specifics, ex. no TYPED visits. 1113 // Cannot write to specifics, ex. no TYPED visits.
855 return base::MakeUnique<EntityData>(); 1114 return base::MakeUnique<EntityData>();
pavely 2017/07/06 19:28:29 CreateEntityData came from TypedUrlSyncableService
Gang Wu 2017/07/10 19:53:24 Done.
856 } 1115 }
857 entity_data->non_unique_name = row.url().spec(); 1116 entity_data->non_unique_name = row.url().spec();
858
859 return entity_data; 1117 return entity_data;
860 } 1118 }
861 1119
862 bool TypedURLSyncBridge::GetValidURLsAndVisits(URLVisitVectorMap* url_to_visit, 1120 bool TypedURLSyncBridge::GetValidURLsAndVisits(URLVisitVectorMap* url_to_visit,
863 TypedURLMap* url_to_urlrow) { 1121 TypedURLMap* url_to_urlrow) {
864 DCHECK(url_to_visit); 1122 DCHECK(url_to_visit);
865 DCHECK(url_to_urlrow); 1123 DCHECK(url_to_urlrow);
866 1124
867 history::URLRows local_typed_urls; 1125 history::URLRows local_typed_urls;
868 ++num_db_accesses_; 1126 ++num_db_accesses_;
(...skipping 26 matching lines...) Expand all
895 if (!is_existing_url) { 1153 if (!is_existing_url) {
896 // The typed url did not save to local history database, so return empty 1154 // The typed url did not save to local history database, so return empty
897 // string. 1155 // string.
898 return std::string(); 1156 return std::string();
899 } 1157 }
900 1158
901 return GetStorageKeyFromURLRow(existing_url); 1159 return GetStorageKeyFromURLRow(existing_url);
902 } 1160 }
903 1161
904 } // namespace history 1162 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698