diff options
author | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-29 23:43:30 +0000 |
---|---|---|
committer | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-29 23:43:30 +0000 |
commit | 6749c68237fcc188dac3520527d5d5210f6147fc (patch) | |
tree | d97e0a9d38d68a969bbfe45a55d7b56c8745737b /chrome/browser | |
parent | 7f856bee73ffdccdbbbbbab4cb79185290d38359 (diff) | |
download | chromium_src-6749c68237fcc188dac3520527d5d5210f6147fc.zip chromium_src-6749c68237fcc188dac3520527d5d5210f6147fc.tar.gz chromium_src-6749c68237fcc188dac3520527d5d5210f6147fc.tar.bz2 |
Add more UMA collection to the New Tab Page
BUG=1450986
Review URL: http://codereview.chromium.org/8686
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4192 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.cc | 133 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.h | 18 | ||||
-rw-r--r-- | chrome/browser/resources/new_tab.html | 17 |
3 files changed, 137 insertions, 31 deletions
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index ff3e997e..02177b1 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -49,6 +49,9 @@ const int kMostVisitedScope = 90; // The number of recent bookmarks we show. static const int kRecentBookmarks = 9; +// The number of search URLs to show. +static const int kSearchURLs = 3; + // Strings sent to the page via jstemplates used to set the direction of the // HTML document based on locale. static const wchar_t kRTLHtmlTextDirection[] = L"rtl"; @@ -150,6 +153,9 @@ void SetURLAndTitle(DictionaryValue* dictionary, std::wstring title, } // end anonymous namespace +/////////////////////////////////////////////////////////////////////////////// +// NewTabHTMLSource + NewTabHTMLSource::NewTabHTMLSource() : DataSource("new-tab", MessageLoop::current()) { } @@ -204,6 +210,9 @@ void NewTabHTMLSource::StartDataRequest(const std::string& path, SendResponse(request_id, html_bytes); } +/////////////////////////////////////////////////////////////////////////////// +// IncognitoTabHTMLSource + IncognitoTabHTMLSource::IncognitoTabHTMLSource() : DataSource("new-tab", MessageLoop::current()) { } @@ -235,6 +244,9 @@ void IncognitoTabHTMLSource::StartDataRequest(const std::string& path, SendResponse(request_id, html_bytes); } +/////////////////////////////////////////////////////////////////////////////// +// ThumbnailSource + ThumbnailSource::ThumbnailSource(Profile* profile) : DataSource(kThumbnailPath, MessageLoop::current()), profile_(profile) {} @@ -274,6 +286,9 @@ void ThumbnailSource::OnThumbnailDataAvailable( } } +/////////////////////////////////////////////////////////////////////////////// +// FavIconSource + FavIconSource::FavIconSource(Profile* profile) : DataSource(kFavIconPath, MessageLoop::current()), profile_(profile) {} @@ -323,6 +338,10 @@ void FavIconSource::OnFavIconDataAvailable( } } + +/////////////////////////////////////////////////////////////////////////////// +// MostVisitedHandler + MostVisitedHandler::MostVisitedHandler(DOMUIHost* dom_ui_host) : dom_ui_host_(dom_ui_host) { // Register ourselves as the handler for the "mostvisited" message from @@ -391,6 +410,8 @@ void MostVisitedHandler::Observe(NotificationType type, HandleGetMostVisited(NULL); } +/////////////////////////////////////////////////////////////////////////////// +// TemplateURLHandler TemplateURLHandler::TemplateURLHandler(DOMUIHost* dom_ui_host) : dom_ui_host_(dom_ui_host), template_url_model_(NULL) { @@ -419,6 +440,13 @@ void TemplateURLHandler::HandleGetMostSearched(const Value* content) { } } +// A helper function for sorting TemplateURLs where the most used ones show up +// first. +static bool TemplateURLSortByUsage(const TemplateURL* a, + const TemplateURL* b) { + return a->usage_count() > b->usage_count(); +} + void TemplateURLHandler::HandleDoSearch(const Value* content) { // Extract the parameters out of the input list. if (!content || !content->IsType(Value::TYPE_LIST)) { @@ -457,27 +485,44 @@ void TemplateURLHandler::HandleDoSearch(const Value* content) { std::wstring url = url_ref->ReplaceSearchTerms(*template_url, search, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()); - // Load the URL. if (!url.empty()) { + // Load the URL. dom_ui_host_->OpenURL(GURL(WideToUTF8(url)), GURL(), CURRENT_TAB, PageTransition::LINK); - } -} -// A helper function for sorting TemplateURLs where the most used ones show up -// first. -static bool TemplateURLSortByUsage(const TemplateURL* a, - const TemplateURL* b) { - return a->usage_count() > b->usage_count(); + // Record the user action + std::vector<const TemplateURL*> urls = + template_url_model_->GetTemplateURLs(); + sort(urls.begin(), urls.end(), TemplateURLSortByUsage); + ListValue urls_value; + int item_number = 0; + for (size_t i = 0; + i < std::min<size_t>(urls.size(), kSearchURLs); ++i) { + if (urls[i]->usage_count() == 0) + break; // The remainder would be no good. + + const TemplateURLRef* urlref = urls[i]->url(); + if (!urlref) + continue; + + if (urls[i] == template_url) { + UserMetrics::RecordComputedAction( + StringPrintf(L"NTP_SearchURL%d", item_number), + dom_ui_host_->profile()); + break; + } + + item_number++; + } + } } void TemplateURLHandler::OnTemplateURLModelChanged() { // We've loaded some template URLs. Send them to the page. - const int kMaxURLs = 3; // The maximum number of URLs we're willing to send. std::vector<const TemplateURL*> urls = template_url_model_->GetTemplateURLs(); sort(urls.begin(), urls.end(), TemplateURLSortByUsage); ListValue urls_value; - for (size_t i = 0; i < std::min<size_t>(urls.size(), kMaxURLs); ++i) { + for (size_t i = 0; i < std::min<size_t>(urls.size(), kSearchURLs); ++i) { if (urls[i]->usage_count() == 0) break; // urls is sorted by usage count; the remainder would be no good. @@ -494,9 +539,13 @@ void TemplateURLHandler::OnTemplateURLModelChanged() { urls_value.Append(entry_value); } + UMA_HISTOGRAM_COUNTS(L"NewTabPage.SearchURLs.Total", urls_value.GetSize()); dom_ui_host_->CallJavascriptFunction(L"searchURLs", urls_value); } +/////////////////////////////////////////////////////////////////////////////// +// RecentlyBookmarkedHandler + RecentlyBookmarkedHandler::RecentlyBookmarkedHandler(DOMUIHost* dom_ui_host) : dom_ui_host_(dom_ui_host), model_(NULL) { @@ -555,6 +604,9 @@ void RecentlyBookmarkedHandler::BookmarkNodeChanged(BookmarkModel* model, SendBookmarksToPage(); } +/////////////////////////////////////////////////////////////////////////////// +// RecentlyClosedTabsHandler + RecentlyClosedTabsHandler::RecentlyClosedTabsHandler(DOMUIHost* dom_ui_host) : dom_ui_host_(dom_ui_host), tab_restore_service_(NULL) { @@ -571,9 +623,6 @@ RecentlyClosedTabsHandler::~RecentlyClosedTabsHandler() { } void RecentlyClosedTabsHandler::HandleReopenTab(const Value* content) { - UserMetrics::RecordAction(L"NewTabPage_ReopenTab", - dom_ui_host_->profile()); - NavigationController* controller = dom_ui_host_->controller(); Browser* browser = Browser::GetBrowserForController( controller, NULL); @@ -600,6 +649,10 @@ void RecentlyClosedTabsHandler::HandleReopenTab(const Value* content) { for (TabRestoreService::Tabs::const_iterator it = tabs.begin(); it != tabs.end(); ++it) { if (it->id == session_to_restore) { + UserMetrics::RecordComputedAction( + StringPrintf(L"NTP_TabRestored%d", session_to_restore), + dom_ui_host_->profile()); + TabRestoreService* tab_restore_service = tab_restore_service_; browser->ReplaceRestoredTab( it->navigations, it->current_navigation_index); @@ -662,6 +715,9 @@ void RecentlyClosedTabsHandler::TabRestoreServiceDestroyed( tab_restore_service_ = NULL; } +/////////////////////////////////////////////////////////////////////////////// +// HistoryHandler + HistoryHandler::HistoryHandler(DOMUIHost* dom_ui_host) : dom_ui_host_(dom_ui_host) { dom_ui_host->RegisterMessageCallback("showHistoryPage", @@ -672,8 +728,11 @@ HistoryHandler::HistoryHandler(DOMUIHost* dom_ui_host) void HistoryHandler::HandleShowHistoryPage(const Value*) { NavigationController* controller = dom_ui_host_->controller(); - if (controller) + if (controller) { controller->LoadURL(HistoryTabUI::GetURL(), GURL(), PageTransition::LINK); + UserMetrics::RecordAction(L"NTP_ShowHistory", + dom_ui_host_->profile()); + } } void HistoryHandler::HandleSearchHistoryPage(const Value* content) { @@ -686,6 +745,9 @@ void HistoryHandler::HandleSearchHistoryPage(const Value* content) { static_cast<const StringValue*>(list_member); std::wstring wstring_value; if (string_value->GetAsString(&wstring_value)) { + UserMetrics::RecordAction(L"NTP_SearchHistory", + dom_ui_host_->profile()); + NavigationController* controller = dom_ui_host_->controller(); controller->LoadURL( HistoryTabUI::GetHistoryURLWithSearchText(wstring_value), @@ -696,6 +758,34 @@ void HistoryHandler::HandleSearchHistoryPage(const Value* content) { } } +/////////////////////////////////////////////////////////////////////////////// +// MetricsHandler + +MetricsHandler::MetricsHandler(DOMUIHost* dom_ui_host) + : dom_ui_host_(dom_ui_host) { + dom_ui_host->RegisterMessageCallback("metrics", + NewCallback(this, &MetricsHandler::HandleMetrics)); +} + +void MetricsHandler::HandleMetrics(const Value* content) { + if (content && content->GetType() == Value::TYPE_LIST) { + const ListValue* list_value = static_cast<const ListValue*>(content); + Value* list_member; + if (list_value->Get(0, &list_member) && + list_member->GetType() == Value::TYPE_STRING) { + const StringValue* string_value = + static_cast<const StringValue*>(list_member); + std::wstring wstring_value; + if (string_value->GetAsString(&wstring_value)) { + UserMetrics::RecordComputedAction(wstring_value, + dom_ui_host_->profile()); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// NewTabUIContents // This is the top-level URL handler for chrome-internal: URLs, and exposed in // our header file. @@ -728,7 +818,7 @@ NewTabUIContents::NewTabUIContents(Profile* profile, if (profile->IsOffTheRecord()) incognito_ = true; - if (NewTabHTMLSource::first_view() && + if (NewTabHTMLSource::first_view() && (profile->GetPrefs()->GetInteger(prefs::kRestoreOnStartup) != 0 || !profile->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage)) ) { @@ -766,6 +856,7 @@ void NewTabUIContents::AttachMessageHandlers() { AddMessageHandler(new RecentlyBookmarkedHandler(this)); AddMessageHandler(new RecentlyClosedTabsHandler(this)); AddMessageHandler(new HistoryHandler(this)); + AddMessageHandler(new MetricsHandler(this)); NewTabHTMLSource* html_source = new NewTabHTMLSource(); @@ -816,16 +907,4 @@ void NewTabUIContents::RequestOpenURL(const GURL& url, // Note this means we're including clicks on not only most visited thumbnails, // but also clicks on recently bookmarked. OpenURL(url, GURL(), disposition, PageTransition::AUTO_BOOKMARK); - - // Figure out if this was a click on a MostVisited entry, and log it if so. - if (most_visited_handler_) { - const std::vector<GURL>& urls = most_visited_handler_->most_visited_urls(); - for (size_t i = 0; i < urls.size(); ++i) { - if (url == urls[i]) { - UserMetrics::RecordComputedAction(StringPrintf(L"MostVisited%d", i), - profile()); - break; - } - } - } } diff --git a/chrome/browser/dom_ui/new_tab_ui.h b/chrome/browser/dom_ui/new_tab_ui.h index 9c18a60..aab91f2 100644 --- a/chrome/browser/dom_ui/new_tab_ui.h +++ b/chrome/browser/dom_ui/new_tab_ui.h @@ -268,6 +268,24 @@ class HistoryHandler : public DOMMessageHandler { DISALLOW_EVIL_CONSTRUCTORS(HistoryHandler); }; +// Let the page contents record UMA actions. Only use when you can't do it from +// C++. For example, we currently use it to let the NTP log the postion of the +// Most Visited or Bookmark the user clicked on, as we don't get that +// information through RequestOpenURL. You will need to update the metrics +// dashboard with the action names you use, as our processor won't catch that +// information (treat it as RecordComputedMetrics) +class MetricsHandler : public DOMMessageHandler { + public: + explicit MetricsHandler(DOMUIHost* dom_ui_host); + + // Callback which records a user action. + void HandleMetrics(const Value* content); + + private: + DOMUIHost* dom_ui_host_; + DISALLOW_EVIL_CONSTRUCTORS(MetricsHandler); +}; + // The TabContents used for the New Tab page. class NewTabUIContents : public DOMUIHost { public: diff --git a/chrome/browser/resources/new_tab.html b/chrome/browser/resources/new_tab.html index 1372ba5..356976b 100644 --- a/chrome/browser/resources/new_tab.html +++ b/chrome/browser/resources/new_tab.html @@ -393,7 +393,7 @@ function DOM(elem, attrs) { /* Return the DOM element for a "most visited" entry. |page| should be an object with "title" and "url" fields. */ -function makeMostVisitedDOM(page) { +function makeMostVisitedDOM(page, number) { /* The HTML we want looks like this: <a class="most-visited-item" href="URL" title="gmail.com"> <div class="thumbnail-title" style="background-image:url(faviconurl);">gmail.com</div> @@ -402,7 +402,11 @@ function makeMostVisitedDOM(page) { */ var root; if (page.url) { - root = DOM('a', {href:page.url, title:page.title}); + root = DOM('a', {href:page.url, + title:page.title}); + root.addEventListener("mousedown", function(event) { + chrome.send("metrics", ["NTP_MostVisited" + number]) + }, false); } else { // Something went wrong; don't make it clickable. root = DOM('span'); @@ -457,7 +461,7 @@ function renderMostVisitedPages(pages) { rows[rowNum] = DOM('tr', {}); } - var dom = makeMostVisitedDOM(page); + var dom = makeMostVisitedDOM(page, i); var cell = DOM('td'); cell.appendChild(dom); @@ -543,7 +547,12 @@ function renderRecentlyBookmarked(entries) { if (entries.length > 0) { section.style.display = 'block'; for (var i = 0, entry = entries[0]; entry = entries[i]; ++i) { - var link = DOM('a', {href: entry.url, className:'recent-bookmark', title:entry.title}); + var link = DOM('a', {href: entry.url, + className:'recent-bookmark', + title:entry.title}); + link.addEventListener("mousedown", function(event) { + chrome.send("metrics", ["NTP_Bookmark" + i]) + }, false); link.style.backgroundImage = 'url("chrome-resource://favicon/' + entry.url + '")'; link.appendChild(document.createTextNode(entry.title)); |