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/search/iframe_source.h"
8 #include "base/memory/ref_counted_memory.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "chrome/browser/search/instant_io_context.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/resource_request_info.h"
14 #include "content/public/test/mock_resource_context.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "grit/browser_resources.h"
17 #include "ipc/ipc_message.h"
18 #include "net/base/request_priority.h"
19 #include "net/url_request/url_request.h"
20 #include "net/url_request/url_request_context.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
25 using content::ResourceType
;
27 const int kNonInstantRendererPID
= 0;
28 const char kNonInstantOrigin
[] = "http://evil";
29 const int kInstantRendererPID
= 1;
30 const char kInstantOrigin
[] = "chrome-search://instant";
31 const int kInvalidRendererPID
= 42;
33 class TestIframeSource
: public IframeSource
{
35 using IframeSource::GetMimeType
;
36 using IframeSource::ShouldServiceRequest
;
37 using IframeSource::SendResource
;
38 using IframeSource::SendJSWithOrigin
;
41 std::string
GetSource() const override
{ return "test"; }
43 bool ServesPath(const std::string
& path
) const override
{
44 return path
== "/valid.html" || path
== "/valid.js";
47 void StartDataRequest(
48 const std::string
& path
,
49 int render_process_id
,
51 const content::URLDataSource::GotDataCallback
& callback
) override
{}
53 // RenderFrameHost is hard to mock in concert with everything else, so stub
54 // this method out for testing.
55 bool GetOrigin(int process_id
,
57 std::string
* origin
) const override
{
58 if (process_id
== kInstantRendererPID
) {
59 *origin
= kInstantOrigin
;
62 if (process_id
== kNonInstantRendererPID
) {
63 *origin
= kNonInstantOrigin
;
70 class IframeSourceTest
: public testing::Test
{
72 // net::URLRequest wants to be executed with a message loop that has TYPE_IO.
73 // InstantIOContext needs to be created on the UI thread and have everything
74 // else happen on the IO thread. This setup is a hacky way to satisfy all
77 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
78 resource_context_(&test_url_request_context_
),
79 instant_io_context_(NULL
),
83 TestIframeSource
* source() { return source_
.get(); }
85 std::string
response_string() {
86 if (response_
.get()) {
87 return std::string(response_
->front_as
<char>(), response_
->size());
92 scoped_ptr
<net::URLRequest
> MockRequest(
93 const std::string
& url
,
95 int render_process_id
,
96 int render_frame_id
) {
97 scoped_ptr
<net::URLRequest
> request(
98 resource_context_
.GetRequestContext()->CreateRequest(
100 net::DEFAULT_PRIORITY
,
103 content::ResourceRequestInfo::AllocateForTesting(
105 content::RESOURCE_TYPE_SUB_FRAME
,
110 false, // is_main_frame
111 false, // parent_is_main_frame
112 true, // allow_download
115 return request
.Pass();
118 void SendResource(int resource_id
) {
119 source()->SendResource(resource_id
, callback_
);
122 void SendJSWithOrigin(
124 int render_process_id
,
125 int render_frame_id
) {
126 source()->SendJSWithOrigin(resource_id
, render_process_id
, render_frame_id
,
131 void SetUp() override
{
132 source_
.reset(new TestIframeSource());
133 callback_
= base::Bind(&IframeSourceTest::SaveResponse
,
134 base::Unretained(this));
135 instant_io_context_
= new InstantIOContext
;
136 InstantIOContext::SetUserDataOnIO(&resource_context_
, instant_io_context_
);
137 InstantIOContext::AddInstantProcessOnIO(instant_io_context_
,
138 kInstantRendererPID
);
142 void TearDown() override
{ source_
.reset(); }
144 void SaveResponse(base::RefCountedMemory
* data
) {
148 content::TestBrowserThreadBundle thread_bundle_
;
150 net::TestURLRequestContext test_url_request_context_
;
151 content::MockResourceContext resource_context_
;
152 scoped_ptr
<TestIframeSource
> source_
;
153 content::URLDataSource::GotDataCallback callback_
;
154 scoped_refptr
<InstantIOContext
> instant_io_context_
;
155 scoped_refptr
<base::RefCountedMemory
> response_
;
158 TEST_F(IframeSourceTest
, ShouldServiceRequest
) {
159 scoped_ptr
<net::URLRequest
> request
;
160 request
= MockRequest("http://test/loader.js", true,
161 kNonInstantRendererPID
, 0);
162 EXPECT_FALSE(source()->ShouldServiceRequest(request
.get()));
163 request
= MockRequest("chrome-search://bogus/valid.js", true,
164 kInstantRendererPID
, 0);
165 EXPECT_FALSE(source()->ShouldServiceRequest(request
.get()));
166 request
= MockRequest("chrome-search://test/bogus.js", true,
167 kInstantRendererPID
, 0);
168 EXPECT_FALSE(source()->ShouldServiceRequest(request
.get()));
169 request
= MockRequest("chrome-search://test/valid.js", true,
170 kInstantRendererPID
, 0);
171 EXPECT_TRUE(source()->ShouldServiceRequest(request
.get()));
172 request
= MockRequest("chrome-search://test/valid.js", true,
173 kNonInstantRendererPID
, 0);
174 EXPECT_FALSE(source()->ShouldServiceRequest(request
.get()));
175 request
= MockRequest("chrome-search://test/valid.js", true,
176 kInvalidRendererPID
, 0);
177 EXPECT_FALSE(source()->ShouldServiceRequest(request
.get()));
180 TEST_F(IframeSourceTest
, GetMimeType
) {
181 // URLDataManagerBackend does not include / in path_and_query.
182 EXPECT_EQ("text/html", source()->GetMimeType("foo.html"));
183 EXPECT_EQ("application/javascript", source()->GetMimeType("foo.js"));
184 EXPECT_EQ("text/css", source()->GetMimeType("foo.css"));
185 EXPECT_EQ("image/png", source()->GetMimeType("foo.png"));
186 EXPECT_EQ("", source()->GetMimeType("bogus"));
189 TEST_F(IframeSourceTest
, SendResource
) {
190 SendResource(IDR_MOST_VISITED_TITLE_HTML
);
191 EXPECT_FALSE(response_string().empty());
194 TEST_F(IframeSourceTest
, SendJSWithOrigin
) {
195 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS
, kInstantRendererPID
, 0);
196 EXPECT_FALSE(response_string().empty());
197 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS
, kNonInstantRendererPID
, 0);
198 EXPECT_FALSE(response_string().empty());
199 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS
, kInvalidRendererPID
, 0);
200 EXPECT_TRUE(response_string().empty());