• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/ui/search/search_tab_helper.h"
6 
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/search/search.h"
11 #include "chrome/browser/search_engines/template_url_service.h"
12 #include "chrome/browser/search_engines/template_url_service_factory.h"
13 #include "chrome/browser/signin/fake_signin_manager.h"
14 #include "chrome/browser/signin/signin_manager_factory.h"
15 #include "chrome/browser/ui/search/search_ipc_router.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/ntp_logging_events.h"
19 #include "chrome/common/omnibox_focus_state.h"
20 #include "chrome/common/render_messages.h"
21 #include "chrome/common/url_constants.h"
22 #include "chrome/test/base/browser_with_test_window_test.h"
23 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/ui_test_utils.h"
26 #include "content/public/browser/navigation_controller.h"
27 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/test/mock_render_process_host.h"
30 #include "grit/generated_resources.h"
31 #include "ipc/ipc_message.h"
32 #include "ipc/ipc_test_sink.h"
33 #include "net/base/net_errors.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "ui/base/l10n/l10n_util.h"
37 #include "url/gurl.h"
38 
39 namespace {
40 
41 class MockSearchIPCRouterDelegate : public SearchIPCRouter::Delegate {
42  public:
~MockSearchIPCRouterDelegate()43   virtual ~MockSearchIPCRouterDelegate() {}
44 
45   MOCK_METHOD1(OnInstantSupportDetermined, void(bool supports_instant));
46   MOCK_METHOD1(OnSetVoiceSearchSupport, void(bool supports_voice_search));
47   MOCK_METHOD1(FocusOmnibox, void(OmniboxFocusState state));
48   MOCK_METHOD3(NavigateToURL, void(const GURL&, WindowOpenDisposition, bool));
49   MOCK_METHOD1(OnDeleteMostVisitedItem, void(const GURL& url));
50   MOCK_METHOD1(OnUndoMostVisitedDeletion, void(const GURL& url));
51   MOCK_METHOD0(OnUndoAllMostVisitedDeletions, void());
52   MOCK_METHOD1(OnLogEvent, void(NTPLoggingEventType event));
53   MOCK_METHOD2(OnLogImpression, void(int position,
54                                      const base::string16& provider));
55   MOCK_METHOD1(PasteIntoOmnibox, void(const base::string16&));
56   MOCK_METHOD1(OnChromeIdentityCheck, void(const base::string16& identity));
57 };
58 
59 }  // namespace
60 
61 class SearchTabHelperTest : public ChromeRenderViewHostTestHarness {
62  public:
SetUp()63   virtual void SetUp() {
64     ChromeRenderViewHostTestHarness::SetUp();
65     SearchTabHelper::CreateForWebContents(web_contents());
66   }
67 
68   // Creates a sign-in manager for tests.  If |username| is not empty, the
69   // testing profile of the WebContents will be connected to the given account.
CreateSigninManager(const std::string & username)70   void CreateSigninManager(const std::string& username) {
71     SigninManagerBase* signin_manager = static_cast<SigninManagerBase*>(
72         SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
73             profile(), FakeSigninManagerBase::Build));
74     signin_manager->Initialize(profile(), NULL);
75 
76     if (!username.empty()) {
77       ASSERT_TRUE(signin_manager);
78       signin_manager->SetAuthenticatedUsername(username);
79     }
80   }
81 
MessageWasSent(uint32 id)82   bool MessageWasSent(uint32 id) {
83     return process()->sink().GetFirstMessageMatching(id) != NULL;
84   }
85 
mock_delegate()86   MockSearchIPCRouterDelegate* mock_delegate() { return &delegate_; }
87 
88  private:
89   MockSearchIPCRouterDelegate delegate_;
90 };
91 
TEST_F(SearchTabHelperTest,DetermineIfPageSupportsInstant_Local)92 TEST_F(SearchTabHelperTest, DetermineIfPageSupportsInstant_Local) {
93   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
94   EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(true)).Times(0);
95 
96   SearchTabHelper* search_tab_helper =
97       SearchTabHelper::FromWebContents(web_contents());
98   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
99   search_tab_helper->ipc_router().set_delegate(mock_delegate());
100   search_tab_helper->DetermineIfPageSupportsInstant();
101 }
102 
TEST_F(SearchTabHelperTest,DetermineIfPageSupportsInstant_NonLocal)103 TEST_F(SearchTabHelperTest, DetermineIfPageSupportsInstant_NonLocal) {
104   NavigateAndCommit(GURL("chrome-search://foo/bar"));
105   process()->sink().ClearMessages();
106   EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(true)).Times(1);
107 
108   SearchTabHelper* search_tab_helper =
109       SearchTabHelper::FromWebContents(web_contents());
110   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
111   search_tab_helper->ipc_router().set_delegate(mock_delegate());
112   search_tab_helper->DetermineIfPageSupportsInstant();
113   ASSERT_TRUE(MessageWasSent(ChromeViewMsg_DetermineIfPageSupportsInstant::ID));
114 
115   scoped_ptr<IPC::Message> response(
116       new ChromeViewHostMsg_InstantSupportDetermined(
117           web_contents()->GetRoutingID(),
118           web_contents()->GetController().GetVisibleEntry()->GetPageID(),
119           true));
120   search_tab_helper->ipc_router().OnMessageReceived(*response);
121 }
122 
TEST_F(SearchTabHelperTest,PageURLDoesntBelongToInstantRenderer)123 TEST_F(SearchTabHelperTest, PageURLDoesntBelongToInstantRenderer) {
124   // Navigate to a page URL that doesn't belong to Instant renderer.
125   // SearchTabHelper::DeterminerIfPageSupportsInstant() should return
126   // immediately without dispatching any message to the renderer.
127   NavigateAndCommit(GURL("http://www.example.com"));
128   process()->sink().ClearMessages();
129   EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(false)).Times(0);
130 
131   SearchTabHelper* search_tab_helper =
132       SearchTabHelper::FromWebContents(web_contents());
133   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
134   search_tab_helper->ipc_router().set_delegate(mock_delegate());
135   search_tab_helper->DetermineIfPageSupportsInstant();
136   ASSERT_FALSE(MessageWasSent(
137       ChromeViewMsg_DetermineIfPageSupportsInstant::ID));
138 }
139 
TEST_F(SearchTabHelperTest,OnChromeIdentityCheckMatch)140 TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMatch) {
141   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
142   CreateSigninManager(std::string("foo@bar.com"));
143   SearchTabHelper* search_tab_helper =
144       SearchTabHelper::FromWebContents(web_contents());
145   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
146 
147   const base::string16 test_identity = ASCIIToUTF16("foo@bar.com");
148   search_tab_helper->OnChromeIdentityCheck(test_identity);
149 
150   const IPC::Message* message = process()->sink().GetUniqueMessageMatching(
151       ChromeViewMsg_ChromeIdentityCheckResult::ID);
152   ASSERT_TRUE(message != NULL);
153 
154   ChromeViewMsg_ChromeIdentityCheckResult::Param params;
155   ChromeViewMsg_ChromeIdentityCheckResult::Read(message, &params);
156   EXPECT_EQ(test_identity, params.a);
157   ASSERT_TRUE(params.b);
158 }
159 
TEST_F(SearchTabHelperTest,OnChromeIdentityCheckMismatch)160 TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMismatch) {
161   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
162   CreateSigninManager(std::string("foo@bar.com"));
163   SearchTabHelper* search_tab_helper =
164       SearchTabHelper::FromWebContents(web_contents());
165   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
166 
167   const base::string16 test_identity = ASCIIToUTF16("bar@foo.com");
168   search_tab_helper->OnChromeIdentityCheck(test_identity);
169 
170   const IPC::Message* message = process()->sink().GetUniqueMessageMatching(
171       ChromeViewMsg_ChromeIdentityCheckResult::ID);
172   ASSERT_TRUE(message != NULL);
173 
174   ChromeViewMsg_ChromeIdentityCheckResult::Param params;
175   ChromeViewMsg_ChromeIdentityCheckResult::Read(message, &params);
176   EXPECT_EQ(test_identity, params.a);
177   ASSERT_FALSE(params.b);
178 }
179 
TEST_F(SearchTabHelperTest,OnChromeIdentityCheckSignedOutMatch)180 TEST_F(SearchTabHelperTest, OnChromeIdentityCheckSignedOutMatch) {
181   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
182   // This test does not sign in.
183   SearchTabHelper* search_tab_helper =
184       SearchTabHelper::FromWebContents(web_contents());
185   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
186 
187   const base::string16 test_identity;
188   search_tab_helper->OnChromeIdentityCheck(test_identity);
189 
190   const IPC::Message* message = process()->sink().GetUniqueMessageMatching(
191       ChromeViewMsg_ChromeIdentityCheckResult::ID);
192   ASSERT_TRUE(message != NULL);
193 
194   ChromeViewMsg_ChromeIdentityCheckResult::Param params;
195   ChromeViewMsg_ChromeIdentityCheckResult::Read(message, &params);
196   EXPECT_EQ(test_identity, params.a);
197   ASSERT_TRUE(params.b);
198 }
199 
TEST_F(SearchTabHelperTest,OnChromeIdentityCheckSignedOutMismatch)200 TEST_F(SearchTabHelperTest, OnChromeIdentityCheckSignedOutMismatch) {
201   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
202   // This test does not sign in.
203   SearchTabHelper* search_tab_helper =
204       SearchTabHelper::FromWebContents(web_contents());
205   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
206 
207   const base::string16 test_identity = ASCIIToUTF16("bar@foo.com");
208   search_tab_helper->OnChromeIdentityCheck(test_identity);
209 
210   const IPC::Message* message = process()->sink().GetUniqueMessageMatching(
211       ChromeViewMsg_ChromeIdentityCheckResult::ID);
212   ASSERT_TRUE(message != NULL);
213 
214   ChromeViewMsg_ChromeIdentityCheckResult::Param params;
215   ChromeViewMsg_ChromeIdentityCheckResult::Read(message, &params);
216   EXPECT_EQ(test_identity, params.a);
217   ASSERT_FALSE(params.b);
218 }
219 
220 class TabTitleObserver : public content::WebContentsObserver {
221  public:
TabTitleObserver(content::WebContents * contents)222   explicit TabTitleObserver(content::WebContents* contents)
223       : WebContentsObserver(contents) {}
224 
title_on_start()225   base::string16 title_on_start() { return title_on_start_; }
title_on_commit()226   base::string16 title_on_commit() { return title_on_commit_; }
227 
228  private:
DidStartProvisionalLoadForFrame(int64,int64,bool,const GURL &,bool,bool,content::RenderViewHost *)229   virtual void DidStartProvisionalLoadForFrame(
230       int64 /* frame_id */,
231       int64 /* parent_frame_id */,
232       bool /* is_main_frame */,
233       const GURL& /* validated_url */,
234       bool /* is_error_page */,
235       bool /* is_iframe_srcdoc */,
236       content::RenderViewHost* /* render_view_host */) OVERRIDE {
237     title_on_start_ = web_contents()->GetTitle();
238   }
239 
DidNavigateMainFrame(const content::LoadCommittedDetails &,const content::FrameNavigateParams &)240   virtual void DidNavigateMainFrame(
241       const content::LoadCommittedDetails& /* details */,
242       const content::FrameNavigateParams& /* params */) OVERRIDE {
243     title_on_commit_ = web_contents()->GetTitle();
244   }
245 
246   base::string16 title_on_start_;
247   base::string16 title_on_commit_;
248 };
249 
TEST_F(SearchTabHelperTest,TitleIsSetForNTP)250 TEST_F(SearchTabHelperTest, TitleIsSetForNTP) {
251   TabTitleObserver title_observer(web_contents());
252   NavigateAndCommit(GURL(chrome::kChromeUINewTabURL));
253   const base::string16 title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
254   EXPECT_EQ(title, title_observer.title_on_start());
255   EXPECT_EQ(title, title_observer.title_on_commit());
256   EXPECT_EQ(title, web_contents()->GetTitle());
257 }
258 
259 class SearchTabHelperWindowTest : public BrowserWithTestWindowTest {
260  protected:
SetUp()261   virtual void SetUp() OVERRIDE {
262     BrowserWithTestWindowTest::SetUp();
263     TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
264         profile(), &TemplateURLServiceFactory::BuildInstanceFor);
265     TemplateURLService* template_url_service =
266         TemplateURLServiceFactory::GetForProfile(profile());
267     ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
268 
269     TemplateURLData data;
270     data.SetURL("http://foo.com/url?bar={searchTerms}");
271     data.instant_url = "http://foo.com/instant?"
272         "{google:omniboxStartMarginParameter}{google:forceInstantResults}"
273         "foo=foo#foo=foo&strk";
274     data.new_tab_url = std::string("https://foo.com/newtab?strk");
275     data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}");
276     data.search_terms_replacement_key = "strk";
277 
278     TemplateURL* template_url = new TemplateURL(profile(), data);
279     template_url_service->Add(template_url);
280     template_url_service->SetDefaultSearchProvider(template_url);
281   }
282 };
283 
TEST_F(SearchTabHelperWindowTest,OnProvisionalLoadFailRedirectNTPToLocal)284 TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailRedirectNTPToLocal) {
285   AddTab(browser(), GURL(chrome::kChromeUINewTabURL));
286   content::WebContents* contents =
287         browser()->tab_strip_model()->GetWebContentsAt(0);
288   content::NavigationController* controller = &contents->GetController();
289 
290   SearchTabHelper* search_tab_helper =
291       SearchTabHelper::FromWebContents(contents);
292   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
293 
294   // A failed provisional load of a cacheable NTP should be redirected to local
295   // NTP.
296   const GURL cacheableNTPURL = chrome::GetNewTabPageURL(profile());
297   search_tab_helper->DidFailProvisionalLoad(1, string16(), true,
298       cacheableNTPURL, 1, string16(), NULL);
299   CommitPendingLoad(controller);
300   EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
301                  controller->GetLastCommittedEntry()->GetURL());
302 }
303 
TEST_F(SearchTabHelperWindowTest,OnProvisionalLoadFailDontRedirectIfAborted)304 TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailDontRedirectIfAborted) {
305   AddTab(browser(), GURL("chrome://blank"));
306   content::WebContents* contents =
307         browser()->tab_strip_model()->GetWebContentsAt(0);
308   content::NavigationController* controller = &contents->GetController();
309 
310   SearchTabHelper* search_tab_helper =
311       SearchTabHelper::FromWebContents(contents);
312   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
313 
314   // A failed provisional load of a cacheable NTP should be redirected to local
315   // NTP.
316   const GURL cacheableNTPURL = chrome::GetNewTabPageURL(profile());
317   search_tab_helper->DidFailProvisionalLoad(1, string16(), true,
318       cacheableNTPURL, net::ERR_ABORTED, string16(), NULL);
319   CommitPendingLoad(controller);
320   EXPECT_EQ(GURL("chrome://blank"),
321                  controller->GetLastCommittedEntry()->GetURL());
322 }
323 
TEST_F(SearchTabHelperWindowTest,OnProvisionalLoadFailDontRedirectNonNTP)324 TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailDontRedirectNonNTP) {
325   AddTab(browser(), GURL(chrome::kChromeUINewTabURL));
326   content::WebContents* contents =
327         browser()->tab_strip_model()->GetWebContentsAt(0);
328   content::NavigationController* controller = &contents->GetController();
329 
330   SearchTabHelper* search_tab_helper =
331       SearchTabHelper::FromWebContents(contents);
332   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
333 
334   // Any other web page shouldn't be redirected when provisional load fails.
335   search_tab_helper->DidFailProvisionalLoad(1, string16(), true,
336       GURL("http://www.example.com"), 1, string16(), NULL);
337   CommitPendingLoad(controller);
338   EXPECT_NE(GURL(chrome::kChromeSearchLocalNtpUrl),
339                  controller->GetLastCommittedEntry()->GetURL());
340 }
341