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/instant_page.h"
6
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"
21#include "url/gurl.h"
22
23class Profile;
24
25namespace {
26
27class FakePageDelegate : public InstantPage::Delegate {
28 public:
29  virtual ~FakePageDelegate() {
30  }
31
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,
39                    const GURL& url));
40  MOCK_METHOD5(NavigateToURL,
41               void(const content::WebContents* contents,
42                    const GURL& url,
43                    ui::PageTransition transition,
44                    WindowOpenDisposition disposition,
45                    bool is_search_type));
46};
47
48}  // namespace
49
50class InstantPageTest : public ChromeRenderViewHostTestHarness {
51 public:
52  virtual void SetUp() OVERRIDE;
53
54  bool MessageWasSent(uint32 id) {
55    return process()->sink().GetFirstMessageMatching(id) != NULL;
56  }
57
58  scoped_ptr<InstantPage> page;
59  FakePageDelegate delegate;
60};
61
62void InstantPageTest::SetUp() {
63  ChromeRenderViewHostTestHarness::SetUp();
64  SearchTabHelper::CreateForWebContents(web_contents());
65}
66
67TEST_F(InstantPageTest, IsLocal) {
68  page.reset(new InstantPage(&delegate, "", NULL, false));
69  EXPECT_FALSE(page->supports_instant());
70  EXPECT_FALSE(page->IsLocal());
71  page->SetContents(web_contents());
72  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
73  EXPECT_TRUE(page->IsLocal());
74  NavigateAndCommit(GURL("http://example.com"));
75  EXPECT_FALSE(page->IsLocal());
76}
77
78TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_Local) {
79  page.reset(new InstantPage(&delegate, "", NULL, false));
80  EXPECT_FALSE(page->supports_instant());
81  page->SetContents(web_contents());
82  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
83  EXPECT_TRUE(page->IsLocal());
84  EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
85      .Times(1);
86  SearchTabHelper::FromWebContents(web_contents())->
87      DetermineIfPageSupportsInstant();
88  EXPECT_TRUE(page->supports_instant());
89}
90
91TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_NonLocal) {
92  page.reset(new InstantPage(&delegate, "", NULL, false));
93  EXPECT_FALSE(page->supports_instant());
94  page->SetContents(web_contents());
95  NavigateAndCommit(GURL("chrome-search://foo/bar"));
96  EXPECT_FALSE(page->IsLocal());
97  process()->sink().ClearMessages();
98  SearchTabHelper::FromWebContents(web_contents())->
99      DetermineIfPageSupportsInstant();
100  const IPC::Message* message = process()->sink().GetFirstMessageMatching(
101      ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
102  ASSERT_TRUE(message != NULL);
103  EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id());
104}
105
106TEST_F(InstantPageTest, PageURLDoesntBelongToInstantRenderer) {
107  page.reset(new InstantPage(&delegate, "", NULL, false));
108  EXPECT_FALSE(page->supports_instant());
109  NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
110  page->SetContents(web_contents());
111
112  // Navigate to a page URL that doesn't belong to Instant renderer.
113  // SearchTabHelper::DeterminerIfPageSupportsInstant() should return
114  // immediately without dispatching any message to the renderer.
115  NavigateAndCommit(GURL("http://www.example.com"));
116  EXPECT_FALSE(page->IsLocal());
117  process()->sink().ClearMessages();
118  EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), false))
119      .Times(1);
120
121  SearchTabHelper::FromWebContents(web_contents())->
122      DetermineIfPageSupportsInstant();
123  const IPC::Message* message = process()->sink().GetFirstMessageMatching(
124      ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
125  ASSERT_TRUE(message == NULL);
126  EXPECT_FALSE(page->supports_instant());
127}
128
129// Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message
130// reply handler updates the instant support state in InstantPage.
131TEST_F(InstantPageTest, PageSupportsInstant) {
132  page.reset(new InstantPage(&delegate, "", NULL, false));
133  EXPECT_FALSE(page->supports_instant());
134  page->SetContents(web_contents());
135  NavigateAndCommit(GURL("chrome-search://foo/bar"));
136  process()->sink().ClearMessages();
137  SearchTabHelper::FromWebContents(web_contents())->
138      DetermineIfPageSupportsInstant();
139  const IPC::Message* message = process()->sink().GetFirstMessageMatching(
140      ChromeViewMsg_DetermineIfPageSupportsInstant::ID);
141  ASSERT_TRUE(message != NULL);
142  EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id());
143
144  EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true))
145      .Times(1);
146
147  // Assume the page supports instant. Invoke the message reply handler to make
148  // sure the InstantPage is notified about the instant support state.
149  const content::NavigationEntry* entry =
150      web_contents()->GetController().GetLastCommittedEntry();
151  EXPECT_TRUE(entry);
152  SearchTabHelper::FromWebContents(web_contents())->InstantSupportChanged(true);
153  EXPECT_TRUE(page->supports_instant());
154}
155