OLD | NEW |
| (Empty) |
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_page_handler.h" | |
6 | |
7 #include <math.h> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/md5.h" | |
13 #include "base/metrics/histogram.h" | |
14 #include "base/strings/string16.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "base/threading/thread.h" | |
17 #include "base/values.h" | |
18 #include "chrome/browser/history/top_sites_factory.h" | |
19 #include "chrome/browser/profiles/profile.h" | |
20 #include "chrome/browser/ui/webui/favicon_source.h" | |
21 #include "chrome/browser/ui/webui/ntp/ntp_stats.h" | |
22 #include "chrome/browser/ui/webui/ntp/suggestions_combiner.h" | |
23 #include "chrome/browser/ui/webui/ntp/suggestions_source_top_sites.h" | |
24 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h" | |
25 #include "chrome/common/url_constants.h" | |
26 #include "components/history/core/browser/page_usage_data.h" | |
27 #include "components/history/core/browser/top_sites.h" | |
28 #include "components/pref_registry/pref_registry_syncable.h" | |
29 #include "content/public/browser/navigation_controller.h" | |
30 #include "content/public/browser/navigation_entry.h" | |
31 #include "content/public/browser/url_data_source.h" | |
32 #include "content/public/browser/user_metrics.h" | |
33 #include "content/public/browser/web_contents.h" | |
34 #include "content/public/browser/web_ui.h" | |
35 #include "ui/base/page_transition_types.h" | |
36 #include "url/gurl.h" | |
37 | |
38 using base::UserMetricsAction; | |
39 | |
40 SuggestionsHandler::SuggestionsHandler() | |
41 : scoped_observer_(this), | |
42 got_first_suggestions_request_(false), | |
43 suggestions_viewed_(false), | |
44 user_action_logged_(false) { | |
45 } | |
46 | |
47 SuggestionsHandler::~SuggestionsHandler() { | |
48 if (!user_action_logged_ && suggestions_viewed_) { | |
49 const GURL ntp_url = GURL(chrome::kChromeUINewTabURL); | |
50 int action_id = NTP_FOLLOW_ACTION_OTHER; | |
51 content::NavigationEntry* entry = | |
52 web_ui()->GetWebContents()->GetController().GetLastCommittedEntry(); | |
53 if (entry && (entry->GetURL() != ntp_url)) { | |
54 action_id = | |
55 ui::PageTransitionStripQualifier(entry->GetTransitionType()); | |
56 } | |
57 | |
58 UMA_HISTOGRAM_ENUMERATION("NewTabPage.SuggestedSitesAction", action_id, | |
59 NUM_NTP_FOLLOW_ACTIONS); | |
60 } | |
61 } | |
62 | |
63 void SuggestionsHandler::RegisterMessages() { | |
64 Profile* profile = Profile::FromWebUI(web_ui()); | |
65 // Set up our sources for thumbnail and favicon data. | |
66 content::URLDataSource::Add(profile, new ThumbnailSource(profile, false)); | |
67 content::URLDataSource::Add( | |
68 profile, new FaviconSource(profile, FaviconSource::FAVICON)); | |
69 | |
70 // TODO(georgey) change the source of the web-sites to provide our data. | |
71 // Initial commit uses top sites as a data source. | |
72 scoped_refptr<history::TopSites> top_sites = | |
73 TopSitesFactory::GetForProfile(profile); | |
74 if (top_sites) { | |
75 // TopSites updates itself after a delay. This is especially noticable when | |
76 // your profile is empty. Ask TopSites to update itself when we're about to | |
77 // show the new tab page. | |
78 top_sites->SyncWithHistory(); | |
79 | |
80 // Register as TopSitesObserver so that we can update ourselves when the | |
81 // TopSites changes. | |
82 scoped_observer_.Add(top_sites.get()); | |
83 } | |
84 | |
85 // Setup the suggestions sources. | |
86 SuggestionsCombiner* combiner = new SuggestionsCombiner(this, profile); | |
87 combiner->AddSource(new SuggestionsSourceTopSites()); | |
88 suggestions_combiner_.reset(combiner); | |
89 | |
90 // We pre-emptively make a fetch for suggestions so we have the results | |
91 // sooner. | |
92 suggestions_combiner_->FetchItems(profile); | |
93 | |
94 web_ui()->RegisterMessageCallback("getSuggestions", | |
95 base::Bind(&SuggestionsHandler::HandleGetSuggestions, | |
96 base::Unretained(this))); | |
97 // Register ourselves for any suggestions item blacklisting. | |
98 web_ui()->RegisterMessageCallback("blacklistURLFromSuggestions", | |
99 base::Bind(&SuggestionsHandler::HandleBlacklistURL, | |
100 base::Unretained(this))); | |
101 web_ui()->RegisterMessageCallback("removeURLsFromSuggestionsBlacklist", | |
102 base::Bind(&SuggestionsHandler::HandleRemoveURLsFromBlacklist, | |
103 base::Unretained(this))); | |
104 web_ui()->RegisterMessageCallback("clearSuggestionsURLsBlacklist", | |
105 base::Bind(&SuggestionsHandler::HandleClearBlacklist, | |
106 base::Unretained(this))); | |
107 web_ui()->RegisterMessageCallback("suggestedSitesAction", | |
108 base::Bind(&SuggestionsHandler::HandleSuggestedSitesAction, | |
109 base::Unretained(this))); | |
110 web_ui()->RegisterMessageCallback("suggestedSitesSelected", | |
111 base::Bind(&SuggestionsHandler::HandleSuggestedSitesSelected, | |
112 base::Unretained(this))); | |
113 } | |
114 | |
115 void SuggestionsHandler::HandleGetSuggestions(const base::ListValue* args) { | |
116 if (!got_first_suggestions_request_) { | |
117 // If it's the first request we get, return the prefetched data. | |
118 SendPagesValue(); | |
119 got_first_suggestions_request_ = true; | |
120 } else { | |
121 suggestions_combiner_->FetchItems(Profile::FromWebUI(web_ui())); | |
122 } | |
123 } | |
124 | |
125 void SuggestionsHandler::OnSuggestionsReady() { | |
126 // If we got the results as a result of a suggestions request initiated by the | |
127 // JavaScript then we send back the page values. | |
128 if (got_first_suggestions_request_) | |
129 SendPagesValue(); | |
130 } | |
131 | |
132 void SuggestionsHandler::SendPagesValue() { | |
133 if (suggestions_combiner_->GetPageValues()) { | |
134 // TODO(georgey) add actual blacklist. | |
135 bool has_blacklisted_urls = false; | |
136 base::FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls); | |
137 web_ui()->CallJavascriptFunction("ntp.setSuggestionsPages", | |
138 *suggestions_combiner_->GetPageValues(), | |
139 has_blacklisted_urls_value); | |
140 } | |
141 } | |
142 | |
143 void SuggestionsHandler::HandleBlacklistURL(const base::ListValue* args) { | |
144 std::string url = base::UTF16ToUTF8(ExtractStringValue(args)); | |
145 BlacklistURL(GURL(url)); | |
146 } | |
147 | |
148 void SuggestionsHandler::HandleRemoveURLsFromBlacklist( | |
149 const base::ListValue* args) { | |
150 DCHECK_GT(args->GetSize(), 0U); | |
151 // TODO(georgey) remove URLs from blacklist. | |
152 } | |
153 | |
154 void SuggestionsHandler::HandleClearBlacklist(const base::ListValue* args) { | |
155 // TODO(georgey) clear blacklist. | |
156 } | |
157 | |
158 void SuggestionsHandler::HandleSuggestedSitesAction( | |
159 const base::ListValue* args) { | |
160 DCHECK(args); | |
161 | |
162 double action_id; | |
163 if (!args->GetDouble(0, &action_id)) | |
164 NOTREACHED(); | |
165 | |
166 UMA_HISTOGRAM_ENUMERATION("NewTabPage.SuggestedSitesAction", | |
167 static_cast<int>(action_id), | |
168 NUM_NTP_FOLLOW_ACTIONS); | |
169 suggestions_viewed_ = true; | |
170 user_action_logged_ = true; | |
171 } | |
172 | |
173 void SuggestionsHandler::HandleSuggestedSitesSelected( | |
174 const base::ListValue* args) { | |
175 suggestions_viewed_ = true; | |
176 } | |
177 | |
178 void SuggestionsHandler::TopSitesLoaded(history::TopSites* top_sites) { | |
179 } | |
180 | |
181 void SuggestionsHandler::TopSitesChanged(history::TopSites* top_sites) { | |
182 // Suggestions urls changed, query again. | |
183 suggestions_combiner_->FetchItems(Profile::FromWebUI(web_ui())); | |
184 } | |
185 | |
186 void SuggestionsHandler::BlacklistURL(const GURL& url) { | |
187 // TODO(georgey) blacklist an URL. | |
188 } | |
189 | |
190 std::string SuggestionsHandler::GetDictionaryKeyForURL(const std::string& url) { | |
191 return base::MD5String(url); | |
192 } | |
193 | |
194 // static | |
195 void SuggestionsHandler::RegisterProfilePrefs( | |
196 user_prefs::PrefRegistrySyncable* registry) { | |
197 // TODO(georgey) add user preferences (such as own blacklist) as needed. | |
198 } | |
OLD | NEW |