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.
5 #include "chrome/browser/google/google_search_counter.h"
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"
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
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
;
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.
30 bool IsSearchAppGoogleSearchNavigation(const content::NavigationEntry
& entry
) {
31 DCHECK(google_util::IsGoogleSearchUrl(entry
.GetURL()));
32 return entry
.GetURL().query().find("source=search_app") !=
39 void GoogleSearchCounter::RegisterForNotifications() {
40 GoogleSearchCounter::GetInstance()->RegisterForNotificationsInternal();
44 GoogleSearchCounter
* GoogleSearchCounter::GetInstance() {
45 return Singleton
<GoogleSearchCounter
>::get();
48 GoogleSearchCounter::GoogleSearchCounter()
49 : search_metrics_(new GoogleSearchMetrics
) {
52 GoogleSearchCounter::~GoogleSearchCounter() {
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
;
62 // First see if this is a Google search URL at all.
63 if (!google_util::IsGoogleSearchUrl(entry
.GetURL()))
66 // If the commit is a GENERATED commit with a Google search URL, we know it's
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
72 search_metrics_
->RecordGoogleSearch(GoogleSearchMetrics::AP_OMNIBOX
);
73 } else if (IsSearchAppGoogleSearchNavigation(entry
)) {
74 search_metrics_
->RecordGoogleSearch(GoogleSearchMetrics::AP_SEARCH_APP
);
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
);
82 void GoogleSearchCounter::SetSearchMetricsForTesting(
83 GoogleSearchMetrics
* search_metrics
) {
84 DCHECK(search_metrics
);
85 search_metrics_
.reset(search_metrics
);
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());
95 void GoogleSearchCounter::Observe(int type
,
96 const content::NotificationSource
& source
,
97 const content::NotificationDetails
& details
) {
99 case content::NOTIFICATION_NAV_ENTRY_COMMITTED
:
100 ProcessCommittedEntry(source
, details
);