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/uma_browsing_activity_observer.h"
6
7#include "base/metrics/histogram.h"
8#include "chrome/browser/chrome_notification_types.h"
9#include "chrome/browser/search_engines/template_url_service.h"
10#include "chrome/browser/search_engines/template_url_service_factory.h"
11#include "chrome/browser/ui/browser.h"
12#include "chrome/browser/ui/browser_finder.h"
13#include "chrome/browser/ui/browser_iterator.h"
14#include "chrome/browser/ui/browser_window.h"
15#include "chrome/browser/ui/tabs/tab_strip_model.h"
16#include "content/public/browser/navigation_controller.h"
17#include "content/public/browser/navigation_details.h"
18#include "content/public/browser/navigation_entry.h"
19#include "content/public/browser/notification_service.h"
20#include "content/public/browser/render_process_host.h"
21#include "content/public/browser/user_metrics.h"
22
23namespace chrome {
24namespace {
25
26UMABrowsingActivityObserver* g_instance = NULL;
27
28}  // namespace
29
30// static
31void UMABrowsingActivityObserver::Init() {
32  DCHECK(!g_instance);
33  // Must be created before any Browsers are.
34  DCHECK_EQ(0U, chrome::GetTotalBrowserCount());
35  g_instance = new UMABrowsingActivityObserver;
36}
37
38UMABrowsingActivityObserver::UMABrowsingActivityObserver() {
39  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
40                  content::NotificationService::AllSources());
41  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
42                  content::NotificationService::AllSources());
43}
44
45UMABrowsingActivityObserver::~UMABrowsingActivityObserver() {
46}
47
48void UMABrowsingActivityObserver::Observe(
49    int type,
50    const content::NotificationSource& source,
51    const content::NotificationDetails& details) {
52  if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
53    const content::LoadCommittedDetails load =
54        *content::Details<content::LoadCommittedDetails>(details).ptr();
55
56    content::NavigationController* controller =
57      content::Source<content::NavigationController>(source).ptr();
58    // Track whether the page loaded is a search results page (SRP). Track
59    // the non-SRP navigations as well so there is a control.
60    content::RecordAction(content::UserMetricsAction("NavEntryCommitted"));
61    // Attempting to determine the cause of a crash originating from
62    // IsSearchResultsPageFromDefaultSearchProvider but manifesting in
63    // TemplateURLRef::ExtractSearchTermsFromURL(...).
64    // See http://crbug.com/291348.
65    CHECK(load.entry);
66    if (TemplateURLServiceFactory::GetForProfile(
67            Profile::FromBrowserContext(controller->GetBrowserContext()))->
68            IsSearchResultsPageFromDefaultSearchProvider(
69                load.entry->GetURL())) {
70      content::RecordAction(
71          content::UserMetricsAction("NavEntryCommitted.SRP"));
72    }
73
74    if (!load.is_navigation_to_different_page())
75      return;  // Don't log for subframes or other trivial types.
76
77    LogRenderProcessHostCount();
78    LogBrowserTabCount();
79  } else if (type == chrome::NOTIFICATION_APP_TERMINATING) {
80    delete g_instance;
81    g_instance = NULL;
82  }
83}
84
85void UMABrowsingActivityObserver::LogRenderProcessHostCount() const {
86  int hosts_count = 0;
87  for (content::RenderProcessHost::iterator i(
88          content::RenderProcessHost::AllHostsIterator());
89        !i.IsAtEnd(); i.Advance())
90    ++hosts_count;
91  UMA_HISTOGRAM_CUSTOM_COUNTS("MPArch.RPHCountPerLoad", hosts_count,
92                              1, 50, 50);
93}
94
95void UMABrowsingActivityObserver::LogBrowserTabCount() const {
96  int tab_count = 0;
97  int app_window_count = 0;
98  int popup_window_count = 0;
99  int tabbed_window_count = 0;
100  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
101    // Record how many tabs each window has open.
102    Browser* browser = *it;
103    UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerWindow",
104                                browser->tab_strip_model()->count(),
105                                1, 200, 50);
106    tab_count += browser->tab_strip_model()->count();
107
108    if (browser->window()->IsActive()) {
109      // Record how many tabs the active window has open.
110      UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountActiveWindow",
111                                  browser->tab_strip_model()->count(),
112                                  1, 200, 50);
113    }
114
115    if (browser->is_app())
116      app_window_count++;
117    else if (browser->is_type_popup())
118      popup_window_count++;
119    else if (browser->is_type_tabbed())
120      tabbed_window_count++;
121  }
122  // Record how many tabs total are open (across all windows).
123  UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tab_count, 1, 200, 50);
124
125  // Record how many windows are open, by type.
126  UMA_HISTOGRAM_COUNTS_100("WindowManager.AppWindowCountPerLoad",
127                           app_window_count);
128  UMA_HISTOGRAM_COUNTS_100("WindowManager.PopUpWindowCountPerLoad",
129                           popup_window_count);
130  UMA_HISTOGRAM_COUNTS_100("WindowManager.TabbedWindowCountPerLoad",
131                           tabbed_window_count);
132}
133
134}  // namespace chrome
135