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.
5 #include "chrome/browser/ui/search/instant_page.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "chrome/browser/ui/search/search_tab_helper.h"
10 #include "chrome/common/chrome_switches.h"
11 #include "chrome/common/render_messages.h"
12 #include "chrome/common/url_constants.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "content/public/browser/navigation_controller.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/test/mock_render_process_host.h"
18 #include "ipc/ipc_test_sink.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
27 class FakePageDelegate : public InstantPage::Delegate {
29 virtual ~FakePageDelegate() {
32 MOCK_METHOD2(InstantSupportDetermined,
33 void(const content::WebContents* contents,
34 bool supports_instant));
35 MOCK_METHOD1(InstantPageRenderProcessGone,
36 void(const content::WebContents* contents));
37 MOCK_METHOD2(InstantPageAboutToNavigateMainFrame,
38 void(const content::WebContents* contents,
40 MOCK_METHOD5(NavigateToURL,
41 void(const content::WebContents* contents,
43 content::PageTransition transition,
44 WindowOpenDisposition disposition,
45 bool is_search_type));
46 MOCK_METHOD1(InstantPageLoadFailed, void(content::WebContents* contents));
51 class InstantPageTest : public ChromeRenderViewHostTestHarness {
53 virtual void SetUp() OVERRIDE;
55 bool MessageWasSent(uint32 id) {
56 return process()->sink().GetFirstMessageMatching(id) != NULL;
59 scoped_ptr<InstantPage> page;
60 FakePageDelegate delegate;
63 void InstantPageTest::SetUp() {
64 CommandLine::ForCurrentProcess()->AppendSwitch(
65 switches::kEnableInstantExtendedAPI);
66 ChromeRenderViewHostTestHarness::SetUp();
67 SearchTabHelper::CreateForWebContents(web_contents());
70 TEST_F(InstantPageTest, IsLocal) {
71 page.reset(new InstantPage(&delegate, "", NULL, false));
72 EXPECT_FALSE(page->supports_instant());
73 EXPECT_FALSE(page->IsLocal());
74 page->SetContents(web_contents());
75 NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
76 EXPECT_TRUE(page->IsLocal());
77 NavigateAndCommit(GURL("http://example.com"));
78 EXPECT_FALSE(page->IsLocal());
81 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_Local) {
82 page.reset(new InstantPage(&delegate, "", NULL, false));
83 EXPECT_FALSE(page->supports_instant());
84 page->SetContents(web_contents());
85 NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
86 EXPECT_TRUE(page->IsLocal());
87 EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
89 SearchTabHelper::FromWebContents(web_contents())->
90 DetermineIfPageSupportsInstant();
91 EXPECT_TRUE(page->supports_instant());
94 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_NonLocal) {
95 page.reset(new InstantPage(&delegate, "", NULL, false));
96 EXPECT_FALSE(page->supports_instant());
97 page->SetContents(web_contents());
98 NavigateAndCommit(GURL("chrome-search://foo/bar"));
99 EXPECT_FALSE(page->IsLocal());
100 process()->sink().ClearMessages();
101 SearchTabHelper::FromWebContents(web_contents())->
102 DetermineIfPageSupportsInstant();
103 const IPC::Message* message = process()->sink().GetFirstMessageMatching(
104 ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
105 ASSERT_TRUE(message != NULL);
106 EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id());
109 TEST_F(InstantPageTest, PageURLDoesntBelongToInstantRenderer) {
110 page.reset(new InstantPage(&delegate, "", NULL, false));
111 EXPECT_FALSE(page->supports_instant());
112 NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
113 page->SetContents(web_contents());
115 // Navigate to a page URL that doesn't belong to Instant renderer.
116 // SearchTabHelper::DeterminerIfPageSupportsInstant() should return
117 // immediately without dispatching any message to the renderer.
118 NavigateAndCommit(GURL("http://www.example.com"));
119 EXPECT_FALSE(page->IsLocal());
120 process()->sink().ClearMessages();
121 EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), false))
124 SearchTabHelper::FromWebContents(web_contents())->
125 DetermineIfPageSupportsInstant();
126 const IPC::Message* message = process()->sink().GetFirstMessageMatching(
127 ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
128 ASSERT_TRUE(message == NULL);
129 EXPECT_FALSE(page->supports_instant());
132 // Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message
133 // reply handler updates the instant support state in InstantPage.
134 TEST_F(InstantPageTest, PageSupportsInstant) {
135 page.reset(new InstantPage(&delegate, "", NULL, false));
136 EXPECT_FALSE(page->supports_instant());
137 page->SetContents(web_contents());
138 NavigateAndCommit(GURL("chrome-search://foo/bar"));
139 process()->sink().ClearMessages();
140 SearchTabHelper::FromWebContents(web_contents())->
141 DetermineIfPageSupportsInstant();
142 const IPC::Message* message = process()->sink().GetFirstMessageMatching(
143 ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
144 ASSERT_TRUE(message != NULL);
145 EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id());
147 EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
150 // Assume the page supports instant. Invoke the message reply handler to make
151 // sure the InstantPage is notified about the instant support state.
152 const content::NavigationEntry* entry =
153 web_contents()->GetController().GetActiveEntry();
155 SearchTabHelper::FromWebContents(web_contents())->InstantSupportChanged(true);
156 EXPECT_TRUE(page->supports_instant());
159 TEST_F(InstantPageTest, AppropriateMessagesSentToIncognitoPages) {
160 page.reset(new InstantPage(&delegate, "", NULL, true));
161 page->SetContents(web_contents());
162 NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
163 process()->sink().ClearMessages();
165 // Incognito pages should get these messages.
166 page->sender()->SetOmniboxBounds(gfx::Rect());
167 EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxMarginChange::ID));
168 page->sender()->ToggleVoiceSearch();
169 EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxToggleVoiceSearch::ID));
171 // Incognito pages should not get any others.
172 page->sender()->FocusChanged(
173 OMNIBOX_FOCUS_NONE, OMNIBOX_FOCUS_CHANGE_EXPLICIT);
174 EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxFocusChanged::ID));
176 page->sender()->SetInputInProgress(false);
177 EXPECT_FALSE(MessageWasSent(ChromeViewMsg_SearchBoxSetInputInProgress::ID));