• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/google/google_search_counter.h"
6 
7 #include "base/logging.h"
8 #include "chrome/browser/google/google_util.h"
9 #include "content/public/browser/navigation_controller.h"
10 #include "content/public/browser/navigation_details.h"
11 #include "content/public/browser/navigation_entry.h"
12 #include "content/public/browser/notification_service.h"
13 #include "content/public/browser/notification_types.h"
14 
15 namespace {
16 
17 // Returns true iff |entry| represents a Google search from the Omnibox.
18 // This method assumes that we have already verified that |entry|'s URL is a
19 // Google search URL.
IsOmniboxGoogleSearchNavigation(const content::NavigationEntry & entry)20 bool IsOmniboxGoogleSearchNavigation(const content::NavigationEntry& entry) {
21   const content::PageTransition stripped_transition =
22       PageTransitionStripQualifier(entry.GetTransitionType());
23   DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL()));
24   return stripped_transition == content::PAGE_TRANSITION_GENERATED;
25 }
26 
27 // Returns true iff |entry| represents a Google search from the Google Search
28 // App. This method assumes that we have already verified that |entry|'s URL is
29 // a Google search URL.
IsSearchAppGoogleSearchNavigation(const content::NavigationEntry & entry)30 bool IsSearchAppGoogleSearchNavigation(const content::NavigationEntry& entry) {
31   DCHECK(google_util::IsGoogleSearchUrl(entry.GetURL()));
32   return entry.GetURL().query().find("source=search_app") !=
33          std::string::npos;
34 }
35 
36 }  // namespace
37 
38 // static
RegisterForNotifications()39 void GoogleSearchCounter::RegisterForNotifications() {
40   GoogleSearchCounter::GetInstance()->RegisterForNotificationsInternal();
41 }
42 
43 // static
GetInstance()44 GoogleSearchCounter* GoogleSearchCounter::GetInstance() {
45   return Singleton<GoogleSearchCounter>::get();
46 }
47 
GoogleSearchCounter()48 GoogleSearchCounter::GoogleSearchCounter()
49     : search_metrics_(new GoogleSearchMetrics) {
50 }
51 
~GoogleSearchCounter()52 GoogleSearchCounter::~GoogleSearchCounter() {
53 }
54 
ProcessCommittedEntry(const content::NotificationSource & source,const content::NotificationDetails & details)55 void GoogleSearchCounter::ProcessCommittedEntry(
56     const content::NotificationSource& source,
57     const content::NotificationDetails& details) {
58   const content::LoadCommittedDetails* commit =
59       content::Details<content::LoadCommittedDetails>(details).ptr();
60   const content::NavigationEntry& entry = *commit->entry;
61 
62   // First see if this is a Google search URL at all.
63   if (!google_util::IsGoogleSearchUrl(entry.GetURL()))
64     return;
65 
66   // If the commit is a GENERATED commit with a Google search URL, we know it's
67   // an Omnibox search.
68   if (IsOmniboxGoogleSearchNavigation(entry)) {
69     // Note that GoogleSearchMetrics logs metrics through UMA, which will only
70     // transmit these counts to the server if the user has opted into sending
71     // usage stats.
72     search_metrics_->RecordGoogleSearch(GoogleSearchMetrics::AP_OMNIBOX);
73   } else if (IsSearchAppGoogleSearchNavigation(entry)) {
74     search_metrics_->RecordGoogleSearch(GoogleSearchMetrics::AP_SEARCH_APP);
75   } else {
76     // For all other cases that we have not yet implemented or care to measure,
77     // we log a generic "catch-all" metric.
78     search_metrics_->RecordGoogleSearch(GoogleSearchMetrics::AP_OTHER);
79   }
80 }
81 
SetSearchMetricsForTesting(GoogleSearchMetrics * search_metrics)82 void GoogleSearchCounter::SetSearchMetricsForTesting(
83     GoogleSearchMetrics* search_metrics) {
84   DCHECK(search_metrics);
85   search_metrics_.reset(search_metrics);
86 }
87 
RegisterForNotificationsInternal()88 void GoogleSearchCounter::RegisterForNotificationsInternal() {
89   // We always listen for all COMMITTED navigations from all sources, as any
90   // one of them could be a navigation of interest.
91   registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
92                  content::NotificationService::AllSources());
93 }
94 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)95 void GoogleSearchCounter::Observe(int type,
96                                   const content::NotificationSource& source,
97                                   const content::NotificationDetails& details) {
98   switch (type) {
99     case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
100       ProcessCommittedEntry(source, details);
101       break;
102     default:
103       NOTREACHED();
104   }
105 }
106