1 // Copyright (c) 2012 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/ui/webui/ntp/suggestions_source_top_sites.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/command_line.h" 10 #include "base/stl_util.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/history/history_service_factory.h" 14 #include "chrome/browser/history/top_sites.h" 15 #include "chrome/browser/history/visit_filter.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 18 #include "chrome/browser/ui/webui/ntp/suggestions_combiner.h" 19 #include "chrome/common/chrome_switches.h" 20 21 22 namespace { 23 24 // The weight used by the combiner to determine which ratio of suggestions 25 // should be obtained from this source. 26 const int kSuggestionsTopListWeight = 1; 27 28 } // namespace 29 30 SuggestionsSourceTopSites::SuggestionsSourceTopSites() 31 : combiner_(NULL), 32 debug_(false) { 33 } 34 35 SuggestionsSourceTopSites::~SuggestionsSourceTopSites() { 36 STLDeleteElements(&items_); 37 } 38 39 void SuggestionsSourceTopSites::SetDebug(bool enable) { 40 debug_ = enable; 41 } 42 43 inline int SuggestionsSourceTopSites::GetWeight() { 44 return kSuggestionsTopListWeight; 45 } 46 47 int SuggestionsSourceTopSites::GetItemCount() { 48 return items_.size(); 49 } 50 51 base::DictionaryValue* SuggestionsSourceTopSites::PopItem() { 52 if (items_.empty()) 53 return NULL; 54 55 base::DictionaryValue* item = items_.front(); 56 items_.pop_front(); 57 return item; 58 } 59 60 void SuggestionsSourceTopSites::FetchItems(Profile* profile) { 61 DCHECK(combiner_); 62 STLDeleteElements(&items_); 63 64 history_consumer_.CancelAllRequests(); 65 HistoryService* history = HistoryServiceFactory::GetForProfile( 66 profile, Profile::EXPLICIT_ACCESS); 67 // |history| may be null during unit tests. 68 if (history) { 69 history::VisitFilter time_filter; 70 time_filter.SetFilterTime(base::Time::Now()); 71 time_filter.SetFilterWidth(GetFilterWidth()); 72 time_filter.set_sorting_order(GetSortingOrder()); 73 74 history->QueryFilteredURLs(0, time_filter, debug_, &history_consumer_, 75 base::Bind(&SuggestionsSourceTopSites::OnSuggestionsUrlsAvailable, 76 base::Unretained(this))); 77 } 78 } 79 80 void SuggestionsSourceTopSites::SetCombiner(SuggestionsCombiner* combiner) { 81 DCHECK(!combiner_); 82 combiner_ = combiner; 83 } 84 85 void SuggestionsSourceTopSites::OnSuggestionsUrlsAvailable( 86 CancelableRequestProvider::Handle handle, 87 const history::FilteredURLList& data) { 88 DCHECK(combiner_); 89 for (size_t i = 0; i < data.size(); i++) { 90 const history::FilteredURL& suggested_url = data[i]; 91 if (suggested_url.url.is_empty()) 92 continue; 93 94 base::DictionaryValue* page_value = new base::DictionaryValue(); 95 NewTabUI::SetUrlTitleAndDirection(page_value, 96 suggested_url.title, 97 suggested_url.url); 98 page_value->SetDouble("score", suggested_url.score); 99 if (debug_) { 100 if (suggested_url.extended_info.total_visits) { 101 page_value->SetInteger("extended_info.total visits", 102 suggested_url.extended_info.total_visits); 103 } 104 if (suggested_url.extended_info.visits) { 105 page_value->SetInteger("extended_info.visits", 106 suggested_url.extended_info.visits); 107 } 108 if (suggested_url.extended_info.duration_opened) { 109 page_value->SetInteger("extended_info.duration opened", 110 suggested_url.extended_info.duration_opened); 111 } 112 if (!suggested_url.extended_info.last_visit_time.is_null()) { 113 base::TimeDelta deltaTime = 114 base::Time::Now() - suggested_url.extended_info.last_visit_time; 115 page_value->SetInteger("extended_info.seconds since last visit", 116 deltaTime.InSeconds()); 117 } 118 } 119 items_.push_back(page_value); 120 } 121 122 combiner_->OnItemsReady(); 123 } 124 125 // static 126 base::TimeDelta SuggestionsSourceTopSites::GetFilterWidth() { 127 const CommandLine* cli = CommandLine::ForCurrentProcess(); 128 const std::string filter_width_switch = 129 cli->GetSwitchValueASCII(switches::kSuggestionNtpFilterWidth); 130 unsigned int filter_width; 131 if (base::StringToUint(filter_width_switch, &filter_width)) 132 return base::TimeDelta::FromMinutes(filter_width); 133 return base::TimeDelta::FromHours(1); 134 } 135 136 // static 137 history::VisitFilter::SortingOrder 138 SuggestionsSourceTopSites::GetSortingOrder() { 139 const CommandLine* cli = CommandLine::ForCurrentProcess(); 140 if (cli->HasSwitch(switches::kSuggestionNtpGaussianFilter)) 141 return history::VisitFilter::ORDER_BY_TIME_GAUSSIAN; 142 if (cli->HasSwitch(switches::kSuggestionNtpLinearFilter)) 143 return history::VisitFilter::ORDER_BY_TIME_LINEAR; 144 return history::VisitFilter::ORDER_BY_RECENCY; 145 } 146