| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/history/page_collector.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/message_loop/message_loop.h" | |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 10 #include "chrome/browser/history/history_publisher.h" | |
| 11 #include "url/gurl.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 // Page info older than this will be published even if we haven't | |
| 16 // gotten a title and/or body. | |
| 17 const int kExpirationSeconds = 20; | |
| 18 | |
| 19 } // namespace | |
| 20 | |
| 21 namespace history { | |
| 22 | |
| 23 // PageCollector::PageInfo ----------------------------------------------- | |
| 24 | |
| 25 PageCollector::PageInfo::PageInfo(base::Time visit_time) | |
| 26 : visit_time_(visit_time), | |
| 27 added_time_(base::TimeTicks::Now()) { | |
| 28 } | |
| 29 | |
| 30 PageCollector::PageInfo::~PageInfo() {} | |
| 31 | |
| 32 // NOTE(shess): Per the comment on has_title() and has_body(), this | |
| 33 // code maps empty strings to single space to differentiate set title | |
| 34 // and body from empty. This approach is held over from the original | |
| 35 // TextDatabaseManager version. | |
| 36 void PageCollector::PageInfo::set_title(const string16& ttl) { | |
| 37 if (ttl.empty()) | |
| 38 title_ = ASCIIToUTF16(" "); | |
| 39 else | |
| 40 title_ = ttl; | |
| 41 } | |
| 42 | |
| 43 void PageCollector::PageInfo::set_body(const string16& bdy) { | |
| 44 if (bdy.empty()) | |
| 45 body_ = ASCIIToUTF16(" "); | |
| 46 else | |
| 47 body_ = bdy; | |
| 48 } | |
| 49 | |
| 50 bool PageCollector::PageInfo::Expired(base::TimeTicks now) const { | |
| 51 return now - added_time_ > base::TimeDelta::FromSeconds(kExpirationSeconds); | |
| 52 } | |
| 53 | |
| 54 PageCollector::PageCollector() | |
| 55 : recent_changes_(RecentChangeList::NO_AUTO_EVICT), | |
| 56 weak_factory_(this) { | |
| 57 } | |
| 58 | |
| 59 PageCollector::~PageCollector() { | |
| 60 } | |
| 61 | |
| 62 void PageCollector::Init(const HistoryPublisher* history_publisher) { | |
| 63 history_publisher_ = history_publisher; | |
| 64 } | |
| 65 | |
| 66 void PageCollector::AddPageURL(const GURL& url, base::Time time) { | |
| 67 // Don't collect data which cannot be published. | |
| 68 if (!history_publisher_) | |
| 69 return; | |
| 70 | |
| 71 // Just save this info for later (evicting any previous data). We | |
| 72 // will delete it when it expires or when all the data is complete. | |
| 73 recent_changes_.Put(url, PageInfo(time)); | |
| 74 | |
| 75 // Schedule flush if not already scheduled. | |
| 76 if (!weak_factory_.HasWeakPtrs()) | |
| 77 ScheduleFlushCollected(); | |
| 78 } | |
| 79 | |
| 80 void PageCollector::AddPageTitle(const GURL& url, const string16& title) { | |
| 81 if (!history_publisher_) | |
| 82 return; | |
| 83 | |
| 84 // If the title comes in after the page has aged out, drop it. | |
| 85 // Older code would manufacture information from the database. | |
| 86 RecentChangeList::iterator found = recent_changes_.Peek(url); | |
| 87 if (found == recent_changes_.end()) | |
| 88 return; | |
| 89 | |
| 90 // Publish the info if complete. | |
| 91 if (found->second.has_body()) { | |
| 92 history_publisher_->PublishPageContent( | |
| 93 found->second.visit_time(), url, title, found->second.body()); | |
| 94 recent_changes_.Erase(found); | |
| 95 } else { | |
| 96 found->second.set_title(title); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 void PageCollector::AddPageContents(const GURL& url, | |
| 101 const string16& body) { | |
| 102 if (!history_publisher_) | |
| 103 return; | |
| 104 | |
| 105 // If the body comes in after the page has aged out, drop it. | |
| 106 // Older code would manufacture information from the database. | |
| 107 RecentChangeList::iterator found = recent_changes_.Peek(url); | |
| 108 if (found == recent_changes_.end()) | |
| 109 return; | |
| 110 | |
| 111 // Publish the info if complete. | |
| 112 if (found->second.has_title()) { | |
| 113 history_publisher_->PublishPageContent( | |
| 114 found->second.visit_time(), url, found->second.title(), body); | |
| 115 recent_changes_.Erase(found); | |
| 116 } else { | |
| 117 found->second.set_body(body); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 void PageCollector::AddPageData(const GURL& url, | |
| 122 base::Time visit_time, | |
| 123 const string16& title, | |
| 124 const string16& body) { | |
| 125 if (!history_publisher_) | |
| 126 return; | |
| 127 | |
| 128 // Publish the item. | |
| 129 history_publisher_->PublishPageContent(visit_time, url, title, body); | |
| 130 } | |
| 131 | |
| 132 void PageCollector::ScheduleFlushCollected() { | |
| 133 weak_factory_.InvalidateWeakPtrs(); | |
| 134 base::MessageLoop::current()->PostDelayedTask( | |
| 135 FROM_HERE, | |
| 136 base::Bind(&PageCollector::FlushCollected, | |
| 137 weak_factory_.GetWeakPtr()), | |
| 138 base::TimeDelta::FromSeconds(kExpirationSeconds)); | |
| 139 } | |
| 140 | |
| 141 void PageCollector::FlushCollected() { | |
| 142 base::TimeTicks now = base::TimeTicks::Now(); | |
| 143 | |
| 144 // Iterate from oldest to newest publishing items which expire while | |
| 145 // waiting for title or body. | |
| 146 RecentChangeList::reverse_iterator iter = recent_changes_.rbegin(); | |
| 147 while (iter != recent_changes_.rend() && iter->second.Expired(now)) { | |
| 148 AddPageData(iter->first, iter->second.visit_time(), | |
| 149 iter->second.title(), iter->second.body()); | |
| 150 iter = recent_changes_.Erase(iter); | |
| 151 } | |
| 152 | |
| 153 if (!recent_changes_.empty()) | |
| 154 ScheduleFlushCollected(); | |
| 155 } | |
| 156 | |
| 157 } // namespace history | |
| OLD | NEW |