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/metrics_handler.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/logging.h" 10 #include "base/metrics/histogram.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/metrics/metric_event_duration_details.h" 15 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" 16 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h" 17 #include "chrome/common/ntp_logging_events.h" 18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/user_metrics.h" 20 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_ui.h" 22 23 using base::ListValue; 24 using base::UserMetricsAction; 25 using content::WebContents; 26 27 MetricsHandler::MetricsHandler() {} 28 MetricsHandler::~MetricsHandler() {} 29 30 void MetricsHandler::RegisterMessages() { 31 web_ui()->RegisterMessageCallback( 32 "metricsHandler:recordAction", 33 base::Bind(&MetricsHandler::HandleRecordAction, base::Unretained(this))); 34 web_ui()->RegisterMessageCallback( 35 "metricsHandler:recordInHistogram", 36 base::Bind(&MetricsHandler::HandleRecordInHistogram, 37 base::Unretained(this))); 38 web_ui()->RegisterMessageCallback( 39 "metricsHandler:logEventTime", 40 base::Bind(&MetricsHandler::HandleLogEventTime, base::Unretained(this))); 41 web_ui()->RegisterMessageCallback( 42 "metricsHandler:logMouseover", 43 base::Bind(&MetricsHandler::HandleLogMouseover, base::Unretained(this))); 44 } 45 46 void MetricsHandler::HandleRecordAction(const base::ListValue* args) { 47 std::string string_action = base::UTF16ToUTF8(ExtractStringValue(args)); 48 content::RecordComputedAction(string_action); 49 } 50 51 void MetricsHandler::HandleRecordInHistogram(const base::ListValue* args) { 52 std::string histogram_name; 53 double value; 54 double boundary_value; 55 if (!args->GetString(0, &histogram_name) || 56 !args->GetDouble(1, &value) || 57 !args->GetDouble(2, &boundary_value)) { 58 NOTREACHED(); 59 return; 60 } 61 62 int int_value = static_cast<int>(value); 63 int int_boundary_value = static_cast<int>(boundary_value); 64 if (int_boundary_value >= 4000 || 65 int_value > int_boundary_value || 66 int_value < 0) { 67 NOTREACHED(); 68 return; 69 } 70 71 int bucket_count = int_boundary_value; 72 while (bucket_count >= 100) { 73 bucket_count /= 10; 74 } 75 76 // As |histogram_name| may change between calls, the UMA_HISTOGRAM_ENUMERATION 77 // macro cannot be used here. 78 base::HistogramBase* counter = 79 base::LinearHistogram::FactoryGet( 80 histogram_name, 1, int_boundary_value, bucket_count + 1, 81 base::HistogramBase::kUmaTargetedHistogramFlag); 82 counter->Add(int_value); 83 } 84 85 void MetricsHandler::HandleLogEventTime(const base::ListValue* args) { 86 std::string event_name = base::UTF16ToUTF8(ExtractStringValue(args)); 87 WebContents* tab = web_ui()->GetWebContents(); 88 89 // Not all new tab pages get timed. In those cases, we don't have a 90 // new_tab_start_time_. 91 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(tab); 92 if (core_tab_helper->new_tab_start_time().is_null()) 93 return; 94 95 base::TimeDelta duration = 96 base::TimeTicks::Now() - core_tab_helper->new_tab_start_time(); 97 MetricEventDurationDetails details(event_name, 98 static_cast<int>(duration.InMilliseconds())); 99 100 if (event_name == "Tab.NewTabScriptStart") { 101 UMA_HISTOGRAM_TIMES("Tab.NewTabScriptStart", duration); 102 } else if (event_name == "Tab.NewTabDOMContentLoaded") { 103 UMA_HISTOGRAM_TIMES("Tab.NewTabDOMContentLoaded", duration); 104 } else if (event_name == "Tab.NewTabOnload") { 105 UMA_HISTOGRAM_TIMES("Tab.NewTabOnload", duration); 106 // The new tab page has finished loading; reset it. 107 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(tab); 108 core_tab_helper->set_new_tab_start_time(base::TimeTicks()); 109 } else { 110 NOTREACHED(); 111 } 112 content::NotificationService::current()->Notify( 113 chrome::NOTIFICATION_METRIC_EVENT_DURATION, 114 content::Source<WebContents>(tab), 115 content::Details<MetricEventDurationDetails>(&details)); 116 } 117 118 void MetricsHandler::HandleLogMouseover(const base::ListValue* args) { 119 #if !defined(OS_ANDROID) 120 // Android uses native UI for NTP. 121 NTPUserDataLogger::GetOrCreateFromWebContents( 122 web_ui()->GetWebContents())->LogEvent(NTP_MOUSEOVER); 123 #endif // !defined(OS_ANDROID) 124 } 125