1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/fileapi/fileapi_message_filter.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <vector>
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/ref_counted.h"
112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/memory/shared_memory.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/process/process.h"
14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/browser/child_process_security_policy_impl.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/fileapi/chrome_blob_storage_context.h"
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "content/browser/streams/stream_registry.h"
17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/common/fileapi/file_system_messages.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/common/fileapi/webblob_messages.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/browser_thread.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/common/common_param_traits.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/mock_render_process_host.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/test_browser_context.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/test_browser_thread.h"
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/test/test_file_system_context.h"
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "net/base/io_buffer.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_storage_context.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/blob/blob_data.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace content {
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochnamespace {
342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kFakeBlobInternalUrlSpec[] =
362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "blob:blobinternal%3A///dc83ede4-9bbd-453b-be2e-60fd623fcc93";
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kFakeBlobInternalUrlSpec2[] =
382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "blob:blobinternal%3A///d28ae2e7-d233-4dda-9598-d135fe5d403e";
392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kFakeContentType[] = "fake/type";
412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}  // namespace
432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FileAPIMessageFilterTest : public testing::Test {
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FileAPIMessageFilterTest()
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : io_browser_thread_(BrowserThread::IO, &message_loop_) {
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch protected:
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void SetUp() OVERRIDE {
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    file_system_context_ =
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CreateFileSystemContextForTesting(NULL, base::FilePath());
54bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<storage::FileSystemType> types;
56bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    file_system_context_->GetFileSystemTypes(&types);
57bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    for (size_t i = 0; i < types.size(); ++i) {
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ChildProcessSecurityPolicyImpl::GetInstance()
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          ->RegisterFileSystemPermissionPolicy(
60bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch              types[i],
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              storage::FileSystemContext::GetPermissionPolicy(types[i]));
62bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    }
632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    stream_context_ = StreamContext::GetFor(&browser_context_);
652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    blob_storage_context_ = ChromeBlobStorageContext::GetFor(&browser_context_);
662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    filter_ = new FileAPIMessageFilter(
682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        0 /* process_id */,
692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        browser_context_.GetRequestContext(),
702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        file_system_context_.get(),
712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        blob_storage_context_,
722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        stream_context_);
732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Complete initialization.
752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    message_loop_.RunUntilIdle();
762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop message_loop_;
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestBrowserThread io_browser_thread_;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestBrowserContext browser_context_;
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<storage::FileSystemContext> file_system_context_;
832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamContext* stream_context_;
842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ChromeBlobStorageContext* blob_storage_context_;
852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<FileAPIMessageFilter> filter_;
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
89bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
90bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_refptr<FileAPIMessageFilter> filter(
91bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new FileAPIMessageFilter(
92bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          0 /* process_id */,
93bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          browser_context_.GetRequestContext(),
94bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          file_system_context_.get(),
952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          ChromeBlobStorageContext::GetFor(&browser_context_),
962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          StreamContext::GetFor(&browser_context_)));
97bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  filter->OnChannelConnected(0);
98bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
99bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Complete initialization.
100bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_.RunUntilIdle();
101bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
102bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  int request_id = 0;
103bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const GURL kUrl("filesystem:http://example.com/temporary/foo");
104bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter->OnMessageReceived(read_metadata));
106bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
107bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Close the filter while it has inflight request.
108bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  filter->OnChannelClosing();
109bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
110bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // This shouldn't cause DCHECK failure.
111bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_.RunUntilIdle();
112bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
113bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
114bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(FileAPIMessageFilterTest, MultipleFilters) {
115bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_refptr<FileAPIMessageFilter> filter1(
116bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new FileAPIMessageFilter(
117bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          0 /* process_id */,
118bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          browser_context_.GetRequestContext(),
119bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          file_system_context_.get(),
1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          ChromeBlobStorageContext::GetFor(&browser_context_),
1212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          StreamContext::GetFor(&browser_context_)));
122bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_refptr<FileAPIMessageFilter> filter2(
123bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new FileAPIMessageFilter(
124bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          1 /* process_id */,
125bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          browser_context_.GetRequestContext(),
126bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          file_system_context_.get(),
1272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          ChromeBlobStorageContext::GetFor(&browser_context_),
1282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          StreamContext::GetFor(&browser_context_)));
129bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  filter1->OnChannelConnected(0);
130bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  filter2->OnChannelConnected(1);
131bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
132bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Complete initialization.
133bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_.RunUntilIdle();
134bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
135bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  int request_id = 0;
136bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const GURL kUrl("filesystem:http://example.com/temporary/foo");
137bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter1->OnMessageReceived(read_metadata));
139bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
140bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Close the other filter before the request for filter1 is processed.
141bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  filter2->OnChannelClosing();
142bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
143bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // This shouldn't cause DCHECK failure.
144bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_.RunUntilIdle();
145bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
146bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
1482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamRegistry* stream_registry = stream_context_->registry();
1492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kUrl(kFakeBlobInternalUrlSpec);
1512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kDifferentUrl("blob:barfoo");
1522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
1542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(start_message));
1572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const int kBufferSize = 10;
1592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
1602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  int bytes_read = 0;
1612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Stream becomes available for read right after registration.
1642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream.get() == NULL);
1652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_EMPTY,
1662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
1672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(0, bytes_read);
1682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  stream = NULL;
1692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_FinishBuilding finish_message(kUrl);
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
1722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  stream = stream_registry->GetStream(kUrl);
1742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream.get() == NULL);
1752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_EMPTY,
1762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
1772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(0, bytes_read);
1782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Run loop to finish transfer.
1802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  message_loop_.RunUntilIdle();
1812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_COMPLETE,
1832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
1842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(0, bytes_read);
1852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Nothing should be returned for a URL we didn't use.
1872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_TRUE(stream_registry->GetStream(kDifferentUrl).get() == NULL);
1882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST_F(FileAPIMessageFilterTest, BuildNonEmptyStream) {
1912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamRegistry* stream_registry = stream_context_->registry();
1922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kUrl(kFakeBlobInternalUrlSpec);
1942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
1962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(start_message));
1992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::BlobData::Item item;
2012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const std::string kFakeData = "foobarbaz";
2022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  item.SetToBytes(kFakeData.data(), kFakeData.size());
2032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_AppendBlobDataItem append_message(kUrl, item);
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(append_message));
2052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_FinishBuilding finish_message(kUrl);
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
2082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Run loop to finish transfer and commit finalize command.
2102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  message_loop_.RunUntilIdle();
2112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
2132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  int bytes_read = 0;
2142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
2162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream.get() == NULL);
2172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_HAS_DATA,
2192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
2202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(kFakeData.size(), static_cast<size_t>(bytes_read));
2212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(kFakeData, std::string(buffer->data(), bytes_read));
2222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_COMPLETE,
2242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
2252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(0, bytes_read);
2262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
2272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
2292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamRegistry* stream_registry = stream_context_->registry();
2302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kUrl(kFakeBlobInternalUrlSpec);
2322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(NULL, stream_registry->GetStream(kUrl).get());
2342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // For win, we need to set valid PID to the filter.
2362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // OnAppendSharedMemoryToStream passes the peer process's handle to
2372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // SharedMemory's constructor. If it's incorrect, DuplicateHandle won't work
2382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // correctly.
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  filter_->set_peer_pid_for_testing(base::Process::Current().pid());
2402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(start_message));
2432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const std::string kFakeData = "foobarbaz";
2452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
2472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_TRUE(shared_memory->CreateAndMapAnonymous(kFakeData.size()));
2482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  memcpy(shared_memory->memory(), kFakeData.data(), kFakeData.size());
2492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_SyncAppendSharedMemory append_message(
2502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      kUrl, shared_memory->handle(), kFakeData.size());
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(append_message));
2522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_FinishBuilding finish_message(kUrl);
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
2552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Run loop to finish transfer and commit finalize command.
2572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  message_loop_.RunUntilIdle();
2582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
2602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  int bytes_read = 0;
2612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  scoped_refptr<Stream> stream = stream_registry->GetStream(kUrl);
2632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream.get() == NULL);
2642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_HAS_DATA,
2662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
2672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(kFakeData.size(), static_cast<size_t>(bytes_read));
2682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(kFakeData, std::string(buffer->data(), bytes_read));
2692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(Stream::STREAM_COMPLETE,
2712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            stream->ReadRawData(buffer.get(), kFakeData.size(), &bytes_read));
2722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  EXPECT_EQ(0, bytes_read);
2732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
2742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST_F(FileAPIMessageFilterTest, BuildStreamAndCallOnChannelClosing) {
2762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamRegistry* stream_registry = stream_context_->registry();
2772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kUrl(kFakeBlobInternalUrlSpec);
2792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(start_message));
2822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream_registry->GetStream(kUrl).get() == NULL);
2842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  filter_->OnChannelClosing();
2862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_EQ(NULL, stream_registry->GetStream(kUrl).get());
2882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
2892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST_F(FileAPIMessageFilterTest, CloneStream) {
2912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamRegistry* stream_registry = stream_context_->registry();
2922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kUrl(kFakeBlobInternalUrlSpec);
2942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const GURL kDestUrl(kFakeBlobInternalUrlSpec2);
2952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(start_message));
2982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  StreamHostMsg_Clone clone_message(kDestUrl, kUrl);
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(filter_->OnMessageReceived(clone_message));
3012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream_registry->GetStream(kUrl).get() == NULL);
3032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ASSERT_FALSE(stream_registry->GetStream(kDestUrl).get() == NULL);
3042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}  // namespace content
307