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:
SimpleDataSourceTest()52 SimpleDataSourceTest() {
53 for (int i = 0; i < kDataSize; ++i) {
54 data_[i] = i;
55 }
56 }
57
~SimpleDataSourceTest()58 virtual ~SimpleDataSourceTest() {
59 }
60
InitializeDataSource(const char * url,media::MockStatusCallback * callback)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
RequestSucceeded(bool is_loaded)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
RequestFailed()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
Redirect(const char * url)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
DestroyDataSource()125 void DestroyDataSource() {
126 data_source_->Stop(media::NewExpectedCallback());
127 MessageLoop::current()->RunAllPending();
128
129 data_source_ = NULL;
130 }
131
AsyncRead()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
TEST_F(SimpleDataSourceTest,InitializeHTTP)159 TEST_F(SimpleDataSourceTest, InitializeHTTP) {
160 InitializeDataSource(kHttpUrl,
161 media::NewExpectedStatusCallback(media::PIPELINE_OK));
162 RequestSucceeded(false);
163 DestroyDataSource();
164 }
165
TEST_F(SimpleDataSourceTest,InitializeHTTPS)166 TEST_F(SimpleDataSourceTest, InitializeHTTPS) {
167 InitializeDataSource(kHttpsUrl,
168 media::NewExpectedStatusCallback(media::PIPELINE_OK));
169 RequestSucceeded(false);
170 DestroyDataSource();
171 }
172
TEST_F(SimpleDataSourceTest,InitializeFile)173 TEST_F(SimpleDataSourceTest, InitializeFile) {
174 InitializeDataSource(kFileUrl,
175 media::NewExpectedStatusCallback(media::PIPELINE_OK));
176 RequestSucceeded(true);
177 DestroyDataSource();
178 }
179
TEST_F(SimpleDataSourceTest,InitializeData)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
TEST_F(SimpleDataSourceTest,RequestFailed)201 TEST_F(SimpleDataSourceTest, RequestFailed) {
202 InitializeDataSource(kHttpUrl,
203 media::NewExpectedStatusCallback(media::PIPELINE_ERROR_NETWORK));
204 RequestFailed();
205 DestroyDataSource();
206 }
207
TEST_F(SimpleDataSourceTest,StopWhenDownloading)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
TEST_F(SimpleDataSourceTest,AsyncRead)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.
TEST_F(SimpleDataSourceTest,HasSingleOrigin)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