Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / ntp / most_visited_handler.cc
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/most_visited_handler.h"
6
7 #include <set>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/md5.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/memory/singleton.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/prefs/scoped_user_pref_update.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/threading/thread.h"
22 #include "base/values.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/history/top_sites.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/thumbnails/thumbnail_list_source.h"
27 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model_utils.h"
31 #include "chrome/browser/ui/webui/favicon_source.h"
32 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
33 #include "chrome/browser/ui/webui/ntp/ntp_stats.h"
34 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h"
37 #include "components/history/core/browser/page_usage_data.h"
38 #include "components/pref_registry/pref_registry_syncable.h"
39 #include "content/public/browser/navigation_controller.h"
40 #include "content/public/browser/navigation_entry.h"
41 #include "content/public/browser/notification_source.h"
42 #include "content/public/browser/url_data_source.h"
43 #include "content/public/browser/user_metrics.h"
44 #include "content/public/browser/web_contents.h"
45 #include "content/public/browser/web_ui.h"
46 #include "url/gurl.h"
47
48 using base::UserMetricsAction;
49
50 MostVisitedHandler::MostVisitedHandler()
51     : got_first_most_visited_request_(false),
52       most_visited_viewed_(false),
53       user_action_logged_(false),
54       weak_ptr_factory_(this) {
55 }
56
57 MostVisitedHandler::~MostVisitedHandler() {
58   if (!user_action_logged_ && most_visited_viewed_) {
59     const GURL ntp_url = GURL(chrome::kChromeUINewTabURL);
60     int action_id = NTP_FOLLOW_ACTION_OTHER;
61     content::NavigationEntry* entry =
62         web_ui()->GetWebContents()->GetController().GetLastCommittedEntry();
63     if (entry && (entry->GetURL() != ntp_url)) {
64       action_id =
65           ui::PageTransitionStripQualifier(entry->GetTransitionType());
66     }
67
68     UMA_HISTOGRAM_ENUMERATION("NewTabPage.MostVisitedAction", action_id,
69                               NUM_NTP_FOLLOW_ACTIONS);
70   }
71 }
72
73 void MostVisitedHandler::RegisterMessages() {
74   Profile* profile = Profile::FromWebUI(web_ui());
75   // Set up our sources for thumbnail and favicon data.
76   content::URLDataSource::Add(profile, new ThumbnailSource(profile, false));
77   content::URLDataSource::Add(profile, new ThumbnailSource(profile, true));
78
79   // Set up our sources for top-sites data.
80   content::URLDataSource::Add(profile, new ThumbnailListSource(profile));
81
82   // Register chrome://favicon as a data source for favicons.
83   content::URLDataSource::Add(
84       profile, new FaviconSource(profile, FaviconSource::FAVICON));
85
86   history::TopSites* ts = profile->GetTopSites();
87   if (ts) {
88     // TopSites updates itself after a delay. This is especially noticable when
89     // your profile is empty. Ask TopSites to update itself when we're about to
90     // show the new tab page.
91     ts->SyncWithHistory();
92
93     // Register for notification when TopSites changes so that we can update
94     // ourself.
95     registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
96                    content::Source<history::TopSites>(ts));
97   }
98
99   // We pre-emptively make a fetch for the most visited pages so we have the
100   // results sooner.
101   StartQueryForMostVisited();
102
103   web_ui()->RegisterMessageCallback("getMostVisited",
104       base::Bind(&MostVisitedHandler::HandleGetMostVisited,
105                  base::Unretained(this)));
106
107   // Register ourselves for any most-visited item blacklisting.
108   web_ui()->RegisterMessageCallback("blacklistURLFromMostVisited",
109       base::Bind(&MostVisitedHandler::HandleBlacklistUrl,
110                  base::Unretained(this)));
111   web_ui()->RegisterMessageCallback("removeURLsFromMostVisitedBlacklist",
112       base::Bind(&MostVisitedHandler::HandleRemoveUrlsFromBlacklist,
113                  base::Unretained(this)));
114   web_ui()->RegisterMessageCallback("clearMostVisitedURLsBlacklist",
115       base::Bind(&MostVisitedHandler::HandleClearBlacklist,
116                  base::Unretained(this)));
117   web_ui()->RegisterMessageCallback("mostVisitedAction",
118       base::Bind(&MostVisitedHandler::HandleMostVisitedAction,
119                  base::Unretained(this)));
120   web_ui()->RegisterMessageCallback("mostVisitedSelected",
121       base::Bind(&MostVisitedHandler::HandleMostVisitedSelected,
122                  base::Unretained(this)));
123 }
124
125 void MostVisitedHandler::HandleGetMostVisited(const base::ListValue* args) {
126   if (!got_first_most_visited_request_) {
127     // If our initial data is already here, return it.
128     SendPagesValue();
129     got_first_most_visited_request_ = true;
130   } else {
131     StartQueryForMostVisited();
132   }
133 }
134
135 void MostVisitedHandler::SendPagesValue() {
136   if (pages_value_) {
137     Profile* profile = Profile::FromWebUI(web_ui());
138     const base::DictionaryValue* url_blacklist =
139         profile->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist);
140     bool has_blacklisted_urls = !url_blacklist->empty();
141     history::TopSites* ts = profile->GetTopSites();
142     if (ts)
143       has_blacklisted_urls = ts->HasBlacklistedItems();
144
145     base::FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls);
146     web_ui()->CallJavascriptFunction("ntp.setMostVisitedPages",
147                                      *pages_value_,
148                                      has_blacklisted_urls_value);
149     pages_value_.reset();
150   }
151 }
152
153 void MostVisitedHandler::StartQueryForMostVisited() {
154   history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites();
155   if (ts) {
156     ts->GetMostVisitedURLs(
157         base::Bind(&MostVisitedHandler::OnMostVisitedUrlsAvailable,
158                    weak_ptr_factory_.GetWeakPtr()), false);
159   }
160 }
161
162 void MostVisitedHandler::HandleBlacklistUrl(const base::ListValue* args) {
163   std::string url = base::UTF16ToUTF8(ExtractStringValue(args));
164   BlacklistUrl(GURL(url));
165 }
166
167 void MostVisitedHandler::HandleRemoveUrlsFromBlacklist(
168     const base::ListValue* args) {
169   DCHECK(args->GetSize() != 0);
170
171   for (base::ListValue::const_iterator iter = args->begin();
172        iter != args->end(); ++iter) {
173     std::string url;
174     bool r = (*iter)->GetAsString(&url);
175     if (!r) {
176       NOTREACHED();
177       return;
178     }
179     content::RecordAction(UserMetricsAction("MostVisited_UrlRemoved"));
180     history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites();
181     if (ts)
182       ts->RemoveBlacklistedURL(GURL(url));
183   }
184 }
185
186 void MostVisitedHandler::HandleClearBlacklist(const base::ListValue* args) {
187   content::RecordAction(UserMetricsAction("MostVisited_BlacklistCleared"));
188
189   history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites();
190   if (ts)
191     ts->ClearBlacklistedURLs();
192 }
193
194 void MostVisitedHandler::HandleMostVisitedAction(const base::ListValue* args) {
195   DCHECK(args);
196
197   double action_id;
198   if (!args->GetDouble(0, &action_id))
199     NOTREACHED();
200
201   UMA_HISTOGRAM_ENUMERATION("NewTabPage.MostVisitedAction",
202                             static_cast<int>(action_id),
203                             NUM_NTP_FOLLOW_ACTIONS);
204   most_visited_viewed_ = true;
205   user_action_logged_ = true;
206 }
207
208 void MostVisitedHandler::HandleMostVisitedSelected(
209     const base::ListValue* args) {
210   most_visited_viewed_ = true;
211 }
212
213 void MostVisitedHandler::SetPagesValueFromTopSites(
214     const history::MostVisitedURLList& data) {
215   pages_value_.reset(new base::ListValue);
216
217   history::MostVisitedURLList top_sites(data);
218   for (size_t i = 0; i < top_sites.size(); i++) {
219     const history::MostVisitedURL& url = top_sites[i];
220
221     // The items which are to be written into |page_value| are also described in
222     // chrome/browser/resources/ntp4/new_tab.js in @typedef for PageData. Please
223     // update it whenever you add or remove any keys here.
224     base::DictionaryValue* page_value = new base::DictionaryValue();
225     if (url.url.is_empty()) {
226       page_value->SetBoolean("filler", true);
227       pages_value_->Append(page_value);
228       continue;
229     }
230
231     NewTabUI::SetUrlTitleAndDirection(page_value,
232                                       url.title,
233                                       url.url);
234     pages_value_->Append(page_value);
235   }
236 }
237
238 void MostVisitedHandler::OnMostVisitedUrlsAvailable(
239     const history::MostVisitedURLList& data) {
240   SetPagesValueFromTopSites(data);
241   if (got_first_most_visited_request_) {
242     SendPagesValue();
243   }
244 }
245
246 void MostVisitedHandler::Observe(int type,
247                                  const content::NotificationSource& source,
248                                  const content::NotificationDetails& details) {
249   DCHECK_EQ(type, chrome::NOTIFICATION_TOP_SITES_CHANGED);
250
251   // Most visited urls changed, query again.
252   StartQueryForMostVisited();
253 }
254
255 void MostVisitedHandler::BlacklistUrl(const GURL& url) {
256   history::TopSites* ts = Profile::FromWebUI(web_ui())->GetTopSites();
257   if (ts)
258     ts->AddBlacklistedURL(url);
259   content::RecordAction(UserMetricsAction("MostVisited_UrlBlacklisted"));
260 }
261
262 std::string MostVisitedHandler::GetDictionaryKeyForUrl(const std::string& url) {
263   return base::MD5String(url);
264 }
265
266 // static
267 void MostVisitedHandler::RegisterProfilePrefs(
268     user_prefs::PrefRegistrySyncable* registry) {
269   registry->RegisterDictionaryPref(
270       prefs::kNtpMostVisitedURLsBlacklist,
271       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
272 }