1 // Copyright (c) 2011 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 "media/base/filters.h" 6 #include "media/base/mock_callback.h" 7 #include "media/base/mock_filter_host.h" 8 #include "media/base/mock_filters.h" 9 #include "net/base/net_errors.h" 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h" 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h" 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 15 #include "webkit/glue/media/simple_data_source.h" 16 #include "webkit/mocks/mock_webframe.h" 17 #include "webkit/mocks/mock_weburlloader.h" 18 19 using ::testing::_; 20 using ::testing::DoAll; 21 using ::testing::InSequence; 22 using ::testing::Invoke; 23 using ::testing::NiceMock; 24 using ::testing::NotNull; 25 using ::testing::Return; 26 using ::testing::SetArgumentPointee; 27 using ::testing::StrictMock; 28 using ::testing::WithArgs; 29 30 using WebKit::WebURLError; 31 using WebKit::WebURLLoader; 32 using WebKit::WebURLRequest; 33 using WebKit::WebURLResponse; 34 35 namespace webkit_glue { 36 37 static const int kDataSize = 1024; 38 static const char kHttpUrl[] = "http://test"; 39 static const char kHttpsUrl[] = "https://test"; 40 static const char kFileUrl[] = "file://test"; 41 static const char kDataUrl[] = 42 "data:text/plain;base64,YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoK"; 43 static const char kDataUrlDecoded[] = "abcdefghijklmnopqrstuvwxyz"; 44 static const char kInvalidUrl[] = "whatever://test"; 45 static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing"; 46 static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2"; 47 static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2"; 48 static const char kHttpRedirectToDifferentDomainUrl2[] = "http://test2/ing"; 49 50 class SimpleDataSourceTest : public testing::Test { 51 public: 52 SimpleDataSourceTest() { 53 for (int i = 0; i < kDataSize; ++i) { 54 data_[i] = i; 55 } 56 } 57 58 virtual ~SimpleDataSourceTest() { 59 } 60 61 void InitializeDataSource(const char* url, 62 media::MockStatusCallback* callback) { 63 gurl_ = GURL(url); 64 65 frame_.reset(new NiceMock<MockWebFrame>()); 66 url_loader_ = new NiceMock<MockWebURLLoader>(); 67 68 data_source_ = new SimpleDataSource(MessageLoop::current(), 69 frame_.get()); 70 71 // There is no need to provide a message loop to data source. 72 data_source_->set_host(&host_); 73 data_source_->SetURLLoaderForTest(url_loader_); 74 75 data_source_->Initialize(url, callback); 76 MessageLoop::current()->RunAllPending(); 77 } 78 79 void RequestSucceeded(bool is_loaded) { 80 WebURLResponse response(gurl_); 81 response.setExpectedContentLength(kDataSize); 82 83 data_source_->didReceiveResponse(NULL, response); 84 int64 size; 85 EXPECT_TRUE(data_source_->GetSize(&size)); 86 EXPECT_EQ(kDataSize, size); 87 88 for (int i = 0; i < kDataSize; ++i) { 89 data_source_->didReceiveData(NULL, data_ + i, 1, 1); 90 } 91 92 EXPECT_CALL(host_, SetLoaded(is_loaded)); 93 94 InSequence s; 95 EXPECT_CALL(host_, SetTotalBytes(kDataSize)); 96 EXPECT_CALL(host_, SetBufferedBytes(kDataSize)); 97 98 data_source_->didFinishLoading(NULL, 0); 99 100 // Let the tasks to be executed. 101 MessageLoop::current()->RunAllPending(); 102 } 103 104 void RequestFailed() { 105 InSequence s; 106 107 WebURLError error; 108 error.reason = net::ERR_FAILED; 109 data_source_->didFail(NULL, error); 110 111 // Let the tasks to be executed. 112 MessageLoop::current()->RunAllPending(); 113 } 114 115 void Redirect(const char* url) { 116 GURL redirectUrl(url); 117 WebKit::WebURLRequest newRequest(redirectUrl); 118 WebKit::WebURLResponse redirectResponse(gurl_); 119 120 data_source_->willSendRequest(url_loader_, newRequest, redirectResponse); 121 122 MessageLoop::current()->RunAllPending(); 123 } 124 125 void DestroyDataSource() { 126 data_source_->Stop(media::NewExpectedCallback()); 127 MessageLoop::current()->RunAllPending(); 128 129 data_source_ = NULL; 130 } 131 132 void AsyncRead() { 133 for (int i = 0; i < kDataSize; ++i) { 134 uint8 buffer[1]; 135 136 EXPECT_CALL(*this, ReadCallback(1)); 137 data_source_->Read( 138 i, 1, buffer, 139 NewCallback(this, &SimpleDataSourceTest::ReadCallback)); 140 EXPECT_EQ(static_cast<uint8>(data_[i]), buffer[0]); 141 } 142 } 143 144 MOCK_METHOD1(ReadCallback, void(size_t size)); 145 146 protected: 147 GURL gurl_; 148 scoped_ptr<MessageLoop> message_loop_; 149 NiceMock<MockWebURLLoader>* url_loader_; 150 scoped_refptr<SimpleDataSource> data_source_; 151 StrictMock<media::MockFilterHost> host_; 152 scoped_ptr<NiceMock<MockWebFrame> > frame_; 153 154 char data_[kDataSize]; 155 156 DISALLOW_COPY_AND_ASSIGN(SimpleDataSourceTest); 157 }; 158 159 TEST_F(SimpleDataSourceTest, InitializeHTTP) { 160 InitializeDataSource(kHttpUrl, 161 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 162 RequestSucceeded(false); 163 DestroyDataSource(); 164 } 165 166 TEST_F(SimpleDataSourceTest, InitializeHTTPS) { 167 InitializeDataSource(kHttpsUrl, 168 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 169 RequestSucceeded(false); 170 DestroyDataSource(); 171 } 172 173 TEST_F(SimpleDataSourceTest, InitializeFile) { 174 InitializeDataSource(kFileUrl, 175 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 176 RequestSucceeded(true); 177 DestroyDataSource(); 178 } 179 180 TEST_F(SimpleDataSourceTest, InitializeData) { 181 frame_.reset(new NiceMock<MockWebFrame>()); 182 url_loader_ = new NiceMock<MockWebURLLoader>(); 183 184 data_source_ = new SimpleDataSource(MessageLoop::current(), 185 frame_.get()); 186 // There is no need to provide a message loop to data source. 187 data_source_->set_host(&host_); 188 data_source_->SetURLLoaderForTest(url_loader_); 189 190 EXPECT_CALL(host_, SetLoaded(true)); 191 EXPECT_CALL(host_, SetTotalBytes(sizeof(kDataUrlDecoded))); 192 EXPECT_CALL(host_, SetBufferedBytes(sizeof(kDataUrlDecoded))); 193 194 data_source_->Initialize(kDataUrl, 195 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 196 MessageLoop::current()->RunAllPending(); 197 198 DestroyDataSource(); 199 } 200 201 TEST_F(SimpleDataSourceTest, RequestFailed) { 202 InitializeDataSource(kHttpUrl, 203 media::NewExpectedStatusCallback(media::PIPELINE_ERROR_NETWORK)); 204 RequestFailed(); 205 DestroyDataSource(); 206 } 207 208 TEST_F(SimpleDataSourceTest, StopWhenDownloading) { 209 // The callback should be deleted, but not executed. 210 // TODO(scherkus): should this really be the behaviour? Seems strange... 211 StrictMock<media::MockStatusCallback>* callback = 212 new StrictMock<media::MockStatusCallback>(); 213 EXPECT_CALL(*callback, Destructor()); 214 215 InitializeDataSource(kHttpUrl, callback); 216 217 EXPECT_CALL(*url_loader_, cancel()); 218 DestroyDataSource(); 219 } 220 221 TEST_F(SimpleDataSourceTest, AsyncRead) { 222 InitializeDataSource(kFileUrl, 223 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 224 RequestSucceeded(true); 225 AsyncRead(); 226 DestroyDataSource(); 227 } 228 229 // NOTE: This test will need to be reworked a little once 230 // http://code.google.com/p/chromium/issues/detail?id=72578 231 // is fixed. 232 TEST_F(SimpleDataSourceTest, HasSingleOrigin) { 233 // Make sure no redirect case works as expected. 234 InitializeDataSource(kHttpUrl, 235 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 236 RequestSucceeded(false); 237 EXPECT_TRUE(data_source_->HasSingleOrigin()); 238 DestroyDataSource(); 239 240 // Test redirect to the same domain. 241 InitializeDataSource(kHttpUrl, 242 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 243 Redirect(kHttpRedirectToSameDomainUrl1); 244 RequestSucceeded(false); 245 EXPECT_TRUE(data_source_->HasSingleOrigin()); 246 DestroyDataSource(); 247 248 // Test redirect twice to the same domain. 249 InitializeDataSource(kHttpUrl, 250 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 251 Redirect(kHttpRedirectToSameDomainUrl1); 252 Redirect(kHttpRedirectToSameDomainUrl2); 253 RequestSucceeded(false); 254 EXPECT_TRUE(data_source_->HasSingleOrigin()); 255 DestroyDataSource(); 256 257 // Test redirect to a different domain. 258 InitializeDataSource(kHttpUrl, 259 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 260 Redirect(kHttpRedirectToDifferentDomainUrl1); 261 RequestSucceeded(false); 262 EXPECT_FALSE(data_source_->HasSingleOrigin()); 263 DestroyDataSource(); 264 265 // Test redirect to the same domain and then to a different domain. 266 InitializeDataSource(kHttpUrl, 267 media::NewExpectedStatusCallback(media::PIPELINE_OK)); 268 Redirect(kHttpRedirectToSameDomainUrl1); 269 Redirect(kHttpRedirectToDifferentDomainUrl1); 270 RequestSucceeded(false); 271 EXPECT_FALSE(data_source_->HasSingleOrigin()); 272 DestroyDataSource(); 273 } 274 275 } // namespace webkit_glue 276