iframe_source_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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.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.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 "testing/gtest/include/gtest/gtest.h" 20#include "url/gurl.h" 21 22const int kNonInstantRendererPID = 0; 23const char kNonInstantOrigin[] = "http://evil"; 24const int kInstantRendererPID = 1; 25const char kInstantOrigin[] = "chrome-search://instant"; 26const int kInvalidRendererPID = 42; 27 28class TestIframeSource : public IframeSource { 29 public: 30 using IframeSource::GetMimeType; 31 using IframeSource::ShouldServiceRequest; 32 using IframeSource::SendResource; 33 using IframeSource::SendJSWithOrigin; 34 35 protected: 36 virtual std::string GetSource() const OVERRIDE { 37 return "test"; 38 } 39 40 virtual bool ServesPath(const std::string& path) const OVERRIDE { 41 return path == "/valid.html" || path == "/valid.js"; 42 } 43 44 virtual void StartDataRequest( 45 const std::string& path, 46 int render_process_id, 47 int render_view_id, 48 const content::URLDataSource::GotDataCallback& callback) OVERRIDE { 49 } 50 51 // RenderViewHost is hard to mock in concert with everything else, so stub 52 // this method out for testing. 53 virtual bool GetOrigin( 54 int process_id, 55 int render_view_id, 56 std::string* origin) const OVERRIDE { 57 if (process_id == kInstantRendererPID) { 58 *origin = kInstantOrigin; 59 return true; 60 } 61 if (process_id == kNonInstantRendererPID) { 62 *origin = kNonInstantOrigin; 63 return true; 64 } 65 return false; 66 } 67}; 68 69class IframeSourceTest : public testing::Test { 70 public: 71 // net::URLRequest wants to be executed with a message loop that has TYPE_IO. 72 // InstantIOContext needs to be created on the UI thread and have everything 73 // else happen on the IO thread. This setup is a hacky way to satisfy all 74 // those constraints. 75 IframeSourceTest() 76 : message_loop_(base::MessageLoop::TYPE_IO), 77 ui_thread_(content::BrowserThread::UI, &message_loop_), 78 io_thread_(content::BrowserThread::IO, &message_loop_), 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 } 108 return request; 109 } 110 111 void SendResource(int resource_id) { 112 source()->SendResource(resource_id, callback_); 113 } 114 115 void SendJSWithOrigin( 116 int resource_id, 117 int render_process_id, 118 int render_view_id) { 119 source()->SendJSWithOrigin(resource_id, render_process_id, render_view_id, 120 callback_); 121 } 122 123 private: 124 virtual void SetUp() { 125 source_.reset(new TestIframeSource()); 126 callback_ = base::Bind(&IframeSourceTest::SaveResponse, 127 base::Unretained(this)); 128 instant_io_context_ = new InstantIOContext; 129 InstantIOContext::SetUserDataOnIO(&resource_context_, instant_io_context_); 130 InstantIOContext::AddInstantProcessOnIO(instant_io_context_, 131 kInstantRendererPID); 132 response_ = NULL; 133 } 134 135 virtual void TearDown() { 136 source_.reset(); 137 } 138 139 void SaveResponse(base::RefCountedMemory* data) { 140 response_ = data; 141 } 142 143 base::MessageLoop message_loop_; 144 content::TestBrowserThread ui_thread_; 145 content::TestBrowserThread io_thread_; 146 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_OMNIBOX_RESULT_LOADER_HTML); 187 EXPECT_FALSE(response_string().empty()); 188} 189 190TEST_F(IframeSourceTest, SendJSWithOrigin) { 191 SendJSWithOrigin(IDR_OMNIBOX_RESULT_LOADER_JS, kInstantRendererPID, 0); 192 EXPECT_FALSE(response_string().empty()); 193 EXPECT_NE(std::string::npos, response_string().find(kInstantOrigin)); 194 SendJSWithOrigin(IDR_OMNIBOX_RESULT_LOADER_JS, kNonInstantRendererPID, 0); 195 EXPECT_FALSE(response_string().empty()); 196 EXPECT_NE(std::string::npos, response_string().find(kNonInstantOrigin)); 197 SendJSWithOrigin(IDR_OMNIBOX_RESULT_LOADER_JS, kInvalidRendererPID, 0); 198 EXPECT_TRUE(response_string().empty()); 199} 200