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/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 "testing/gtest/include/gtest/gtest.h" 16 #include "webkit/browser/fileapi/file_system_context.h" 17 #include "webkit/browser/fileapi/isolated_context.h" 18 #include "webkit/browser/fileapi/obfuscated_file_util.h" 19 #include "webkit/browser/fileapi/plugin_private_file_system_backend.h" 20 #include "webkit/common/fileapi/file_system_util.h" 21 22 using content::AsyncFileTestHelper; 23 using fileapi::FileSystemContext; 24 using fileapi::FileSystemURL; 25 using fileapi::IsolatedContext; 26 27 namespace content { 28 29 namespace { 30 31 const GURL kOrigin("http://www.example.com"); 32 const std::string kPlugin1("plugin1"); 33 const std::string kPlugin2("plugin2"); 34 const fileapi::FileSystemType kType = fileapi::kFileSystemTypePluginPrivate; 35 const std::string kRootName = "pluginprivate"; 36 37 void DidOpenFileSystem(base::File::Error* error_out, 38 base::File::Error error) { 39 *error_out = error; 40 } 41 42 std::string RegisterFileSystem() { 43 return IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 44 kType, kRootName, base::FilePath()); 45 } 46 47 } // namespace 48 49 class 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 fileapi::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 78 TEST_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, kType, filesystem_id1, kPlugin1, 83 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 84 base::Bind(&DidOpenFileSystem, &error)); 85 base::RunLoop().RunUntilIdle(); 86 ASSERT_EQ(base::File::FILE_OK, error); 87 88 // Run this again with FAIL_IF_NONEXISTENT to see if it succeeds. 89 const std::string filesystem_id2 = RegisterFileSystem(); 90 error = base::File::FILE_ERROR_FAILED; 91 backend()->OpenPrivateFileSystem( 92 kOrigin, kType, filesystem_id2, kPlugin1, 93 fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, 94 base::Bind(&DidOpenFileSystem, &error)); 95 base::RunLoop().RunUntilIdle(); 96 ASSERT_EQ(base::File::FILE_OK, error); 97 98 const GURL root_url( 99 fileapi::GetIsolatedFileSystemRootURIString( 100 kOrigin, filesystem_id1, kRootName)); 101 FileSystemURL file = CreateURL(root_url, "foo"); 102 base::FilePath platform_path; 103 EXPECT_EQ(base::File::FILE_OK, 104 AsyncFileTestHelper::CreateFile(context_.get(), file)); 105 EXPECT_EQ(base::File::FILE_OK, 106 AsyncFileTestHelper::GetPlatformPath(context_.get(), file, 107 &platform_path)); 108 EXPECT_TRUE(base_path().AppendASCII("000").AppendASCII(kPlugin1).IsParent( 109 platform_path)); 110 } 111 112 TEST_F(PluginPrivateFileSystemBackendTest, PluginIsolation) { 113 // Open filesystem for kPlugin1 and kPlugin2. 114 const std::string filesystem_id1 = RegisterFileSystem(); 115 base::File::Error error = base::File::FILE_ERROR_FAILED; 116 backend()->OpenPrivateFileSystem( 117 kOrigin, kType, filesystem_id1, kPlugin1, 118 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 119 base::Bind(&DidOpenFileSystem, &error)); 120 base::RunLoop().RunUntilIdle(); 121 ASSERT_EQ(base::File::FILE_OK, error); 122 123 const std::string filesystem_id2 = RegisterFileSystem(); 124 error = base::File::FILE_ERROR_FAILED; 125 backend()->OpenPrivateFileSystem( 126 kOrigin, kType, filesystem_id2, kPlugin2, 127 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 128 base::Bind(&DidOpenFileSystem, &error)); 129 base::RunLoop().RunUntilIdle(); 130 ASSERT_EQ(base::File::FILE_OK, error); 131 132 // Create 'foo' in kPlugin1. 133 const GURL root_url1( 134 fileapi::GetIsolatedFileSystemRootURIString( 135 kOrigin, filesystem_id1, kRootName)); 136 FileSystemURL file1 = CreateURL(root_url1, "foo"); 137 base::FilePath platform_path; 138 EXPECT_EQ(base::File::FILE_OK, 139 AsyncFileTestHelper::CreateFile(context_.get(), file1)); 140 EXPECT_TRUE(AsyncFileTestHelper::FileExists( 141 context_.get(), file1, AsyncFileTestHelper::kDontCheckSize)); 142 143 // See the same path is not available in kPlugin2. 144 const GURL root_url2( 145 fileapi::GetIsolatedFileSystemRootURIString( 146 kOrigin, filesystem_id2, kRootName)); 147 FileSystemURL file2 = CreateURL(root_url2, "foo"); 148 EXPECT_FALSE(AsyncFileTestHelper::FileExists( 149 context_.get(), file2, AsyncFileTestHelper::kDontCheckSize)); 150 } 151 152 // TODO(kinuko,nhiroki): also test if DeleteOriginDataOnFileThread 153 // works fine when there's multiple plugin partitions. 154 155 } // namespace content 156