summaryrefslogtreecommitdiffstats
path: root/chrome/browser/history/page_collector.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/history/page_collector.cc')
-rw-r--r--chrome/browser/history/page_collector.cc157
1 files changed, 157 insertions, 0 deletions
diff --git a/chrome/browser/history/page_collector.cc b/chrome/browser/history/page_collector.cc
new file mode 100644
index 0000000..da07ad1
--- /dev/null
+++ b/chrome/browser/history/page_collector.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/history/page_collector.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/history/history_publisher.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Page info older than this will be published even if we haven't
+// gotten a title and/or body.
+const int kExpirationSeconds = 20;
+
+} // namespace
+
+namespace history {
+
+// PageCollector::PageInfo -----------------------------------------------
+
+PageCollector::PageInfo::PageInfo(base::Time visit_time)
+ : visit_time_(visit_time),
+ added_time_(base::TimeTicks::Now()) {
+}
+
+PageCollector::PageInfo::~PageInfo() {}
+
+// NOTE(shess): Per the comment on has_title() and has_body(), this
+// code maps empty strings to single space to differentiate set title
+// and body from empty. This approach is held over from the original
+// TextDatabaseManager version.
+void PageCollector::PageInfo::set_title(const string16& ttl) {
+ if (ttl.empty())
+ title_ = ASCIIToUTF16(" ");
+ else
+ title_ = ttl;
+}
+
+void PageCollector::PageInfo::set_body(const string16& bdy) {
+ if (bdy.empty())
+ body_ = ASCIIToUTF16(" ");
+ else
+ body_ = bdy;
+}
+
+bool PageCollector::PageInfo::Expired(base::TimeTicks now) const {
+ return now - added_time_ > base::TimeDelta::FromSeconds(kExpirationSeconds);
+}
+
+PageCollector::PageCollector()
+ : recent_changes_(RecentChangeList::NO_AUTO_EVICT),
+ weak_factory_(this) {
+}
+
+PageCollector::~PageCollector() {
+}
+
+void PageCollector::Init(const HistoryPublisher* history_publisher) {
+ history_publisher_ = history_publisher;
+}
+
+void PageCollector::AddPageURL(const GURL& url, base::Time time) {
+ // Don't collect data which cannot be published.
+ if (!history_publisher_)
+ return;
+
+ // Just save this info for later (evicting any previous data). We
+ // will delete it when it expires or when all the data is complete.
+ recent_changes_.Put(url, PageInfo(time));
+
+ // Schedule flush if not already scheduled.
+ if (!weak_factory_.HasWeakPtrs())
+ ScheduleFlushCollected();
+}
+
+void PageCollector::AddPageTitle(const GURL& url, const string16& title) {
+ if (!history_publisher_)
+ return;
+
+ // If the title comes in after the page has aged out, drop it.
+ // Older code would manufacture information from the database.
+ RecentChangeList::iterator found = recent_changes_.Peek(url);
+ if (found == recent_changes_.end())
+ return;
+
+ // Publish the info if complete.
+ if (found->second.has_body()) {
+ history_publisher_->PublishPageContent(
+ found->second.visit_time(), url, title, found->second.body());
+ recent_changes_.Erase(found);
+ } else {
+ found->second.set_title(title);
+ }
+}
+
+void PageCollector::AddPageContents(const GURL& url,
+ const string16& body) {
+ if (!history_publisher_)
+ return;
+
+ // If the body comes in after the page has aged out, drop it.
+ // Older code would manufacture information from the database.
+ RecentChangeList::iterator found = recent_changes_.Peek(url);
+ if (found == recent_changes_.end())
+ return;
+
+ // Publish the info if complete.
+ if (found->second.has_title()) {
+ history_publisher_->PublishPageContent(
+ found->second.visit_time(), url, found->second.title(), body);
+ recent_changes_.Erase(found);
+ } else {
+ found->second.set_body(body);
+ }
+}
+
+void PageCollector::AddPageData(const GURL& url,
+ base::Time visit_time,
+ const string16& title,
+ const string16& body) {
+ if (!history_publisher_)
+ return;
+
+ // Publish the item.
+ history_publisher_->PublishPageContent(visit_time, url, title, body);
+}
+
+void PageCollector::ScheduleFlushCollected() {
+ weak_factory_.InvalidateWeakPtrs();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&PageCollector::FlushCollected,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kExpirationSeconds));
+}
+
+void PageCollector::FlushCollected() {
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ // Iterate from oldest to newest publishing items which expire while
+ // waiting for title or body.
+ RecentChangeList::reverse_iterator iter = recent_changes_.rbegin();
+ while (iter != recent_changes_.rend() && iter->second.Expired(now)) {
+ AddPageData(iter->first, iter->second.visit_time(),
+ iter->second.title(), iter->second.body());
+ iter = recent_changes_.Erase(iter);
+ }
+
+ if (!recent_changes_.empty())
+ ScheduleFlushCollected();
+}
+
+} // namespace history