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 "base/basictypes.h" 6#include "base/files/file_util.h" 7#include "base/files/scoped_temp_dir.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/message_loop/message_loop.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "base/run_loop.h" 12#include "content/public/test/async_file_test_helper.h" 13#include "content/public/test/test_file_system_context.h" 14#include "content/public/test/test_file_system_options.h" 15#include "storage/browser/fileapi/file_system_context.h" 16#include "storage/browser/fileapi/isolated_context.h" 17#include "storage/browser/fileapi/obfuscated_file_util.h" 18#include "storage/browser/fileapi/plugin_private_file_system_backend.h" 19#include "storage/common/fileapi/file_system_util.h" 20#include "testing/gtest/include/gtest/gtest.h" 21 22using content::AsyncFileTestHelper; 23using storage::FileSystemContext; 24using storage::FileSystemURL; 25using storage::IsolatedContext; 26 27namespace content { 28 29namespace { 30 31const GURL kOrigin("http://www.example.com"); 32const std::string kPlugin1("plugin1"); 33const std::string kPlugin2("plugin2"); 34const storage::FileSystemType kType = storage::kFileSystemTypePluginPrivate; 35const std::string kRootName = "pluginprivate"; 36 37void DidOpenFileSystem(base::File::Error* error_out, 38 base::File::Error error) { 39 *error_out = error; 40} 41 42std::string RegisterFileSystem() { 43 return IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 44 kType, kRootName, base::FilePath()); 45} 46 47} // namespace 48 49class PluginPrivateFileSystemBackendTest : public testing::Test { 50 protected: 51 virtual void SetUp() OVERRIDE { 52 ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); 53 context_ = CreateFileSystemContextForTesting( 54 NULL /* quota_manager_proxy */, 55 data_dir_.path()); 56 } 57 58 FileSystemURL CreateURL(const GURL& root_url, const std::string& relative) { 59 FileSystemURL root = context_->CrackURL(root_url); 60 return context_->CreateCrackedFileSystemURL( 61 root.origin(), 62 root.mount_type(), 63 root.virtual_path().AppendASCII(relative)); 64 } 65 66 storage::PluginPrivateFileSystemBackend* backend() const { 67 return context_->plugin_private_backend(); 68 } 69 70 const base::FilePath& base_path() const { return backend()->base_path(); } 71 72 base::ScopedTempDir data_dir_; 73 base::MessageLoop message_loop_; 74 scoped_refptr<FileSystemContext> context_; 75 std::string filesystem_id_; 76}; 77 78TEST_F(PluginPrivateFileSystemBackendTest, OpenFileSystemBasic) { 79 const std::string filesystem_id1 = RegisterFileSystem(); 80 base::File::Error error = base::File::FILE_ERROR_FAILED; 81 backend()->OpenPrivateFileSystem( 82 kOrigin, 83 kType, 84 filesystem_id1, 85 kPlugin1, 86 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 87 base::Bind(&DidOpenFileSystem, &error)); 88 base::RunLoop().RunUntilIdle(); 89 ASSERT_EQ(base::File::FILE_OK, error); 90 91 // Run this again with FAIL_IF_NONEXISTENT to see if it succeeds. 92 const std::string filesystem_id2 = RegisterFileSystem(); 93 error = base::File::FILE_ERROR_FAILED; 94 backend()->OpenPrivateFileSystem( 95 kOrigin, 96 kType, 97 filesystem_id2, 98 kPlugin1, 99 storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, 100 base::Bind(&DidOpenFileSystem, &error)); 101 base::RunLoop().RunUntilIdle(); 102 ASSERT_EQ(base::File::FILE_OK, error); 103 104 const GURL root_url(storage::GetIsolatedFileSystemRootURIString( 105 kOrigin, filesystem_id1, kRootName)); 106 FileSystemURL file = CreateURL(root_url, "foo"); 107 base::FilePath platform_path; 108 EXPECT_EQ(base::File::FILE_OK, 109 AsyncFileTestHelper::CreateFile(context_.get(), file)); 110 EXPECT_EQ(base::File::FILE_OK, 111 AsyncFileTestHelper::GetPlatformPath(context_.get(), file, 112 &platform_path)); 113 EXPECT_TRUE(base_path().AppendASCII("000").AppendASCII(kPlugin1).IsParent( 114 platform_path)); 115} 116 117TEST_F(PluginPrivateFileSystemBackendTest, PluginIsolation) { 118 // Open filesystem for kPlugin1 and kPlugin2. 119 const std::string filesystem_id1 = RegisterFileSystem(); 120 base::File::Error error = base::File::FILE_ERROR_FAILED; 121 backend()->OpenPrivateFileSystem( 122 kOrigin, 123 kType, 124 filesystem_id1, 125 kPlugin1, 126 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 127 base::Bind(&DidOpenFileSystem, &error)); 128 base::RunLoop().RunUntilIdle(); 129 ASSERT_EQ(base::File::FILE_OK, error); 130 131 const std::string filesystem_id2 = RegisterFileSystem(); 132 error = base::File::FILE_ERROR_FAILED; 133 backend()->OpenPrivateFileSystem( 134 kOrigin, 135 kType, 136 filesystem_id2, 137 kPlugin2, 138 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 139 base::Bind(&DidOpenFileSystem, &error)); 140 base::RunLoop().RunUntilIdle(); 141 ASSERT_EQ(base::File::FILE_OK, error); 142 143 // Create 'foo' in kPlugin1. 144 const GURL root_url1(storage::GetIsolatedFileSystemRootURIString( 145 kOrigin, filesystem_id1, kRootName)); 146 FileSystemURL file1 = CreateURL(root_url1, "foo"); 147 base::FilePath platform_path; 148 EXPECT_EQ(base::File::FILE_OK, 149 AsyncFileTestHelper::CreateFile(context_.get(), file1)); 150 EXPECT_TRUE(AsyncFileTestHelper::FileExists( 151 context_.get(), file1, AsyncFileTestHelper::kDontCheckSize)); 152 153 // See the same path is not available in kPlugin2. 154 const GURL root_url2(storage::GetIsolatedFileSystemRootURIString( 155 kOrigin, filesystem_id2, kRootName)); 156 FileSystemURL file2 = CreateURL(root_url2, "foo"); 157 EXPECT_FALSE(AsyncFileTestHelper::FileExists( 158 context_.get(), file2, AsyncFileTestHelper::kDontCheckSize)); 159} 160 161// TODO(kinuko,nhiroki): also test if DeleteOriginDataOnFileThread 162// works fine when there's multiple plugin partitions. 163 164} // namespace content 165