普通文本  |  462行  |  15.47 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/google/google_url_tracker.h"

#include "base/command_line.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/common/net/test_url_fetcher_factory.h"
#include "chrome/common/net/url_fetcher.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_browser_process.h"
#include "chrome/test/testing_pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

// TestNotificationObserver ---------------------------------------------------

namespace {

class TestNotificationObserver : public NotificationObserver {
 public:
  TestNotificationObserver();
  virtual ~TestNotificationObserver();

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);
  bool notified() const { return notified_; }
  void clear_notified() { notified_ = false; }

 private:
  bool notified_;
};

TestNotificationObserver::TestNotificationObserver() : notified_(false) {
}

TestNotificationObserver::~TestNotificationObserver() {
}

void TestNotificationObserver::Observe(NotificationType type,
                                       const NotificationSource& source,
                                       const NotificationDetails& details) {
  notified_ = true;
}


// TestInfoBarDelegate --------------------------------------------------------

class TestInfoBarDelegate : public InfoBarDelegate {
 public:
  TestInfoBarDelegate(GoogleURLTracker* google_url_tracker,
                      const GURL& new_google_url);

  GoogleURLTracker* google_url_tracker() const { return google_url_tracker_; }
  GURL new_google_url() const { return new_google_url_; }

 private:
  virtual ~TestInfoBarDelegate();

  // InfoBarDelegate:
  virtual InfoBar* CreateInfoBar();

  GoogleURLTracker* google_url_tracker_;
  GURL new_google_url_;
};

TestInfoBarDelegate::TestInfoBarDelegate(GoogleURLTracker* google_url_tracker,
                                         const GURL& new_google_url)
    : InfoBarDelegate(NULL),
      google_url_tracker_(google_url_tracker),
      new_google_url_(new_google_url) {
}

TestInfoBarDelegate::~TestInfoBarDelegate() {
}

InfoBar* TestInfoBarDelegate::CreateInfoBar() {
  return NULL;
}

InfoBarDelegate* CreateTestInfobar(
    TabContents* tab_contents,
    GoogleURLTracker* google_url_tracker,
    const GURL& new_google_url) {
  return new TestInfoBarDelegate(google_url_tracker, new_google_url);
}

}  // namespace


// GoogleURLTrackerTest -------------------------------------------------------

class GoogleURLTrackerTest : public testing::Test {
 protected:
  GoogleURLTrackerTest();
  virtual ~GoogleURLTrackerTest();

  // testing::Test
  virtual void SetUp();
  virtual void TearDown();

  TestURLFetcher* GetFetcherByID(int expected_id);
  void MockSearchDomainCheckResponse(int expected_id,
                                     const std::string& domain);
  void RequestServerCheck();
  void FinishSleep();
  void NotifyIPAddressChanged();
  GURL GetFetchedGoogleURL();
  void SetGoogleURL(const GURL& url);
  void SetLastPromptedGoogleURL(const GURL& url);
  GURL GetLastPromptedGoogleURL();
  void SearchCommitted(const GURL& search_url);
  void NavEntryCommitted();
  bool InfoBarIsShown();
  GURL GetInfoBarShowingURL();
  void AcceptGoogleURL();
  void CancelGoogleURL();
  void InfoBarClosed();
  void ExpectDefaultURLs();

  scoped_ptr<TestNotificationObserver> observer_;

 private:
  MessageLoop* message_loop_;
  BrowserThread* io_thread_;
  scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
  TestingPrefService local_state_;

  TestURLFetcherFactory fetcher_factory_;
  NotificationRegistrar registrar_;
};

GoogleURLTrackerTest::GoogleURLTrackerTest()
    : observer_(new TestNotificationObserver),
      message_loop_(NULL),
      io_thread_(NULL) {
}

GoogleURLTrackerTest::~GoogleURLTrackerTest() {
}

void GoogleURLTrackerTest::SetUp() {
  message_loop_ = new MessageLoop(MessageLoop::TYPE_IO);
  io_thread_ = new BrowserThread(BrowserThread::IO, message_loop_);
  network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
  browser::RegisterLocalState(&local_state_);
  TestingBrowserProcess* testing_browser_process =
      static_cast<TestingBrowserProcess*>(g_browser_process);
  testing_browser_process->SetPrefService(&local_state_);
  GoogleURLTracker* tracker = new GoogleURLTracker;
  tracker->queue_wakeup_task_ = false;
  MessageLoop::current()->RunAllPending();
  testing_browser_process->SetGoogleURLTracker(tracker);

  URLFetcher::set_factory(&fetcher_factory_);
  g_browser_process->google_url_tracker()->infobar_creator_ =
      &CreateTestInfobar;
}

