Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / webui / ntp / suggestions_combiner.cc
blob07cc95b878956e94e2da4f0b88a0fb6451cfded1
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.
5 #include "chrome/browser/ui/webui/ntp/suggestions_combiner.h"
7 #include <algorithm>
9 #include "base/values.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_iterator.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/browser/ui/webui/ntp/suggestions_page_handler.h"
15 #include "chrome/browser/ui/webui/ntp/suggestions_source.h"
16 #include "content/public/browser/web_contents.h"
18 namespace {
20 static const size_t kSuggestionsCount = 8;
22 } // namespace
24 SuggestionsCombiner::SuggestionsCombiner(
25 SuggestionsCombiner::Delegate* delegate,
26 Profile* profile)
27 : sources_fetching_count_(0),
28 delegate_(delegate),
29 suggestions_count_(kSuggestionsCount),
30 page_values_(new base::ListValue()),
31 debug_enabled_(false),
32 profile_(profile) {
35 SuggestionsCombiner::~SuggestionsCombiner() {
38 void SuggestionsCombiner::AddSource(SuggestionsSource* source) {
39 source->SetCombiner(this);
40 source->SetDebug(debug_enabled_);
41 sources_.push_back(source);
44 void SuggestionsCombiner::EnableDebug(bool enable) {
45 debug_enabled_ = enable;
46 for (size_t i = 0; i < sources_.size(); ++i) {
47 sources_[i]->SetDebug(enable);
51 void SuggestionsCombiner::FetchItems(Profile* profile) {
52 sources_fetching_count_ = sources_.size();
53 for (size_t i = 0; i < sources_.size(); ++i) {
54 sources_[i]->FetchItems(profile);
58 base::ListValue* SuggestionsCombiner::GetPageValues() {
59 return page_values_.get();
62 void SuggestionsCombiner::OnItemsReady() {
63 DCHECK_GT(sources_fetching_count_, 0);
64 sources_fetching_count_--;
65 if (sources_fetching_count_ == 0) {
66 FillPageValues();
67 delegate_->OnSuggestionsReady();
71 void SuggestionsCombiner::SetSuggestionsCount(size_t suggestions_count) {
72 suggestions_count_ = suggestions_count;
75 void SuggestionsCombiner::FillPageValues() {
76 int total_weight = 0;
77 for (size_t i = 0; i < sources_.size(); ++i)
78 total_weight += sources_[i]->GetWeight();
79 DCHECK_GT(total_weight, 0);
81 page_values_.reset(new base::ListValue());
83 // Evaluate how many items to obtain from each source. We use error diffusion
84 // to ensure that we get the total desired number of items.
85 int error = 0;
87 // Holds the index at which the next item should be added for each source.
88 std::vector<size_t> next_item_index_for_source;
89 next_item_index_for_source.reserve(sources_.size());
90 for (size_t i = 0; i < sources_.size(); ++i) {
91 int numerator = sources_[i]->GetWeight() * suggestions_count_ + error;
92 error = numerator % total_weight;
93 int item_count = std::min(numerator / total_weight,
94 sources_[i]->GetItemCount());
96 for (int j = 0; j < item_count; ++j)
97 page_values_->Append(sources_[i]->PopItem());
98 next_item_index_for_source.push_back(page_values_->GetSize());
101 // Fill in extra items, prioritizing the first source.
102 base::DictionaryValue* item;
103 // Rather than updating |next_item_index_for_source| we keep track of the
104 // number of extra items that were added and offset indices by that much.
105 size_t extra_items_added = 0;
106 for (size_t i = 0; i < sources_.size() &&
107 page_values_->GetSize() < suggestions_count_; ++i) {
109 size_t index = next_item_index_for_source[i] + extra_items_added;
110 while (page_values_->GetSize() < suggestions_count_ &&
111 (item = sources_[i]->PopItem())) {
112 page_values_->Insert(index++, item);
113 extra_items_added++;
117 // Add page value information common to all sources.
118 for (size_t i = 0; i < page_values_->GetSize(); i++) {
119 base::DictionaryValue* page_value;
120 if (page_values_->GetDictionary(i, &page_value))
121 AddExtendedInformation(page_value);
125 void SuggestionsCombiner::AddExtendedInformation(
126 base::DictionaryValue* page_value) {
127 if (debug_enabled_) {
128 std::string url_string;
129 if (page_value->GetString("url", &url_string)) {
130 GURL url(url_string);
131 page_value->SetBoolean("already_open", IsUrlAlreadyOpen(url));
136 bool SuggestionsCombiner::IsUrlAlreadyOpen(const GURL &url) {
137 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
138 const Browser* browser = *it;
139 if (browser->profile()->IsOffTheRecord() ||
140 !browser->profile()->IsSameProfile(profile_))
141 continue;
143 for (int i = 0; i < browser->tab_strip_model()->count(); i++) {
144 const content::WebContents* tab =
145 browser->tab_strip_model()->GetWebContentsAt(i);
146 if (tab->GetURL() == url)
147 return true;
150 return false;