google_search_counter.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 15namespace { 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. 20bool 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. 30bool 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 39void GoogleSearchCounter::RegisterForNotifications() { 40 GoogleSearchCounter::GetInstance()->RegisterForNotificationsInternal(); 41} 42 43// static 44GoogleSearchCounter* GoogleSearchCounter::GetInstance() { 45 return Singleton<GoogleSearchCounter>::get(); 46} 47 48GoogleSearchCounter::GoogleSearchCounter() 49 : search_metrics_(new GoogleSearchMetrics) { 50} 51 52GoogleSearchCounter::~GoogleSearchCounter() { 53} 54 55void 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 82void GoogleSearchCounter::SetSearchMetricsForTesting( 83 GoogleSearchMetrics* search_metrics) { 84 DCHECK(search_metrics); 85 search_metrics_.reset(search_metrics); 86} 87 88void 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 95void 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