3a4c47e93eb758cd66dac8d55b1a67cf9aad35e1
[platform/framework/web/crosswalk.git] / src / content / browser / fileapi / fileapi_message_filter_unittest.cc
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 "content/browser/fileapi/fileapi_message_filter.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/shared_memory.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/process/process.h"
14 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/fileapi/chrome_blob_storage_context.h"
16 #include "content/browser/streams/stream_registry.h"
17 #include "content/common/fileapi/file_system_messages.h"
18 #include "content/common/fileapi/webblob_messages.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/common_param_traits.h"
21 #include "content/public/test/mock_render_process_host.h"
22 #include "content/public/test/test_browser_context.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "content/public/test/test_file_system_context.h"
25 #include "net/base/io_buffer.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "webkit/browser/blob/blob_storage_context.h"
28 #include "webkit/browser/fileapi/file_system_context.h"
29 #include "webkit/common/blob/blob_data.h"
30
31 namespace content {
32
33 namespace {
34
35 const char kFakeBlobInternalUrlSpec[] =
36     "blob:blobinternal%3A///dc83ede4-9bbd-453b-be2e-60fd623fcc93";
37 const char kFakeBlobInternalUrlSpec2[] =
38     "blob:blobinternal%3A///d28ae2e7-d233-4dda-9598-d135fe5d403e";
39
40 const char kFakeContentType[] = "fake/type";
41
42 }  // namespace
43
44 class FileAPIMessageFilterTest : public testing::Test {
45  public:
46   FileAPIMessageFilterTest()
47       : io_browser_thread_(BrowserThread::IO, &message_loop_) {
48   }
49
50  protected:
51   virtual void SetUp() OVERRIDE {
52     file_system_context_ =
53         CreateFileSystemContextForTesting(NULL, base::FilePath());
54
55     std::vector<fileapi::FileSystemType> types;
56     file_system_context_->GetFileSystemTypes(&types);
57     for (size_t i = 0; i < types.size(); ++i) {
58       ChildProcessSecurityPolicyImpl::GetInstance()->
59           RegisterFileSystemPermissionPolicy(
60               types[i],
61               fileapi::FileSystemContext::GetPermissionPolicy(types[i]));
62     }
63
64     stream_context_ = StreamContext::GetFor(&browser_context_);
65     blob_storage_context_ = ChromeBlobStorageContext::GetFor(&browser_context_);
66
67     filter_ = new FileAPIMessageFilter(
68         0 /* process_id */,
69         browser_context_.GetRequestContext(),
70         file_system_context_.get(),
71         blob_storage_context_,
72         stream_context_);
73
74     // Complete initialization.
75     message_loop_.RunUntilIdle();
76   }
77
78   base::MessageLoop message_loop_;
79   TestBrowserThread io_browser_thread_;
80
81   TestBrowserContext browser_context_;
82   scoped_refptr<fileapi::FileSystemContext> file_system_context_;
83   StreamContext* stream_context_;
84   ChromeBlobStorageContext* blob_storage_context_;
85
86   scoped_refptr<FileAPIMessageFilter> filter_;
87 };
88
89 TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
90   scoped_refptr<FileAPIMessageFilter> filter(
91       new FileAPIMessageFilter(
92           0 /* process_id */,
93           browser_context_.GetRequestContext(),
94           file_system_context_.get(),
95           ChromeBlobStorageContext::GetFor(&browser_context_),
96           StreamContext::GetFor(&browser_context_)));
97   filter->OnChannelConnected(0);
98
99   // Complete initialization.
100   message_loop_.RunUntilIdle();
101
102   int request_id = 0;
103   const GURL kUrl("filesystem:http://example.com/temporary/foo");
104   FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
105   EXPECT_TRUE(filter->OnMessageReceived(read_metadata));
106
107   // Close the filter while it has inflight request.
108   filter->OnChannelClosing();
109
110   // This shouldn't cause DCHECK failure.
111   message_loop_.RunUntilIdle();
112 }
113
114 TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
115   scoped_refptr<FileAPIMessageFilter> filter1(
116       new FileAPIMessageFilter(
117           0 /* process_id */,
118           browser_context_.GetRequestContext(),
119           file_system_context_.get(),
120           ChromeBlobStorageContext::GetFor(&browser_context_),
121           StreamContext::GetFor(&browser_context_)));
122   scoped_refptr<FileAPIMessageFilter> filter2(
123       new FileAPIMessageFilter(
124           1 /* process_id */,
125           browser_context_.GetRequestContext(),
126           file_system_context_.get(),
127           ChromeBlobStorageContext::GetFor(&browser_context_),
128           StreamContext::GetFor(&browser_context_)));
129   filter1->OnChannelConnected(0);
130   filter2->OnChannelConnected(1);
131
132   // Complete initialization.
133   message_loop_.RunUntilIdle();
134
135   int request_id = 0;
136   const GURL kUrl("filesystem:http://example.com/temporary/foo");
137   FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
138   EXPECT_TRUE(filter1->OnMessageReceived(read_metadata));
139
140   // Close the other filter before the request for filter1 is processed.
141   filter2->OnChannelClosing();
142
143   // This shouldn't cause DCHECK failure.
144   message_loop_.RunUntilIdle();
145 }
146
147 TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
148   StreamRegistry* stream_registry = stream_context_->registry();
149
150   const GURL kUrl(kFakeBlobInternalUrlSpec);
151   const GURL kDifferentUrl("blob:barfoo");
152
153   EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
154
155   StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
156   EXPECT_TRUE(filter_->OnMessageReceived(start_message));
157
158   const int kBufferSize = 10;
159   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
160   int bytes_read = 0;
161
162   scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
163   // Stream becomes available for read right after registration.
164   ASSERT_FALSE(stream.get() == NULL);
165   EXPECT_EQ(Stream::STREAM_EMPTY,
166             stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
167   EXPECT_EQ(0, bytes_read);
168   stream = NULL;
169
170   StreamHostMsg_FinishBuilding finish_message(kUrl);
171   EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
172
173   stream = stream_registry->GetStream(kUrl);
174   ASSERT_FALSE(stream.get() == NULL);
175   EXPECT_EQ(Stream::STREAM_EMPTY,
176             stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
177   EXPECT_EQ(0, bytes_read);
178
179   // Run loop to finish transfer.
180   message_loop_.RunUntilIdle();
181
182   EXPECT_EQ(Stream::STREAM_COMPLETE,
183             stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
184   EXPECT_EQ(0, bytes_read);
185
186   // Nothing should be returned for a URL we didn't use.
187   EXPECT_TRUE(stream_registry->GetStream(kDifferentUrl).get() == NULL);
188 }
189
190 TEST_F(FileAPIMessageFilterTest, BuildNonEmptyStream) {
191   StreamRegistry* stream_registry = stream_context_->registry();
192
193   const GURL kUrl(kFakeBlobInternalUrlSpec);
194
195   EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
196
197   StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
198   EXPECT_TRUE(filter_->OnMessageReceived(start_message));
199
200   webkit_blob::BlobData::Item item;
201   const std::string kFakeData = "foobarbaz";
202   item.SetToBytes(kFakeData.data(), kFakeData.size());
203   StreamHostMsg_AppendBlobDataItem append_message(kUrl, item);
204   EXPECT_TRUE(filter_->OnMessageReceived(append_message));
205
206   StreamHostMsg_FinishBuilding finish_message(kUrl);
207   EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
208
209   // Run loop to finish transfer and commit finalize command.
210   message_loop_.RunUntilIdle();
211
212   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
213   int bytes_read = 0;
214
215   scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
216   ASSERT_FALSE(stream.get() == NULL);
217
218   EXPECT_EQ(Stream::STREAM_HAS_DATA,
219             stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
220   EXPECT_EQ(kFakeData.size(), static_cast<size_t>(bytes_read));
221   EXPECT_EQ(kFakeData, std::string(buffer->data(), bytes_read));
222
223   EXPECT_EQ(Stream::STREAM_COMPLETE,
224             stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
225   EXPECT_EQ(0, bytes_read);
226 }
227
228 TEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
229   StreamRegistry* stream_registry = stream_context_->registry();
230
231   const GURL kUrl(kFakeBlobInternalUrlSpec);
232
233   EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
234
235   // For win, we need to set valid PID to the filter.
236   // OnAppendSharedMemoryToStream passes the peer process's handle to
237   // SharedMemory's constructor. If it's incorrect, DuplicateHandle won't work
238   // correctly.
239   filter_->set_peer_pid_for_testing(base::Process::Current().pid());
240
241   StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
242   EXPECT_TRUE(filter_->OnMessageReceived(start_message));
243
244   const std::string kFakeData = "foobarbaz";
245
246   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
247   ASSERT_TRUE(shared_memory->CreateAndMapAnonymous(kFakeData.size()));
248   memcpy(shared_memory->memory(), kFakeData.data(), kFakeData.size());
249   StreamHostMsg_SyncAppendSharedMemory append_message(
250       kUrl, shared_memory->handle(), kFakeData.size());
251   EXPECT_TRUE(filter_->OnMessageReceived(append_message));
252
253   StreamHostMsg_FinishBuilding finish_message(kUrl);
254   EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
255
256   // Run loop to finish transfer and commit finalize command.
257   message_loop_.RunUntilIdle();
258
259   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
260   int bytes_read = 0;
261
262   scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
263   ASSERT_FALSE(stream.get() == NULL);
264
265   EXPECT_EQ(Stream::STREAM_HAS_DATA,
266             stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
267   EXPECT_EQ(kFakeData.size(), static_cast<size_t>(bytes_read));
268   EXPECT_EQ(kFakeData, std::string(buffer->data(), bytes_read));
269
270   EXPECT_EQ(Stream::STREAM_COMPLETE,
271             stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
272   EXPECT_EQ(0, bytes_read);
273 }
274
275 TEST_F(FileAPIMessageFilterTest, BuildStreamAndCallOnChannelClosing) {
276   StreamRegistry* stream_registry = stream_context_->registry();
277
278   const GURL kUrl(kFakeBlobInternalUrlSpec);
279
280   StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
281   EXPECT_TRUE(filter_->OnMessageReceived(start_message));
282
283   ASSERT_FALSE(stream_registry->GetStream(kUrl).get() == NULL);
284
285   filter_->OnChannelClosing();
286
287   ASSERT_EQ(NULL, stream_registry->GetStream(kUrl).get());
288 }
289
290 TEST_F(FileAPIMessageFilterTest, CloneStream) {
291   StreamRegistry* stream_registry = stream_context_->registry();
292
293   const GURL kUrl(kFakeBlobInternalUrlSpec);
294   const GURL kDestUrl(kFakeBlobInternalUrlSpec2);
295
296   StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
297   EXPECT_TRUE(filter_->OnMessageReceived(start_message));
298
299   StreamHostMsg_Clone clone_message(kDestUrl, kUrl);
300   EXPECT_TRUE(filter_->OnMessageReceived(clone_message));
301
302   ASSERT_FALSE(stream_registry->GetStream(kUrl).get() == NULL);
303   ASSERT_FALSE(stream_registry->GetStream(kDestUrl).get() == NULL);
304 }
305
306 }  // namespace content