Index: chrome/browser/sync/glue/typed_url_model_associator.cc |
diff --git a/chrome/browser/sync/glue/typed_url_model_associator.cc b/chrome/browser/sync/glue/typed_url_model_associator.cc |
index 961f2b9ae895b223ffc09cbff5d9815789a27377..08e47d43d27a5e7acdf438a4cd5f6dbabfae7a54 100644 |
--- a/chrome/browser/sync/glue/typed_url_model_associator.cc |
+++ b/chrome/browser/sync/glue/typed_url_model_associator.cc |
@@ -18,6 +18,10 @@ |
namespace browser_sync { |
+// The server backend can't handle arbitrarily large node sizes, so to keep |
+// the size under control we limit the visit array. |
+static const int kMaxTypedUrlVisits = 100; |
+ |
const char kTypedUrlTag[] = "google_chrome_typed_urls"; |
static bool CheckVisitOrdering(const history::VisitVector& visits) { |
@@ -537,23 +541,80 @@ void TypedUrlModelAssociator::WriteToSyncNode( |
const history::URLRow& url, |
const history::VisitVector& visits, |
sync_api::WriteNode* node) { |
+ sync_pb::TypedUrlSpecifics typed_url; |
+ WriteToTypedUrlSpecifics(url, visits, &typed_url); |
+ node->SetTypedUrlSpecifics(typed_url); |
+} |
+ |
+void TypedUrlModelAssociator::WriteToTypedUrlSpecifics( |
+ const history::URLRow& url, |
+ const history::VisitVector& visits, |
+ sync_pb::TypedUrlSpecifics* typed_url) { |
+ |
DCHECK(!url.last_visit().is_null()); |
DCHECK(!visits.empty()); |
DCHECK(url.last_visit() == visits.back().visit_time); |
- sync_pb::TypedUrlSpecifics typed_url; |
- typed_url.set_url(url.url().spec()); |
- typed_url.set_title(UTF16ToUTF8(url.title())); |
- typed_url.set_hidden(url.hidden()); |
+ typed_url->set_url(url.url().spec()); |
+ typed_url->set_title(UTF16ToUTF8(url.title())); |
+ typed_url->set_hidden(url.hidden()); |
DCHECK(CheckVisitOrdering(visits)); |
+ |
+ bool only_typed = false; |
+ int skip_count = 0; |
+ |
+ if (visits.size() > static_cast<size_t>(kMaxTypedUrlVisits)) { |
+ int typed_count = 0; |
+ int total = 0; |
+ // Walk the passed-in visit vector and count the # of typed visits. |
+ for (history::VisitVector::const_iterator visit = visits.begin(); |
+ visit != visits.end(); ++visit) { |
+ PageTransition::Type transition = static_cast<PageTransition::Type>( |
+ visit->transition) & PageTransition::CORE_MASK; |
+ // We ignore reload visits. |
+ if (transition == PageTransition::RELOAD) |
+ continue; |
+ ++total; |
+ if (transition == PageTransition::TYPED) |
+ ++typed_count; |
+ } |
+ |
+ if (typed_count > kMaxTypedUrlVisits) { |
+ only_typed = true; |
+ skip_count = typed_count - kMaxTypedUrlVisits; |
+ } else if (total > kMaxTypedUrlVisits) { |
+ skip_count = total - kMaxTypedUrlVisits; |
+ } |
+ } |
+ |
+ |
for (history::VisitVector::const_iterator visit = visits.begin(); |
visit != visits.end(); ++visit) { |
- typed_url.add_visits(visit->visit_time.ToInternalValue()); |
- typed_url.add_visit_transitions(visit->transition); |
+ PageTransition::Type transition = static_cast<PageTransition::Type>( |
+ visit->transition) & PageTransition::CORE_MASK; |
+ // Skip reload visits. |
+ if (transition == PageTransition::RELOAD) |
+ continue; |
+ |
+ // If we only have room for typed visits, then only add typed visits. |
+ if (only_typed && transition != PageTransition::TYPED) |
+ continue; |
+ |
+ if (skip_count > 0) { |
+ // We have too many entries to fit, so we need to skip the oldest ones. |
+ // Only skip typed URLs if there are too many typed URLs to fit. |
+ if (only_typed || transition != PageTransition::TYPED) { |
+ --skip_count; |
+ continue; |
+ } |
+ } |
+ typed_url->add_visits(visit->visit_time.ToInternalValue()); |
+ typed_url->add_visit_transitions(visit->transition); |
} |
- |
- node->SetTypedUrlSpecifics(typed_url); |
+ DCHECK_EQ(skip_count, 0); |
+ CHECK_GT(typed_url->visits_size(), 0); |
+ CHECK_LE(typed_url->visits_size(), kMaxTypedUrlVisits); |
} |
// static |