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