1// Copyright 2014 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 "base/memory/scoped_ptr.h"
6#include "chrome/browser/browser_process.h"
7#include "chrome/browser/ui/browser.h"
8#include "chrome/browser/ui/browser_tabstrip.h"
9#include "chrome/browser/ui/tabs/tab_strip_model.h"
10#include "chrome/common/url_constants.h"
11#include "chrome/test/base/in_process_browser_test.h"
12#include "chrome/test/base/testing_pref_service_syncable.h"
13#include "components/autofill/content/browser/content_autofill_driver.h"
14#include "components/autofill/core/browser/autofill_manager.h"
15#include "components/autofill/core/browser/test_autofill_client.h"
16#include "content/public/browser/navigation_controller.h"
17#include "content/public/browser/page_navigator.h"
18#include "content/public/browser/web_contents.h"
19#include "content/public/browser/web_contents_observer.h"
20#include "content/public/common/url_constants.h"
21#include "content/public/test/test_utils.h"
22#include "testing/gmock/include/gmock/gmock.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "ui/gfx/rect.h"
25
26namespace autofill {
27namespace {
28
29class MockAutofillClient : public TestAutofillClient {
30 public:
31  MockAutofillClient() {}
32  virtual ~MockAutofillClient() {}
33
34  virtual PrefService* GetPrefs() { return &prefs_; }
35
36  user_prefs::PrefRegistrySyncable* GetPrefRegistry() {
37    return prefs_.registry();
38  }
39
40  MOCK_METHOD7(ShowAutofillPopup,
41               void(const gfx::RectF& element_bounds,
42                    base::i18n::TextDirection text_direction,
43                    const std::vector<base::string16>& values,
44                    const std::vector<base::string16>& labels,
45                    const std::vector<base::string16>& icons,
46                    const std::vector<int>& identifiers,
47                    base::WeakPtr<AutofillPopupDelegate> delegate));
48
49  MOCK_METHOD0(HideAutofillPopup, void());
50
51 private:
52  TestingPrefServiceSyncable prefs_;
53
54  DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
55};
56
57// Subclass ContentAutofillDriver so we can create an ContentAutofillDriver
58// instance.
59class TestContentAutofillDriver : public ContentAutofillDriver {
60 public:
61  TestContentAutofillDriver(content::WebContents* web_contents,
62                            AutofillClient* client)
63      : ContentAutofillDriver(
64            web_contents,
65            client,
66            g_browser_process->GetApplicationLocale(),
67            AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {}
68  virtual ~TestContentAutofillDriver() {}
69
70 private:
71  DISALLOW_COPY_AND_ASSIGN(TestContentAutofillDriver);
72};
73
74}  // namespace
75
76class ContentAutofillDriverBrowserTest : public InProcessBrowserTest,
77                                         public content::WebContentsObserver {
78 public:
79  ContentAutofillDriverBrowserTest() {}
80  virtual ~ContentAutofillDriverBrowserTest() {}
81
82  virtual void SetUpOnMainThread() OVERRIDE {
83    content::WebContents* web_contents =
84        browser()->tab_strip_model()->GetActiveWebContents();
85    ASSERT_TRUE(web_contents != NULL);
86    Observe(web_contents);
87    AutofillManager::RegisterProfilePrefs(autofill_client_.GetPrefRegistry());
88
89    autofill_driver_.reset(
90        new TestContentAutofillDriver(web_contents, &autofill_client_));
91  }
92
93  // Normally the WebContents will automatically delete the driver, but here
94  // the driver is owned by this test, so we have to manually destroy.
95  virtual void WebContentsDestroyed() OVERRIDE {
96    autofill_driver_.reset();
97  }
98
99  virtual void WasHidden() OVERRIDE {
100    if (!web_contents_hidden_callback_.is_null())
101      web_contents_hidden_callback_.Run();
102  }
103
104  virtual void NavigationEntryCommitted(
105      const content::LoadCommittedDetails& load_details) OVERRIDE {
106    if (!nav_entry_committed_callback_.is_null())
107      nav_entry_committed_callback_.Run();
108  }
109
110 protected:
111  content::WebContents* web_contents_;
112
113  base::Closure web_contents_hidden_callback_;
114  base::Closure nav_entry_committed_callback_;
115
116  testing::NiceMock<MockAutofillClient> autofill_client_;
117  scoped_ptr<TestContentAutofillDriver> autofill_driver_;
118};
119
120IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest,
121                       SwitchTabAndHideAutofillPopup) {
122  // Notification is different on platforms. On linux this will be called twice,
123  // while on windows only once.
124  EXPECT_CALL(autofill_client_, HideAutofillPopup()).Times(testing::AtLeast(1));
125
126  scoped_refptr<content::MessageLoopRunner> runner =
127      new content::MessageLoopRunner;
128  web_contents_hidden_callback_ = runner->QuitClosure();
129  chrome::AddSelectedTabWithURL(browser(),
130                                GURL(url::kAboutBlankURL),
131                                ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
132  runner->Run();
133  web_contents_hidden_callback_.Reset();
134}
135
136IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest,
137                       TestPageNavigationHidingAutofillPopup) {
138  // Notification is different on platforms. On linux this will be called twice,
139  // while on windows only once.
140  EXPECT_CALL(autofill_client_, HideAutofillPopup()).Times(testing::AtLeast(1));
141
142  scoped_refptr<content::MessageLoopRunner> runner =
143      new content::MessageLoopRunner;
144  nav_entry_committed_callback_ = runner->QuitClosure();
145  browser()->OpenURL(content::OpenURLParams(GURL(chrome::kChromeUIBookmarksURL),
146                                            content::Referrer(),
147                                            CURRENT_TAB,
148                                            ui::PAGE_TRANSITION_TYPED,
149                                            false));
150  browser()->OpenURL(content::OpenURLParams(GURL(chrome::kChromeUIAboutURL),
151                                            content::Referrer(),
152                                            CURRENT_TAB,
153                                            ui::PAGE_TRANSITION_TYPED,
154                                            false));
155  runner->Run();
156  nav_entry_committed_callback_.Reset();
157}
158
159}  // namespace autofill
160