1// Copyright (c) 2011 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_url_tracker.h"
6
7#include "base/command_line.h"
8#include "base/message_loop.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/prefs/browser_prefs.h"
11#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
12#include "chrome/common/net/test_url_fetcher_factory.h"
13#include "chrome/common/net/url_fetcher.h"
14#include "chrome/common/pref_names.h"
15#include "chrome/test/testing_browser_process.h"
16#include "chrome/test/testing_pref_service.h"
17#include "content/browser/browser_thread.h"
18#include "content/common/notification_service.h"
19#include "net/url_request/url_request.h"
20#include "net/url_request/url_request_context_getter.h"
21#include "net/url_request/url_request_test_util.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24// TestNotificationObserver ---------------------------------------------------
25
26namespace {
27
28class TestNotificationObserver : public NotificationObserver {
29 public:
30  TestNotificationObserver();
31  virtual ~TestNotificationObserver();
32
33  virtual void Observe(NotificationType type,
34                       const NotificationSource& source,
35                       const NotificationDetails& details);
36  bool notified() const { return notified_; }
37  void clear_notified() { notified_ = false; }
38
39 private:
40  bool notified_;
41};
42
43TestNotificationObserver::TestNotificationObserver() : notified_(false) {
44}
45
46TestNotificationObserver::~TestNotificationObserver() {
47}
48
49void TestNotificationObserver::Observe(NotificationType type,
50                                       const NotificationSource& source,
51                                       const NotificationDetails& details) {
52  notified_ = true;
53}
54
55
56// TestInfoBarDelegate --------------------------------------------------------
57
58class TestInfoBarDelegate : public InfoBarDelegate {
59 public:
60  TestInfoBarDelegate(GoogleURLTracker* google_url_tracker,
61                      const GURL& new_google_url);
62
63  GoogleURLTracker* google_url_tracker() const { return google_url_tracker_; }
64  GURL new_google_url() const { return new_google_url_; }
65
66 private:
67  virtual ~TestInfoBarDelegate();
68
69  // InfoBarDelegate:
70  virtual InfoBar* CreateInfoBar();
71
72  GoogleURLTracker* google_url_tracker_;
73  GURL new_google_url_;
74};
75
76TestInfoBarDelegate::TestInfoBarDelegate(GoogleURLTracker* google_url_tracker,
77                                         const GURL& new_google_url)
78    : InfoBarDelegate(NULL),
79      google_url_tracker_(google_url_tracker),
80      new_google_url_(new_google_url) {
81}
82
83TestInfoBarDelegate::~TestInfoBarDelegate() {
84}
85
86InfoBar* TestInfoBarDelegate::CreateInfoBar() {
87  return NULL;
88}
89
90InfoBarDelegate* CreateTestInfobar(
91    TabContents* tab_contents,
92    GoogleURLTracker* google_url_tracker,
93    const GURL& new_google_url) {
94  return new TestInfoBarDelegate(google_url_tracker, new_google_url);
95}
96
97}  // namespace
98
99
100// GoogleURLTrackerTest -------------------------------------------------------
101
102class GoogleURLTrackerTest : public testing::Test {
103 protected:
104  GoogleURLTrackerTest();
105  virtual ~GoogleURLTrackerTest();
106
107  // testing::Test
108  virtual void SetUp();
109  virtual void TearDown();
110
111  TestURLFetcher* GetFetcherByID(int expected_id);
112  void MockSearchDomainCheckResponse(int expected_id,
113                                     const std::string& domain);
114  void RequestServerCheck();
115  void FinishSleep();
116  void NotifyIPAddressChanged();
117  GURL GetFetchedGoogleURL();
118  void SetGoogleURL(const GURL& url);
119  void SetLastPromptedGoogleURL(const GURL& url);
120  GURL GetLastPromptedGoogleURL();
121  void SearchCommitted(const GURL& search_url);
122  void NavEntryCommitted();
123  bool InfoBarIsShown();
124  GURL GetInfoBarShowingURL();
125  void AcceptGoogleURL();
126  void CancelGoogleURL();
127  void InfoBarClosed();
128  void ExpectDefaultURLs();
129
130  scoped_ptr<TestNotificationObserver> observer_;
131
132 private:
133  MessageLoop* message_loop_;
134  BrowserThread* io_thread_;
135  scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
136  TestingPrefService local_state_;
137
138  TestURLFetcherFactory fetcher_factory_;
139  NotificationRegistrar registrar_;
140};
141
142GoogleURLTrackerTest::GoogleURLTrackerTest()
143    : observer_(new TestNotificationObserver),
144      message_loop_(NULL),
145      io_thread_(NULL) {
146}
147
148GoogleURLTrackerTest::~GoogleURLTrackerTest() {
149}
150
151void GoogleURLTrackerTest::SetUp() {
152  message_loop_ = new MessageLoop(MessageLoop::TYPE_IO);
153  io_thread_ = new BrowserThread(BrowserThread::IO, message_loop_);
154  network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
155  browser::RegisterLocalState(&local_state_);
156  TestingBrowserProcess* testing_browser_process =
157      static_cast<TestingBrowserProcess*>(g_browser_process);
158  testing_browser_process->SetPrefService(&local_state_);
159  GoogleURLTracker* tracker = new GoogleURLTracker;
160  tracker->queue_wakeup_task_ = false;
161  MessageLoop::current()->RunAllPending();
162  testing_browser_process->SetGoogleURLTracker(tracker);
163
164  URLFetcher::set_factory(&fetcher_factory_);
165  g_browser_process->google_url_tracker()->infobar_creator_ =
166      &CreateTestInfobar;
167}
168
169void GoogleURLTrackerTest::TearDown() {
170  URLFetcher::set_factory(NULL);
171  TestingBrowserProcess* testing_browser_process =
172      static_cast<TestingBrowserProcess*>(g_browser_process);
173  testing_browser_process->SetGoogleURLTracker(NULL);
174  testing_browser_process->SetPrefService(NULL);
175  network_change_notifier_.reset();
176  delete io_thread_;
177  delete message_loop_;
178}
179
180TestURLFetcher* GoogleURLTrackerTest::GetFetcherByID(int expected_id) {
181  return fetcher_factory_.GetFetcherByID(expected_id);
182}
183
184void GoogleURLTrackerTest::MockSearchDomainCheckResponse(
185    int expected_id,
186    const std::string& domain) {
187  TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(expected_id);
188  if (!fetcher)
189    return;
190  fetcher->delegate()->OnURLFetchComplete(fetcher,
191      GURL(GoogleURLTracker::kSearchDomainCheckURL), net::URLRequestStatus(),
192      200, ResponseCookies(), domain);
193  // At this point, |fetcher| is deleted.
194  MessageLoop::current()->RunAllPending();
195}
196
197void GoogleURLTrackerTest::RequestServerCheck() {
198  if (!registrar_.IsRegistered(observer_.get(),
199                               NotificationType::GOOGLE_URL_UPDATED,
200                               NotificationService::AllSources())) {
201    registrar_.Add(observer_.get(), NotificationType::GOOGLE_URL_UPDATED,
202                   NotificationService::AllSources());
203  }
204  GoogleURLTracker::RequestServerCheck();
205  MessageLoop::current()->RunAllPending();
206}
207
208void GoogleURLTrackerTest::FinishSleep() {
209  g_browser_process->google_url_tracker()->FinishSleep();
210  MessageLoop::current()->RunAllPending();
211}
212
213void GoogleURLTrackerTest::NotifyIPAddressChanged() {
214  net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
215  MessageLoop::current()->RunAllPending();
216}
217
218GURL GoogleURLTrackerTest::GetFetchedGoogleURL() {
219  return g_browser_process->google_url_tracker()->fetched_google_url_;
220}
221
222void GoogleURLTrackerTest::SetGoogleURL(const GURL& url) {
223  g_browser_process->google_url_tracker()->google_url_ = url;
224}
225
226void GoogleURLTrackerTest::SetLastPromptedGoogleURL(const GURL& url) {
227  g_browser_process->local_state()->SetString(
228      prefs::kLastPromptedGoogleURL, url.spec());
229}
230
231GURL GoogleURLTrackerTest::GetLastPromptedGoogleURL() {
232  return GURL(g_browser_process->local_state()->GetString(
233      prefs::kLastPromptedGoogleURL));
234}
235
236void GoogleURLTrackerTest::SearchCommitted(const GURL& search_url) {
237  GoogleURLTracker* google_url_tracker =
238      g_browser_process->google_url_tracker();
239  google_url_tracker->SearchCommitted();
240  if (google_url_tracker->registrar_.IsRegistered(google_url_tracker,
241      NotificationType::NAV_ENTRY_PENDING,
242      NotificationService::AllSources()))
243    google_url_tracker->search_url_ = search_url;
244}
245
246void GoogleURLTrackerTest::NavEntryCommitted() {
247  GoogleURLTracker* google_url_tracker =
248      g_browser_process->google_url_tracker();
249  google_url_tracker->ShowGoogleURLInfoBarIfNecessary(NULL);
250}
251
252bool GoogleURLTrackerTest::InfoBarIsShown() {
253  return (g_browser_process->google_url_tracker()->infobar_ != NULL);
254}
255
256GURL GoogleURLTrackerTest::GetInfoBarShowingURL() {
257  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
258      g_browser_process->google_url_tracker()->infobar_);
259  return infobar->new_google_url();
260}
261
262void GoogleURLTrackerTest::AcceptGoogleURL() {
263  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
264      g_browser_process->google_url_tracker()->infobar_);
265  ASSERT_TRUE(infobar);
266  ASSERT_TRUE(infobar->google_url_tracker());
267  infobar->google_url_tracker()->AcceptGoogleURL(infobar->new_google_url());
268}
269
270void GoogleURLTrackerTest::CancelGoogleURL() {
271  TestInfoBarDelegate* infobar = static_cast<TestInfoBarDelegate*>(
272      g_browser_process->google_url_tracker()->infobar_);
273  ASSERT_TRUE(infobar);
274  ASSERT_TRUE(infobar->google_url_tracker());
275  infobar->google_url_tracker()->CancelGoogleURL(infobar->new_google_url());
276}
277
278void GoogleURLTrackerTest::InfoBarClosed() {
279  InfoBarDelegate* infobar = g_browser_process->google_url_tracker()->infobar_;
280  ASSERT_TRUE(infobar);
281  GoogleURLTracker* url_tracker =
282      static_cast<TestInfoBarDelegate*>(infobar)->google_url_tracker();
283  ASSERT_TRUE(url_tracker);
284  url_tracker->InfoBarClosed();
285  delete infobar;
286}
287
288void GoogleURLTrackerTest::ExpectDefaultURLs() {
289  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
290            GoogleURLTracker::GoogleURL());
291  EXPECT_EQ(GURL(), GetFetchedGoogleURL());
292}
293
294
295// Tests ----------------------------------------------------------------------
296
297TEST_F(GoogleURLTrackerTest, DontFetchWhenNoOneRequestsCheck) {
298  ExpectDefaultURLs();
299  FinishSleep();
300  // No one called RequestServerCheck() so nothing should have happened.
301  EXPECT_FALSE(GetFetcherByID(0));
302  ExpectDefaultURLs();
303  EXPECT_FALSE(observer_->notified());
304}
305
306TEST_F(GoogleURLTrackerTest, UpdateOnFirstRun) {
307  RequestServerCheck();
308  EXPECT_FALSE(GetFetcherByID(0));
309  ExpectDefaultURLs();
310  EXPECT_FALSE(observer_->notified());
311
312  FinishSleep();
313  MockSearchDomainCheckResponse(0, ".google.co.uk");
314  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
315  // GoogleURL should be updated, becase there was no last prompted URL.
316  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
317  EXPECT_TRUE(observer_->notified());
318}
319
320TEST_F(GoogleURLTrackerTest, DontUpdateWhenUnchanged) {
321  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
322
323  RequestServerCheck();
324  EXPECT_FALSE(GetFetcherByID(0));
325  ExpectDefaultURLs();
326  EXPECT_FALSE(observer_->notified());
327
328  FinishSleep();
329  MockSearchDomainCheckResponse(0, ".google.co.uk");
330  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
331  // GoogleURL should not be updated, because the fetched and prompted URLs
332  // match.
333  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
334            GoogleURLTracker::GoogleURL());
335  EXPECT_FALSE(observer_->notified());
336}
337
338TEST_F(GoogleURLTrackerTest, UpdatePromptedURLOnReturnToPreviousLocation) {
339  SetLastPromptedGoogleURL(GURL("http://www.google.co.jp/"));
340  SetGoogleURL(GURL("http://www.google.co.uk/"));
341  RequestServerCheck();
342  FinishSleep();
343  MockSearchDomainCheckResponse(0, ".google.co.uk");
344  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
345  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
346  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
347  EXPECT_FALSE(observer_->notified());
348}
349
350TEST_F(GoogleURLTrackerTest, RefetchOnIPAddressChange) {
351  RequestServerCheck();
352  FinishSleep();
353  MockSearchDomainCheckResponse(0, ".google.co.uk");
354  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
355  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
356  EXPECT_TRUE(observer_->notified());
357  observer_->clear_notified();
358
359  NotifyIPAddressChanged();
360  MockSearchDomainCheckResponse(1, ".google.co.in");
361  EXPECT_EQ(GURL("http://www.google.co.in/"), GetFetchedGoogleURL());
362  // Just fetching a new URL shouldn't reset things without a prompt.
363  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
364  EXPECT_FALSE(observer_->notified());
365}
366
367TEST_F(GoogleURLTrackerTest, DontRefetchWhenNoOneRequestsCheck) {
368  FinishSleep();
369  NotifyIPAddressChanged();
370  // No one called RequestServerCheck() so nothing should have happened.
371  EXPECT_FALSE(GetFetcherByID(0));
372  ExpectDefaultURLs();
373  EXPECT_FALSE(observer_->notified());
374}
375
376TEST_F(GoogleURLTrackerTest, FetchOnLateRequest) {
377  FinishSleep();
378  NotifyIPAddressChanged();
379
380  RequestServerCheck();
381  // The first request for a check should trigger a fetch if it hasn't happened
382  // already.
383  MockSearchDomainCheckResponse(0, ".google.co.uk");
384  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
385  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
386  EXPECT_TRUE(observer_->notified());
387}
388
389TEST_F(GoogleURLTrackerTest, SearchingDoesNothingIfNoNeedToPrompt) {
390  RequestServerCheck();
391  FinishSleep();
392  MockSearchDomainCheckResponse(0, ".google.co.uk");
393  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
394  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
395  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
396  EXPECT_TRUE(observer_->notified());
397  observer_->clear_notified();
398
399  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
400  NavEntryCommitted();
401  EXPECT_FALSE(InfoBarIsShown());
402  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetFetchedGoogleURL());
403  EXPECT_EQ(GURL("http://www.google.co.uk/"), GoogleURLTracker::GoogleURL());
404  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
405  EXPECT_FALSE(observer_->notified());
406}
407
408TEST_F(GoogleURLTrackerTest, InfobarClosed) {
409  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
410  RequestServerCheck();
411  FinishSleep();
412  MockSearchDomainCheckResponse(0, ".google.co.jp");
413
414  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
415  NavEntryCommitted();
416  EXPECT_TRUE(InfoBarIsShown());
417
418  InfoBarClosed();
419  EXPECT_FALSE(InfoBarIsShown());
420  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
421            GoogleURLTracker::GoogleURL());
422  EXPECT_EQ(GURL("http://www.google.co.uk/"), GetLastPromptedGoogleURL());
423  EXPECT_FALSE(observer_->notified());
424}
425
426TEST_F(GoogleURLTrackerTest, InfobarRefused) {
427  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
428  RequestServerCheck();
429  FinishSleep();
430  MockSearchDomainCheckResponse(0, ".google.co.jp");
431
432  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
433  NavEntryCommitted();
434  EXPECT_TRUE(InfoBarIsShown());
435
436  CancelGoogleURL();
437  InfoBarClosed();
438  EXPECT_FALSE(InfoBarIsShown());
439  EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage),
440            GoogleURLTracker::GoogleURL());
441  EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL());
442  EXPECT_FALSE(observer_->notified());
443}
444
445TEST_F(GoogleURLTrackerTest, InfobarAccepted) {
446  SetLastPromptedGoogleURL(GURL("http://www.google.co.uk/"));
447  RequestServerCheck();
448  FinishSleep();
449  MockSearchDomainCheckResponse(0, ".google.co.jp");
450
451  SearchCommitted(GURL("http://www.google.co.uk/search?q=test"));
452  NavEntryCommitted();
453  EXPECT_TRUE(InfoBarIsShown());
454
455  AcceptGoogleURL();
456  InfoBarClosed();
457  EXPECT_FALSE(InfoBarIsShown());
458  EXPECT_EQ(GURL("http://www.google.co.jp/"), GoogleURLTracker::GoogleURL());
459  EXPECT_EQ(GURL("http://www.google.co.jp/"), GetLastPromptedGoogleURL());
460  EXPECT_TRUE(observer_->notified());
461}
462