iframe_source_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/search/iframe_source.h" 6 7#include "base/bind.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 "net/url_request/url_request.h" 18#include "net/url_request/url_request_context.h" 19#include "net/url_request/url_request_test_util.h" 20#include "testing/gtest/include/gtest/gtest.h" 21#include "url/gurl.h" 22 23const int kNonInstantRendererPID = 0; 24const char kNonInstantOrigin[] = "http://evil"; 25const int kInstantRendererPID = 1; 26const char kInstantOrigin[] = "chrome-search://instant"; 27const int kInvalidRendererPID = 42; 28 29class TestIframeSource : public IframeSource { 30 public: 31 using IframeSource::GetMimeType; 32 using IframeSource::ShouldServiceRequest; 33 using IframeSource::SendResource; 34 using IframeSource::SendJSWithOrigin; 35 36 protected: 37 virtual std::string GetSource() const OVERRIDE { 38 return "test"; 39 } 40 41 virtual bool ServesPath(const std::string& path) const OVERRIDE { 42 return path == "/valid.html" || path == "/valid.js"; 43 } 44 45 virtual void StartDataRequest( 46 const std::string& path, 47 int render_process_id, 48 int render_view_id, 49 const content::URLDataSource::GotDataCallback& callback) OVERRIDE { 50 } 51 52 // RenderViewHost is hard to mock in concert with everything else, so stub 53 // this method out for testing. 54 virtual bool GetOrigin( 55 int process_id, 56 int render_view_id, 57 std::string* origin) const OVERRIDE { 58 if (process_id == kInstantRendererPID) { 59 *origin = kInstantOrigin; 60 return true; 61 } 62 if (process_id == kNonInstantRendererPID) { 63 *origin = kNonInstantOrigin; 64 return true; 65 } 66 return false; 67 } 68}; 69 70class IframeSourceTest : public testing::Test { 71 public: 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 75 // those constraints. 76 IframeSourceTest() 77 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 78 resource_context_(&test_url_request_context_), 79 instant_io_context_(NULL), 80 response_(NULL) { 81 } 82 83 TestIframeSource* source() { return source_.get(); } 84 85 std::string response_string() { 86 if (response_.get()) { 87 return std::string(reinterpret_cast<const char*>(response_->front()), 88 response_->size()); 89 } 90 return ""; 91 } 92 93 net::URLRequest* MockRequest( 94 const std::string& url, 95 bool allocate_info, 96 int render_process_id, 97 int render_view_id) { 98 net::URLRequest* request = 99 new net::URLRequest(GURL(url), NULL, 100 resource_context_.GetRequestContext()); 101 if (allocate_info) { 102 content::ResourceRequestInfo::AllocateForTesting(request, 103 ResourceType::SUB_FRAME, 104 &resource_context_, 105 render_process_id, 106 render_view_id, 107 false); 108 } 109 return request; 110 } 111 112 void SendResource(int resource_id) { 113 source()->SendResource(resource_id, callback_); 114 } 115 116 void SendJSWithOrigin( 117 int resource_id, 118 int render_process_id, 119 int render_view_id) { 120 source()->SendJSWithOrigin(resource_id, render_process_id, render_view_id, 121 callback_); 122 } 123 124 private: 125 virtual void SetUp() OVERRIDE { 126 source_.reset(new TestIframeSource()); 127 callback_ = base::Bind(&IframeSourceTest::SaveResponse, 128 base::Unretained(this)); 129 instant_io_context_ = new InstantIOContext; 130 InstantIOContext::SetUserDataOnIO(&resource_context_, instant_io_context_); 131 InstantIOContext::AddInstantProcessOnIO(instant_io_context_, 132 kInstantRendererPID); 133 response_ = NULL; 134 } 135 136 virtual void TearDown() { 137 source_.reset(); 138 } 139 140 void SaveResponse(base::RefCountedMemory* data) { 141 response_ = data; 142 } 143 144 content::TestBrowserThreadBundle thread_bundle_; 145 146 net::TestURLRequestContext test_url_request_context_; 147 content::MockResourceContext resource_context_; 148 scoped_ptr<TestIframeSource> source_; 149 content::URLDataSource::GotDataCallback callback_; 150 scoped_refptr<InstantIOContext> instant_io_context_; 151 scoped_refptr<base::RefCountedMemory> response_; 152}; 153 154TEST_F(IframeSourceTest, ShouldServiceRequest) { 155 scoped_ptr<net::URLRequest> request; 156 request.reset(MockRequest("http://test/loader.js", true, 157 kNonInstantRendererPID, 0)); 158 EXPECT_FALSE(source()->ShouldServiceRequest(request.get())); 159 request.reset(MockRequest("chrome-search://bogus/valid.js", true, 160 kInstantRendererPID, 0)); 161 EXPECT_FALSE(source()->ShouldServiceRequest(request.get())); 162 request.reset(MockRequest("chrome-search://test/bogus.js", true, 163 kInstantRendererPID, 0)); 164 EXPECT_FALSE(source()->ShouldServiceRequest(request.get())); 165 request.reset(MockRequest("chrome-search://test/valid.js", true, 166 kInstantRendererPID, 0)); 167 EXPECT_TRUE(source()->ShouldServiceRequest(request.get())); 168 request.reset(MockRequest("chrome-search://test/valid.js", true, 169 kNonInstantRendererPID, 0)); 170 EXPECT_FALSE(source()->ShouldServiceRequest(request.get())); 171 request.reset(MockRequest("chrome-search://test/valid.js", true, 172 kInvalidRendererPID, 0)); 173 EXPECT_FALSE(source()->ShouldServiceRequest(request.get())); 174} 175 176TEST_F(IframeSourceTest, GetMimeType) { 177 // URLDataManagerBackend does not include / in path_and_query. 178 EXPECT_EQ("text/html", source()->GetMimeType("foo.html")); 179 EXPECT_EQ("application/javascript", source()->GetMimeType("foo.js")); 180 EXPECT_EQ("text/css", source()->GetMimeType("foo.css")); 181 EXPECT_EQ("image/png", source()->GetMimeType("foo.png")); 182 EXPECT_EQ("", source()->GetMimeType("bogus")); 183} 184 185TEST_F(IframeSourceTest, SendResource) { 186 SendResource(IDR_MOST_VISITED_TITLE_HTML); 187 EXPECT_FALSE(response_string().empty()); 188} 189 190TEST_F(IframeSourceTest, SendJSWithOrigin) { 191 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kInstantRendererPID, 0); 192 EXPECT_FALSE(response_string().empty()); 193 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kNonInstantRendererPID, 0); 194 EXPECT_FALSE(response_string().empty()); 195 SendJSWithOrigin(IDR_MOST_VISITED_TITLE_JS, kInvalidRendererPID, 0); 196 EXPECT_TRUE(response_string().empty()); 197} 198