15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/google/google_search_counter.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/google/core/browser/google_search_metrics.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_details.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockSearchMetrics : public GoogleSearchMetrics {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_CONST_METHOD1(RecordGoogleSearch,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void(GoogleSearchMetrics::AccessPoint ap));
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GoogleSearchCounterTest : public testing::Test {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GoogleSearchCounterTest();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~GoogleSearchCounterTest();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test if |url| is a Google search for specific types. When |is_omnibox| is
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, this method will append Omnibox identifiers to the simulated URL
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // navigation. If |expected_metric| is set and not AP_BOUNDARY, we'll also use
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Search Metrics mock class to ensure that the type of metric recorded is
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // correct. Note that when |expected_metric| is AP_BOUNDARY, we strictly
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // forbid any metrics from being logged at all. See implementation below for
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // details.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestGoogleSearch(const std::string& url,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        bool is_omnibox,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        GoogleSearchMetrics::AccessPoint expected_metric);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectMetricsLogged(GoogleSearchMetrics::AccessPoint ap);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Weak ptr. Actual instance owned by GoogleSearchCounter.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::testing::StrictMock<MockSearchMetrics>* mock_search_metrics_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleSearchCounterTest::GoogleSearchCounterTest()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : mock_search_metrics_(NULL) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GoogleSearchCounterTest::~GoogleSearchCounterTest() {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GoogleSearchCounterTest::SetUp() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep a weak ptr to MockSearchMetrics so we can run expectations. The
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GoogleSearchCounter singleton will own and clean up MockSearchMetrics.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_search_metrics_ = new ::testing::StrictMock<MockSearchMetrics>;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GoogleSearchCounter::GetInstance()->SetSearchMetricsForTesting(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mock_search_metrics_);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GoogleSearchCounterTest::TearDown() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_search_metrics_ = NULL;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GoogleSearchCounterTest::TestGoogleSearch(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& url,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_omnibox,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GoogleSearchMetrics::AccessPoint expected_metric) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::LoadCommittedDetails details;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<content::NavigationEntry> entry(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NavigationEntry::Create());
786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (is_omnibox) {
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entry->SetTransitionType(ui::PageTransitionFromInt(
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ui::PAGE_TRANSITION_GENERATED |
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->SetURL(GURL(url));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details.entry = entry.get();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the internal mocked metrics object is strict, if |expect_metrics| is
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // false, the absence of this call to ExpectMetricsLogged will be noticed and
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cause the test to complain, as expected. We use this behaviour to test
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // negative test cases (such as bad searches).
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (expected_metric != GoogleSearchMetrics::AP_BOUNDARY)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectMetricsLogged(expected_metric);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now we don't care about the notification source, but when we start
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // listening for additional access points, we will have to pass in a valid
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // controller.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GoogleSearchCounter::GetInstance()->Observe(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<content::NavigationController>(NULL),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::LoadCommittedDetails>(&details));
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GoogleSearchCounterTest::ExpectMetricsLogged(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GoogleSearchMetrics::AccessPoint ap) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*mock_search_metrics_, RecordGoogleSearch(ap)).Times(1);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, EmptySearch) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch(std::string(), false, GoogleSearchMetrics::AP_BOUNDARY);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, GoodOmniboxSearch) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/search?q=something", true,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   GoogleSearchMetrics::AP_OMNIBOX);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, BadOmniboxSearch) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/search?other=something", true,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   GoogleSearchMetrics::AP_BOUNDARY);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, EmptyOmniboxSearch) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch(std::string(), true, GoogleSearchMetrics::AP_BOUNDARY);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, GoodOtherSearch) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/search?q=something", false,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   GoogleSearchMetrics::AP_OTHER);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, BadOtherSearch) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/search?other=something", false,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   GoogleSearchMetrics::AP_BOUNDARY);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, SearchAppSearch) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/webhp?source=search_app#q=something",
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   false, GoogleSearchMetrics::AP_SEARCH_APP);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GoogleSearchCounterTest, SearchAppStart) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starting the search app takes you to this URL, but it should not be
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // considered an actual search event. Note that this URL is not considered an
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actual search because it has no query string parameter ("q").
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGoogleSearch("http://www.google.com/webhp?source=search_app",
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   false, GoogleSearchMetrics::AP_BOUNDARY);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(stevet): Add a regression test to protect against the particular
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bad-flags handling case that asvitkine pointed out.
150