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/new_tab_page_handler.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/metrics/histogram.h" 11 #include "base/prefs/pref_service.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/sync/profile_sync_service.h" 14 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 15 #include "chrome/browser/web_resource/notification_promo.h" 16 #include "chrome/common/pref_names.h" 17 #include "components/pref_registry/pref_registry_syncable.h" 18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/web_ui.h" 20 #include "grit/chromium_strings.h" 21 #include "grit/generated_resources.h" 22 #include "ui/base/l10n/l10n_util.h" 23 24 namespace { 25 26 const char kDefaultPageTypeHistogram[] = "NewTabPage.DefaultPageType"; 27 28 enum PromoAction { 29 PROMO_VIEWED = 0, 30 PROMO_CLOSED, 31 PROMO_LINK_CLICKED, 32 PROMO_ACTION_MAX, 33 }; 34 35 } // namespace 36 37 NewTabPageHandler::NewTabPageHandler() : page_switch_count_(0) { 38 } 39 40 NewTabPageHandler::~NewTabPageHandler() { 41 HISTOGRAM_COUNTS_100("NewTabPage.SingleSessionPageSwitches", 42 page_switch_count_); 43 } 44 45 void NewTabPageHandler::RegisterMessages() { 46 // Record an open of the NTP with its default page type. 47 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 48 int shown_page_type = prefs->GetInteger(prefs::kNtpShownPage) >> 49 kPageIdOffset; 50 UMA_HISTOGRAM_ENUMERATION(kDefaultPageTypeHistogram, 51 shown_page_type, kHistogramEnumerationMax); 52 53 web_ui()->RegisterMessageCallback("notificationPromoClosed", 54 base::Bind(&NewTabPageHandler::HandleNotificationPromoClosed, 55 base::Unretained(this))); 56 web_ui()->RegisterMessageCallback("notificationPromoViewed", 57 base::Bind(&NewTabPageHandler::HandleNotificationPromoViewed, 58 base::Unretained(this))); 59 web_ui()->RegisterMessageCallback("notificationPromoLinkClicked", 60 base::Bind(&NewTabPageHandler::HandleNotificationPromoLinkClicked, 61 base::Unretained(this))); 62 web_ui()->RegisterMessageCallback("bubblePromoClosed", 63 base::Bind(&NewTabPageHandler::HandleBubblePromoClosed, 64 base::Unretained(this))); 65 web_ui()->RegisterMessageCallback("bubblePromoViewed", 66 base::Bind(&NewTabPageHandler::HandleBubblePromoViewed, 67 base::Unretained(this))); 68 web_ui()->RegisterMessageCallback("bubblePromoLinkClicked", 69 base::Bind(&NewTabPageHandler::HandleBubblePromoLinkClicked, 70 base::Unretained(this))); 71 web_ui()->RegisterMessageCallback("pageSelected", 72 base::Bind(&NewTabPageHandler::HandlePageSelected, 73 base::Unretained(this))); 74 web_ui()->RegisterMessageCallback("logTimeToClick", 75 base::Bind(&NewTabPageHandler::HandleLogTimeToClick, 76 base::Unretained(this))); 77 } 78 79 void NewTabPageHandler::HandleNotificationPromoClosed( 80 const base::ListValue* args) { 81 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Notification", 82 PROMO_CLOSED, PROMO_ACTION_MAX); 83 NotificationPromo::HandleClosed(NotificationPromo::NTP_NOTIFICATION_PROMO); 84 Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED); 85 } 86 87 void NewTabPageHandler::HandleNotificationPromoViewed( 88 const base::ListValue* args) { 89 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Notification", 90 PROMO_VIEWED, PROMO_ACTION_MAX); 91 if (NotificationPromo::HandleViewed( 92 NotificationPromo::NTP_NOTIFICATION_PROMO)) { 93 Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED); 94 } 95 } 96 97 void NewTabPageHandler::HandleNotificationPromoLinkClicked( 98 const base::ListValue* args) { 99 DVLOG(1) << "HandleNotificationPromoLinkClicked"; 100 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Notification", 101 PROMO_LINK_CLICKED, PROMO_ACTION_MAX); 102 } 103 104 void NewTabPageHandler::HandleBubblePromoClosed(const base::ListValue* args) { 105 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Bubble", 106 PROMO_CLOSED, PROMO_ACTION_MAX); 107 NotificationPromo::HandleClosed(NotificationPromo::NTP_BUBBLE_PROMO); 108 Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED); 109 } 110 111 void NewTabPageHandler::HandleBubblePromoViewed(const base::ListValue* args) { 112 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Bubble", 113 PROMO_VIEWED, PROMO_ACTION_MAX); 114 if (NotificationPromo::HandleViewed(NotificationPromo::NTP_BUBBLE_PROMO)) 115 Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED); 116 } 117 118 void NewTabPageHandler::HandleBubblePromoLinkClicked( 119 const base::ListValue* args) { 120 DVLOG(1) << "HandleBubblePromoLinkClicked"; 121 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Promo.Bubble", 122 PROMO_LINK_CLICKED, PROMO_ACTION_MAX); 123 } 124 125 void NewTabPageHandler::HandlePageSelected(const base::ListValue* args) { 126 page_switch_count_++; 127 128 double page_id_double; 129 CHECK(args->GetDouble(0, &page_id_double)); 130 int page_id = static_cast<int>(page_id_double); 131 132 double index_double; 133 CHECK(args->GetDouble(1, &index_double)); 134 int index = static_cast<int>(index_double); 135 136 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 137 int previous_shown_page = 138 prefs->GetInteger(prefs::kNtpShownPage) >> kPageIdOffset; 139 UMA_HISTOGRAM_ENUMERATION("NewTabPage.PreviousSelectedPageType", 140 previous_shown_page, kHistogramEnumerationMax); 141 142 prefs->SetInteger(prefs::kNtpShownPage, page_id | index); 143 144 int shown_page_type = page_id >> kPageIdOffset; 145 UMA_HISTOGRAM_ENUMERATION("NewTabPage.SelectedPageType", 146 shown_page_type, kHistogramEnumerationMax); 147 } 148 149 void NewTabPageHandler::HandleLogTimeToClick(const base::ListValue* args) { 150 std::string histogram_name; 151 double duration; 152 if (!args->GetString(0, &histogram_name) || !args->GetDouble(1, &duration)) { 153 NOTREACHED(); 154 return; 155 } 156 157 base::TimeDelta delta = base::TimeDelta::FromMilliseconds(duration); 158 159 if (histogram_name == "NewTabPage.TimeToClickMostVisited") { 160 UMA_HISTOGRAM_LONG_TIMES("NewTabPage.TimeToClickMostVisited", delta); 161 } else if (histogram_name == "NewTabPage.TimeToClickRecentlyClosed") { 162 UMA_HISTOGRAM_LONG_TIMES("NewTabPage.TimeToClickRecentlyClosed", delta); 163 } else if (histogram_name == "ExtendedNewTabPage.TimeToClickMostVisited") { 164 UMA_HISTOGRAM_LONG_TIMES( 165 "ExtendedNewTabPage.TimeToClickMostVisited", delta); 166 } else if (histogram_name == "ExtendedNewTabPage.TimeToClickRecentlyClosed") { 167 UMA_HISTOGRAM_LONG_TIMES( 168 "ExtendedNewTabPage.TimeToClickRecentlyClosed", delta); 169 } else { 170 NOTREACHED(); 171 } 172 } 173 174 // static 175 void NewTabPageHandler::RegisterProfilePrefs( 176 user_prefs::PrefRegistrySyncable* registry) { 177 // TODO(estade): should be syncable. 178 registry->RegisterIntegerPref( 179 prefs::kNtpShownPage, 180 APPS_PAGE_ID, 181 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 182 } 183 184 // static 185 void NewTabPageHandler::GetLocalizedValues(Profile* profile, 186 base::DictionaryValue* values) { 187 values->SetInteger("most_visited_page_id", MOST_VISITED_PAGE_ID); 188 values->SetInteger("apps_page_id", APPS_PAGE_ID); 189 values->SetInteger("suggestions_page_id", SUGGESTIONS_PAGE_ID); 190 191 PrefService* prefs = profile->GetPrefs(); 192 int shown_page = prefs->GetInteger(prefs::kNtpShownPage); 193 values->SetInteger("shown_page_type", shown_page & ~INDEX_MASK); 194 values->SetInteger("shown_page_index", shown_page & INDEX_MASK); 195 } 196 197 void NewTabPageHandler::Notify(chrome::NotificationType notification_type) { 198 content::NotificationService* service = 199 content::NotificationService::current(); 200 service->Notify(notification_type, 201 content::Source<NewTabPageHandler>(this), 202 content::NotificationService::NoDetails()); 203 } 204