diff options
Diffstat (limited to 'chrome/browser/history/page_collector.cc')
-rw-r--r-- | chrome/browser/history/page_collector.cc | 157 |
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 |