void GoogleURLTrackerTest::TearDown() {
  URLFetcher::set_factory(NULL);
  TestingBrowserProcess* testing_browser_process =
      static_cast<TestingBrowserProcess*>(g_browser_process);
  testing_browser_process->SetGoogleURLTracker(NULL);
  testing_browser_process->SetPrefService(NULL);
  network_change_notifier_.reset();
  delete io_thread_;
  delete message_loop_;
}

TestURLFetcher* GoogleURLTrackerTest::GetFetcherByID(int expected_id) {
  return fetcher_factory_.GetFetcherByID(expected_id);
}

void GoogleURLTrackerTest::MockSearchDomainCheckResponse(
    int expected_id,
    const std::string& domain) {
  TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(expected_id);
  if (!fetcher)
    return;
  fetcher->delegate()->OnURLFetchComplete(fetcher,
      GURL(GoogleURLTracker::kSearchDomainCheckURL), net::URLRequestStatus(),
      200, ResponseCookies(), domain);
  // At this point, |fetcher| is deleted.
  MessageLoop::current()->RunAllPending();
}

void GoogleURLTrackerTest::RequestServerCheck() {
  if (!registrar_.IsRegistered(observer_.get(),
                               NotificationType::GOOGLE_URL_UPDATED,
                               NotificationService::AllSources())) {
    registrar_.Add(observer_.get(), NotificationType::GOOGLE_URL_UPDATED,
                   NotificationService::AllSources());
  }
  GoogleURLTracker::RequestServerCheck();
  MessageLoop::current()->RunAllPending();
}

void GoogleURLTrackerTest::FinishSleep() {
  g_browser_process->google_url_tracker()->FinishSleep();
  MessageLoop::current()->RunAllPending();
}

void GoogleURLTrackerTest::NotifyIPAddressChanged() {
  net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
  MessageLoop::current()->RunAllPending();
}

GURL GoogleURLTrackerTest::GetFetchedGoogleURL() {
  return g_browser_process->google_url_tracker()->fetched_google_url_;
}

void GoogleURLTrackerTest::SetGoogleURL(const GURL& url) {
  g_browser_process->google_url_tracker()->google_url_ = url;
}

void GoogleURLTrackerTest::SetLastPromptedGoogleURL(const GURL& url) {
  g_browser_process->local_state()->SetString(
      prefs::kLastPromptedGoogleURL, url.spec());
}

GURL GoogleURLTrackerTest::GetLastPromptedGoogleURL() {
  return GURL(g_browser_process->local_state()->GetString(
      prefs::kLastPromptedGoogleURL));
}

void GoogleURLTrackerTest::SearchCommitted(const GURL& search_url) {
  GoogleURLTracker* google_url_tracker =
      g_browser_process->google_url_tracker();
  google_url_tracker->SearchCommitted();
  if (google_url_tracker->registrar_.IsRegistered(google_url_tracker,
      NotificationType::NAV_ENTRY_PENDING,
      NotificationService::AllSources()))
    google_url_tracker->search_url_ = search_url;
}

void GoogleURLTrackerTest::NavEntryCommitted() {
  GoogleURLTracker* google_url_tracker =
      g_browser_process->google_url_tracker();
  google_url_tracker->ShowGoogleURLInfoBarIfNecessary(NULL);
}

bool GoogleURLTrackerTest::InfoBarIsShown() {
  return (g_browser_process->google_url_tracker()->infobar_ != NULL);
}

GURL GoogleURLTrackerTest::GetInfoBarShowingURL() {
  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
      g_browser_process->google_url_tracker()->infobar_);
  return infobar->new_google_url();
}

void GoogleURLTrackerTest::AcceptGoogleURL() {
  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
      g_browser_process->google_url_tracker()->infobar_);
  ASSERT_TRUE(infobar);
  ASSERT_TRUE(infobar->google_url_tracker());
  infobar->google_url_tracker()->AcceptGoogleURL(infobar->new_google_url());
}

