Home | History | Annotate | Download | only in ntp
      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 DictionaryValue* SuggestionsSourceTopSites::PopItem() {
     52   if (items_.empty())
     53     return NULL;
     54 
     55   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     DictionaryValue* page_value = new 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