172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/most_visited_handler.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/md5.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_vector.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string16.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/utf_string_conversions.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/page_usage_data.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/top_sites.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h" 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h" 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/chrome_url_data_manager.h" 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/favicon_source.h" 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/new_tab_ui.h" 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/thumbnail_source.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/url_constants.h" 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "googleurl/src/gurl.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h" 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of most visited pages we show. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst size_t kMostVisitedPages = 8; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of days of history we consider for most visited entries. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMostVisitedScope = 90; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This struct is used when getting the pre-populated pages in case the user 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// hasn't filled up his most visited pages. 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstruct MostVisitedHandler::MostVisitedPage { 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 title; 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL url; 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL thumbnail_url; 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL favicon_url; 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMostVisitedHandler::MostVisitedHandler() 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : got_first_most_visited_request_(false) { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickMostVisitedHandler::~MostVisitedHandler() { 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenWebUIMessageHandler* MostVisitedHandler::Attach(WebUI* web_ui) { 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Profile* profile = web_ui->GetProfile(); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up our sources for thumbnail and favicon data. 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ThumbnailSource* thumbnail_src = new ThumbnailSource(profile); 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen profile->GetChromeURLDataManager()->AddDataSource(thumbnail_src); 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile->GetChromeURLDataManager()->AddDataSource(new FaviconSource(profile)); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get notifications when history is cleared. 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED, 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Source<Profile>(profile)); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We pre-emptively make a fetch for the most visited pages so we have the 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // results sooner. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartQueryForMostVisited(); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::RegisterMessages() { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register ourselves as the handler for the "mostvisited" message from 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Javascript. 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("getMostVisited", 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleGetMostVisited)); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register ourselves for any most-visited item blacklisting. 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("blacklistURLFromMostVisited", 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleBlacklistURL)); 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("removeURLsFromMostVisitedBlacklist", 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleRemoveURLsFromBlacklist)); 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("clearMostVisitedURLsBlacklist", 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleClearBlacklist)); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register ourself for pinned URL messages. 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("addPinnedURL", 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleAddPinnedURL)); 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->RegisterMessageCallback("removePinnedURL", 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &MostVisitedHandler::HandleRemovePinnedURL)); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleGetMostVisited(const ListValue* args) { 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!got_first_most_visited_request_) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If our intial data is already here, return it. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendPagesValue(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch got_first_most_visited_request_ = true; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartQueryForMostVisited(); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::SendPagesValue() { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pages_value_.get()) { 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Profile* profile = web_ui_->GetProfile(); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const DictionaryValue* url_blacklist = 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile->GetPrefs()->GetDictionary(prefs::kNTPMostVisitedURLsBlacklist); 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_blacklisted_urls = !url_blacklist->empty(); 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history::TopSites* ts = profile->GetTopSites(); 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen has_blacklisted_urls = ts->HasBlacklistedItems(); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FundamentalValue first_run(IsFirstRun()); 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls); 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_ui_->CallJavascriptFunction("mostVisitedPages", 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *(pages_value_.get()), 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick first_run, 131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick has_blacklisted_urls_value); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pages_value_.reset(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::StartQueryForMostVisited() { 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Use TopSites. 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) { 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->GetMostVisitedURLs( 14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &topsites_consumer_, 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewCallback(this, &MostVisitedHandler::OnMostVisitedURLsAvailable)); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleBlacklistURL(const ListValue* args) { 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url = UTF16ToUTF8(ExtractStringValue(args)); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BlacklistURL(GURL(url)); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleRemoveURLsFromBlacklist(const ListValue* args) { 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(args->GetSize() != 0); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (ListValue::const_iterator iter = args->begin(); 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick iter != args->end(); ++iter) { 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string url; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool r = (*iter)->GetAsString(&url); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!r) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("MostVisited_UrlRemoved"), 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->GetProfile()); 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->RemoveBlacklistedURL(GURL(url)); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleClearBlacklist(const ListValue* args) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("MostVisited_BlacklistCleared"), 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_ui_->GetProfile()); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->ClearBlacklistedURLs(); 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleAddPinnedURL(const ListValue* args) { 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(5U, args->GetSize()) << "Wrong number of params to addPinnedURL"; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedPage mvp; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string tmp_string; 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 tmp_string16; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool r = args->GetString(0, &tmp_string); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(r) << "Missing URL in addPinnedURL from the NTP Most Visited."; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mvp.url = GURL(tmp_string); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick r = args->GetString(1, &tmp_string16); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(r) << "Missing title in addPinnedURL from the NTP Most Visited."; 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mvp.title = tmp_string16; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick r = args->GetString(2, &tmp_string); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(r) << "Failed to read the favicon URL in addPinnedURL from the NTP " 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "Most Visited."; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tmp_string.empty()) 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mvp.favicon_url = GURL(tmp_string); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick r = args->GetString(3, &tmp_string); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(r) << "Failed to read the thumbnail URL in addPinnedURL from the NTP " 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "Most Visited."; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tmp_string.empty()) 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mvp.thumbnail_url = GURL(tmp_string); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick r = args->GetString(4, &tmp_string); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(r) << "Missing index in addPinnedURL from the NTP Most Visited."; 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::StringToInt(tmp_string, &index); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddPinnedURL(mvp, index); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::AddPinnedURL(const MostVisitedPage& page, int index) { 21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->AddPinnedURL(page.url, index); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::HandleRemovePinnedURL(const ListValue* args) { 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url = UTF16ToUTF8(ExtractStringValue(args)); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemovePinnedURL(GURL(url)); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::RemovePinnedURL(const GURL& url) { 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->RemovePinnedURL(url); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MostVisitedHandler::GetPinnedURLAtIndex(int index, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedPage* page) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This iterates over all the pinned URLs. It might seem like it is worth 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // having a map from the index to the item but the number of items is limited 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the number of items the most visited section is showing on the NTP so 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this will be fast enough for now. 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrefService* prefs = web_ui_->GetProfile()->GetPrefs(); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const DictionaryValue* pinned_urls = 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prefs->GetDictionary(prefs::kNTPMostVisitedPinnedURLs); 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (DictionaryValue::key_iterator it = pinned_urls->begin_keys(); 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != pinned_urls->end_keys(); ++it) { 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Value* value; 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pinned_urls->GetWithoutPathExpansion(*it, &value)) { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!value->IsType(DictionaryValue::TYPE_DICTIONARY)) { 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Moved on to TopSites and now going back. 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryPrefUpdate update(prefs, prefs::kNTPMostVisitedPinnedURLs); 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen update.Get()->Clear(); 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int dict_index; 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const DictionaryValue* dict = static_cast<DictionaryValue*>(value); 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dict->GetInteger("index", &dict_index) && dict_index == index) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The favicon and thumbnail URLs may be empty. 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string tmp_string; 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dict->GetString("faviconUrl", &tmp_string)) 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch page->favicon_url = GURL(tmp_string); 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dict->GetString("thumbnailUrl", &tmp_string)) 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch page->thumbnail_url = GURL(tmp_string); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dict->GetString("url", &tmp_string)) 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch page->url = GURL(tmp_string); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return dict->GetString("title", &page->title); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "DictionaryValue iterators are filthy liars."; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MostVisitedHandler::SetPagesValueFromTopSites( 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const history::MostVisitedURLList& data) { 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pages_value_.reset(new ListValue); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < data.size(); i++) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const history::MostVisitedURL& url = data[i]; 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DictionaryValue* page_value = new DictionaryValue(); 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (url.url.is_empty()) { 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_value->SetBoolean("filler", true); 2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pages_value_->Append(page_value); 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick continue; 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewTabUI::SetURLTitleAndDirection(page_value, 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url.title, 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url.url); 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!url.favicon_url.is_empty()) 2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_value->SetString("faviconUrl", url.favicon_url.spec()); 2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Special case for prepopulated pages: thumbnailUrl is different from url. 2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (url.url.spec() == l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL)) { 2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_value->SetString("thumbnailUrl", 2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "chrome://theme/IDR_NEWTAB_CHROME_WELCOME_PAGE_THUMBNAIL"); 2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (url.url.spec() == 2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL)) { 2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_value->SetString("thumbnailUrl", 3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "chrome://theme/IDR_NEWTAB_THEMES_GALLERY_THUMBNAIL"); 3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (ts && ts->IsURLPinned(url.url)) 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_value->SetBoolean("pinned", true); 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pages_value_->Append(page_value); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::OnMostVisitedURLsAvailable( 311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const history::MostVisitedURLList& data) { 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetPagesValueFromTopSites(data); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_first_most_visited_request_) { 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendPagesValue(); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MostVisitedHandler::IsFirstRun() { 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we found no pages we treat this as the first run. 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool first_run = NewTabUI::NewTabHTMLSource::first_run() && 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pages_value_->GetSize() == 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedHandler::GetPrePopulatedPages().size(); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but first_run should only be true once. 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewTabUI::NewTabHTMLSource::set_first_run(false); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return first_run; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::vector<MostVisitedHandler::MostVisitedPage>& 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedHandler::GetPrePopulatedPages() { 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(arv): This needs to get the data from some configurable place. 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // http://crbug.com/17630 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::vector<MostVisitedPage> pages; 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pages.empty()) { 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedPage welcome_page = { 3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick l10n_util::GetStringUTF16(IDS_NEW_TAB_CHROME_WELCOME_PAGE_TITLE), 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL(l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL)), 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("chrome://theme/IDR_NEWTAB_CHROME_WELCOME_PAGE_THUMBNAIL"), 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("chrome://theme/IDR_NEWTAB_CHROME_WELCOME_PAGE_FAVICON")}; 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pages.push_back(welcome_page); 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedPage gallery_page = { 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick l10n_util::GetStringUTF16(IDS_NEW_TAB_THEMES_GALLERY_PAGE_TITLE), 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL)), 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("chrome://theme/IDR_NEWTAB_THEMES_GALLERY_THUMBNAIL"), 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL("chrome://theme/IDR_NEWTAB_THEMES_GALLERY_FAVICON")}; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pages.push_back(gallery_page); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return pages; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::Observe(NotificationType type, 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type != NotificationType::HISTORY_URLS_DELETED) { 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Some URLs were deleted from history. Reload the most visited list. 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleGetMostVisited(NULL); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::BlacklistURL(const GURL& url) { 36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen history::TopSites* ts = web_ui_->GetProfile()->GetTopSites(); 36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ts) 36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ts->AddBlacklistedURL(url); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string MostVisitedHandler::GetDictionaryKeyForURL(const std::string& url) { 3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return MD5String(url); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MostVisitedHandler::RegisterUserPrefs(PrefService* prefs) { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterDictionaryPref(prefs::kNTPMostVisitedURLsBlacklist); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterDictionaryPref(prefs::kNTPMostVisitedPinnedURLs); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static 382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::vector<GURL> MostVisitedHandler::GetPrePopulatedUrls() { 383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const std::vector<MostVisitedPage> pages = 384201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch MostVisitedHandler::GetPrePopulatedPages(); 385201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::vector<GURL> page_urls; 386201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (size_t i = 0; i < pages.size(); ++i) 387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch page_urls.push_back(pages[i].url); 388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return page_urls; 389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 390