void GoogleURLTrackerTest::CancelGoogleURL() {
  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
      g_browser_process->google_url_tracker()->infobar_);
  ASSERT_TRUE(infobar);
  ASSERT_TRUE(infobar->google_url_tracker());
  infobar->google_url_tracker()->CancelGoogleURL(infobar->new_google_url());
}

void GoogleURLTrackerTest::InfoBarClosed() {
  InfoBarDelegate* infobar = g_browser_process->google_url_tracker()->infobar_;
  ASSERT_TRUE(infobar);
  GoogleURLTracker* url_tracker =
      static_cast<TestInfoBarDelegate*>(infobar)->google_url_tracker();
  ASSERT_TRUE(url_tracker);
  url_tracker->InfoBarClosed();
  delete infobar;
}

void GoogleURLTrackerTest::ExpectDefaultURLs() {
  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
            GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL(), GetFetchedGoogleURL());
}


// Tests ----------------------------------------------------------------------

TEST_F(GoogleURLTrackerTest, DontFetchWhenNoOneRequestsCheck) {
  ExpectDefaultURLs();
  FinishSleep();
  // No one called RequestServerCheck() so nothing should have happened.
  EXPECT_FALSE(GetFetcherByID(0));
  ExpectDefaultURLs();
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, UpdateOnFirstRun) {
  RequestServerCheck();
  EXPECT_FALSE(GetFetcherByID(0));
  ExpectDefaultURLs();
  EXPECT_FALSE(observer_->notified());

  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  // GoogleURL should be updated, becase there was no last prompted URL.
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_TRUE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, DontUpdateWhenUnchanged) {
  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));

  RequestServerCheck();
  EXPECT_FALSE(GetFetcherByID(0));
  ExpectDefaultURLs();
  EXPECT_FALSE(observer_->notified());

  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  // GoogleURL should not be updated, because the fetched and prompted URLs
  // match.
  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
            GoogleURLTracker::GoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, UpdatePromptedURLOnReturnToPreviousLocation) {
  SetLastPromptedGoogleURL(GURL("http://www.google.co.jp/"));
  SetGoogleURL(GURL("http://www.google.co.uk/"));
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, RefetchOnIPAddressChange) {
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_TRUE(observer_->notified());
  observer_->clear_notified();

  NotifyIPAddressChanged();
  MockSearchDomainCheckResponse(1, ".google.co.in");
  EXPECT_EQ(GURL("http://www.google.co.in/"), GetFetchedGoogleURL());
  // Just fetching a new URL shouldn't reset things without a prompt.
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, DontRefetchWhenNoOneRequestsCheck) {
  FinishSleep();
  NotifyIPAddressChanged();
  // No one called RequestServerCheck() so nothing should have happened.
  EXPECT_FALSE(GetFetcherByID(0));
  ExpectDefaultURLs();
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, FetchOnLateRequest) {
  FinishSleep();
  NotifyIPAddressChanged();

  RequestServerCheck();
  // The first request for a check should trigger a fetch if it hasn't happened
  // already.
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_TRUE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, SearchingDoesNothingIfNoNeedToPrompt) {
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.uk");
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
  EXPECT_TRUE(observer_->notified());
  observer_->clear_notified();

  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
  NavEntryCommitted();
  EXPECT_FALSE(InfoBarIsShown());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, InfobarClosed) {
  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.jp");

  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
  NavEntryCommitted();
  EXPECT_TRUE(InfoBarIsShown());

  InfoBarClosed();
  EXPECT_FALSE(InfoBarIsShown());
  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
            GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, InfobarRefused) {
  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.jp");

  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
  NavEntryCommitted();
  EXPECT_TRUE(InfoBarIsShown());

  CancelGoogleURL();
  InfoBarClosed();
  EXPECT_FALSE(InfoBarIsShown());
  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
            GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL());
  EXPECT_FALSE(observer_->notified());
}

TEST_F(GoogleURLTrackerTest, InfobarAccepted) {
  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
  RequestServerCheck();
  FinishSleep();
  MockSearchDomainCheckResponse(0, ".google.co.jp");

  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
  NavEntryCommitted();
  EXPECT_TRUE(InfoBarIsShown());

  AcceptGoogleURL();
  InfoBarClosed();
  EXPECT_FALSE(InfoBarIsShown());
  EXPECT_EQ(GURL("http://www.google.co.jp/"), GoogleURLTracker::GoogleURL());
  EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL());
  EXPECT_TRUE(observer_->notified());
}