OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/webui/ntp/most_visited_handler.h" | 5 #include "chrome/browser/ui/webui/ntp/most_visited_handler.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/md5.h" | 12 #include "base/md5.h" |
13 #include "base/memory/scoped_vector.h" | 13 #include "base/memory/scoped_vector.h" |
14 #include "base/memory/singleton.h" | 14 #include "base/memory/singleton.h" |
15 #include "base/metrics/field_trial.h" | |
16 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
17 #include "base/prefs/pref_service.h" | 16 #include "base/prefs/pref_service.h" |
18 #include "base/strings/string16.h" | 17 #include "base/strings/string16.h" |
19 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
21 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
22 #include "base/values.h" | 21 #include "base/values.h" |
23 #include "chrome/browser/chrome_notification_types.h" | 22 #include "chrome/browser/chrome_notification_types.h" |
| 23 #include "chrome/browser/history/most_visited_tiles_experiment.h" |
24 #include "chrome/browser/history/page_usage_data.h" | 24 #include "chrome/browser/history/page_usage_data.h" |
25 #include "chrome/browser/history/top_sites.h" | 25 #include "chrome/browser/history/top_sites.h" |
26 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 26 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
27 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
28 #include "chrome/browser/ui/browser.h" | 28 #include "chrome/browser/ui/browser.h" |
29 #include "chrome/browser/ui/browser_finder.h" | 29 #include "chrome/browser/ui/browser_finder.h" |
30 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 30 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
31 #include "chrome/browser/ui/webui/favicon_source.h" | 31 #include "chrome/browser/ui/webui/favicon_source.h" |
32 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" | 32 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" |
33 #include "chrome/browser/ui/webui/ntp/ntp_stats.h" | 33 #include "chrome/browser/ui/webui/ntp/ntp_stats.h" |
(...skipping 11 matching lines...) Expand all Loading... |
45 #include "grit/chromium_strings.h" | 45 #include "grit/chromium_strings.h" |
46 #include "grit/generated_resources.h" | 46 #include "grit/generated_resources.h" |
47 #include "grit/locale_settings.h" | 47 #include "grit/locale_settings.h" |
48 #include "ui/base/l10n/l10n_util.h" | 48 #include "ui/base/l10n/l10n_util.h" |
49 #include "url/gurl.h" | 49 #include "url/gurl.h" |
50 | 50 |
51 using content::UserMetricsAction; | 51 using content::UserMetricsAction; |
52 | 52 |
53 namespace { | 53 namespace { |
54 | 54 |
55 // Constants for the most visited tile placement field trial. | |
56 const char kMostVisitedFieldTrialName[] = "MostVisitedTilePlacement"; | |
57 const char kTabsGroupName[] = "DontShowOpenTabs"; | |
58 | |
59 // Minimum number of suggestions that |pages_value_| must hold for the Most | |
60 // Visited Field Trial to remove a URL if already open in the browser. | |
61 const size_t kMinUrlSuggestions = 8; | |
62 | |
63 // Creates a set containing the canonical URLs of the currently open tabs. | 55 // Creates a set containing the canonical URLs of the currently open tabs. |
64 void GetOpenUrls(const TabStripModel& tabs, | 56 void GetOpenUrls(const TabStripModel& tabs, |
65 const history::TopSites& ts, | 57 const history::TopSites& ts, |
66 std::set<std::string>* urls) { | 58 std::set<std::string>* urls) { |
67 for (int i = 0; i < tabs.count(); ++i) { | 59 for (int i = 0; i < tabs.count(); ++i) { |
68 content::WebContents* web_contents = tabs.GetWebContentsAt(i); | 60 content::WebContents* web_contents = tabs.GetWebContentsAt(i); |
69 if (web_contents) | 61 if (web_contents) |
70 urls->insert(ts.GetCanonicalURLString(web_contents->GetURL())); | 62 urls->insert(ts.GetCanonicalURLString(web_contents->GetURL())); |
71 } | 63 } |
72 } | 64 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 void MostVisitedHandler::SendPagesValue() { | 155 void MostVisitedHandler::SendPagesValue() { |
164 if (pages_value_) { | 156 if (pages_value_) { |
165 Profile* profile = Profile::FromWebUI(web_ui()); | 157 Profile* profile = Profile::FromWebUI(web_ui()); |
166 const DictionaryValue* url_blacklist = | 158 const DictionaryValue* url_blacklist = |
167 profile->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 159 profile->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
168 bool has_blacklisted_urls = !url_blacklist->empty(); | 160 bool has_blacklisted_urls = !url_blacklist->empty(); |
169 history::TopSites* ts = profile->GetTopSites(); | 161 history::TopSites* ts = profile->GetTopSites(); |
170 if (ts) { | 162 if (ts) { |
171 has_blacklisted_urls = ts->HasBlacklistedItems(); | 163 has_blacklisted_urls = ts->HasBlacklistedItems(); |
172 | 164 |
173 // The following experiment removes recommended URLs if a matching URL is | 165 MaybeRemovePageValues(); |
174 // already open in the Browser. Note: this targets only the | |
175 // top-level of sites i.e. if www.foo.com/bar is open in browser, and | |
176 // www.foo.com is a recommended URL, www.foo.com will still appear on the | |
177 // next NTP open. | |
178 if (base::FieldTrialList::FindFullName(kMostVisitedFieldTrialName) == | |
179 kTabsGroupName) { | |
180 RemovePageValuesMatchingOpenTabs(); | |
181 } | |
182 } | 166 } |
183 | 167 |
184 base::FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls); | 168 base::FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls); |
185 web_ui()->CallJavascriptFunction("ntp.setMostVisitedPages", | 169 web_ui()->CallJavascriptFunction("ntp.setMostVisitedPages", |
186 *pages_value_, | 170 *pages_value_, |
187 has_blacklisted_urls_value); | 171 has_blacklisted_urls_value); |
188 pages_value_.reset(); | 172 pages_value_.reset(); |
189 } | 173 } |
190 } | 174 } |
191 | 175 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 void MostVisitedHandler::HandleMostVisitedSelected( | 230 void MostVisitedHandler::HandleMostVisitedSelected( |
247 const base::ListValue* args) { | 231 const base::ListValue* args) { |
248 most_visited_viewed_ = true; | 232 most_visited_viewed_ = true; |
249 } | 233 } |
250 | 234 |
251 void MostVisitedHandler::SetPagesValueFromTopSites( | 235 void MostVisitedHandler::SetPagesValueFromTopSites( |
252 const history::MostVisitedURLList& data) { | 236 const history::MostVisitedURLList& data) { |
253 pages_value_.reset(new ListValue); | 237 pages_value_.reset(new ListValue); |
254 | 238 |
255 history::MostVisitedURLList top_sites(data); | 239 history::MostVisitedURLList top_sites(data); |
256 history::TopSites::MaybeShuffle(&top_sites); | 240 history::MostVisitedTilesExperiment::MaybeShuffle(&top_sites); |
257 | 241 |
258 for (size_t i = 0; i < top_sites.size(); i++) { | 242 for (size_t i = 0; i < top_sites.size(); i++) { |
259 const history::MostVisitedURL& url = top_sites[i]; | 243 const history::MostVisitedURL& url = top_sites[i]; |
260 DictionaryValue* page_value = new DictionaryValue(); | 244 DictionaryValue* page_value = new DictionaryValue(); |
261 if (url.url.is_empty()) { | 245 if (url.url.is_empty()) { |
262 page_value->SetBoolean("filler", true); | 246 page_value->SetBoolean("filler", true); |
263 pages_value_->Append(page_value); | 247 pages_value_->Append(page_value); |
264 continue; | 248 continue; |
265 } | 249 } |
266 | 250 |
(...skipping 25 matching lines...) Expand all Loading... |
292 history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites(); | 276 history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites(); |
293 if (ts) | 277 if (ts) |
294 ts->AddBlacklistedURL(url); | 278 ts->AddBlacklistedURL(url); |
295 content::RecordAction(UserMetricsAction("MostVisited_UrlBlacklisted")); | 279 content::RecordAction(UserMetricsAction("MostVisited_UrlBlacklisted")); |
296 } | 280 } |
297 | 281 |
298 std::string MostVisitedHandler::GetDictionaryKeyForUrl(const std::string& url) { | 282 std::string MostVisitedHandler::GetDictionaryKeyForUrl(const std::string& url) { |
299 return base::MD5String(url); | 283 return base::MD5String(url); |
300 } | 284 } |
301 | 285 |
302 void MostVisitedHandler::RemovePageValuesMatchingOpenTabs() { | 286 void MostVisitedHandler::MaybeRemovePageValues() { |
| 287 // The following #if is due to the facts that tabstripmodel cannot be accessed |
| 288 // in the same way, that chrome::FindBrowserWithWebContents is undefined in |
| 289 // Android and, moreover, that this experiment is not designed to run on Android |
| 290 // devices due to different NTP presentation. |
303 #if !defined(OS_ANDROID) | 291 #if !defined(OS_ANDROID) |
| 292 if (!history::MostVisitedTilesExperiment::IsDontShowOpenURLsEnabled()) |
| 293 return; |
| 294 |
304 TabStripModel* tab_strip_model = chrome::FindBrowserWithWebContents( | 295 TabStripModel* tab_strip_model = chrome::FindBrowserWithWebContents( |
305 web_ui()->GetWebContents())->tab_strip_model(); | 296 web_ui()->GetWebContents())->tab_strip_model(); |
306 history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites(); | 297 history::TopSites* top_sites = Profile::FromWebUI(web_ui())->GetTopSites(); |
307 if (!tab_strip_model || !ts) { | 298 if (!tab_strip_model || !top_sites) { |
308 NOTREACHED(); | 299 NOTREACHED(); |
309 return; | 300 return; |
310 } | 301 } |
311 | 302 |
312 // Iterate through most visited suggestions and remove pages already open in | |
313 // current browser, making sure to not drop below 8 suggestions. | |
314 std::set<std::string> open_urls; | 303 std::set<std::string> open_urls; |
315 GetOpenUrls(*tab_strip_model, *ts, &open_urls); | 304 GetOpenUrls(*tab_strip_model, *top_sites, &open_urls); |
316 size_t i = 0; | 305 history::MostVisitedTilesExperiment::RemovePageValuesMatchingOpenTabs( |
317 while (i < pages_value_->GetSize() && | 306 open_urls, |
318 pages_value_->GetSize() > kMinUrlSuggestions) { | 307 pages_value_.get()); |
319 base::DictionaryValue* page_value; | |
320 std::string url; | |
321 if (pages_value_->GetDictionary(i, &page_value) && | |
322 page_value->GetString("url", &url) && | |
323 open_urls.count(url) != 0) { | |
324 pages_value_->Remove(*page_value, &i); | |
325 } else { | |
326 ++i; | |
327 } | |
328 } | |
329 #endif | 308 #endif |
330 } | 309 } |
331 | 310 |
332 // static | 311 // static |
333 void MostVisitedHandler::RegisterProfilePrefs( | 312 void MostVisitedHandler::RegisterProfilePrefs( |
334 user_prefs::PrefRegistrySyncable* registry) { | 313 user_prefs::PrefRegistrySyncable* registry) { |
335 registry->RegisterDictionaryPref( | 314 registry->RegisterDictionaryPref( |
336 prefs::kNtpMostVisitedURLsBlacklist, | 315 prefs::kNtpMostVisitedURLsBlacklist, |
337 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 316 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
338 } | 317 } |
OLD | NEW |