Home | History | Annotate | Download | only in fileapi
      1 // Copyright (c) 2012 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 <set>
      6 #include <string>
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/file_util.h"
     11 #include "base/files/file_path.h"
     12 #include "base/files/scoped_temp_dir.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/platform_file.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "webkit/browser/fileapi/async_file_test_helper.h"
     18 #include "webkit/browser/fileapi/external_mount_points.h"
     19 #include "webkit/browser/fileapi/file_system_backend.h"
     20 #include "webkit/browser/fileapi/file_system_context.h"
     21 #include "webkit/browser/fileapi/file_system_operation_context.h"
     22 #include "webkit/browser/fileapi/file_system_usage_cache.h"
     23 #include "webkit/browser/fileapi/mock_file_change_observer.h"
     24 #include "webkit/browser/fileapi/mock_file_system_context.h"
     25 #include "webkit/browser/fileapi/obfuscated_file_util.h"
     26 #include "webkit/browser/fileapi/sandbox_directory_database.h"
     27 #include "webkit/browser/fileapi/sandbox_file_system_test_helper.h"
     28 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
     29 #include "webkit/browser/fileapi/sandbox_origin_database.h"
     30 #include "webkit/browser/fileapi/test_file_set.h"
     31 #include "webkit/browser/quota/mock_special_storage_policy.h"
     32 #include "webkit/browser/quota/quota_manager.h"
     33 #include "webkit/common/database/database_identifier.h"
     34 #include "webkit/common/quota/quota_types.h"
     35 
     36 namespace fileapi {
     37 
     38 namespace {
     39 
     40 bool FileExists(const base::FilePath& path) {
     41   return base::PathExists(path) && !base::DirectoryExists(path);
     42 }
     43 
     44 int64 GetSize(const base::FilePath& path) {
     45   int64 size;
     46   EXPECT_TRUE(file_util::GetFileSize(path, &size));
     47   return size;
     48 }
     49 
     50 // After a move, the dest exists and the source doesn't.
     51 // After a copy, both source and dest exist.
     52 struct CopyMoveTestCaseRecord {
     53   bool is_copy_not_move;
     54   const char source_path[64];
     55   const char dest_path[64];
     56   bool cause_overwrite;
     57 };
     58 
     59 const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
     60   // This is the combinatoric set of:
     61   //  rename vs. same-name
     62   //  different directory vs. same directory
     63   //  overwrite vs. no-overwrite
     64   //  copy vs. move
     65   //  We can never be called with source and destination paths identical, so
     66   //  those cases are omitted.
     67   {true, "dir0/file0", "dir0/file1", false},
     68   {false, "dir0/file0", "dir0/file1", false},
     69   {true, "dir0/file0", "dir0/file1", true},
     70   {false, "dir0/file0", "dir0/file1", true},
     71 
     72   {true, "dir0/file0", "dir1/file0", false},
     73   {false, "dir0/file0", "dir1/file0", false},
     74   {true, "dir0/file0", "dir1/file0", true},
     75   {false, "dir0/file0", "dir1/file0", true},
     76   {true, "dir0/file0", "dir1/file1", false},
     77   {false, "dir0/file0", "dir1/file1", false},
     78   {true, "dir0/file0", "dir1/file1", true},
     79   {false, "dir0/file0", "dir1/file1", true},
     80 };
     81 
     82 struct OriginEnumerationTestRecord {
     83   std::string origin_url;
     84   bool has_temporary;
     85   bool has_persistent;
     86 };
     87 
     88 const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
     89   {"http://example.com", false, true},
     90   {"http://example1.com", true, false},
     91   {"https://example1.com", true, true},
     92   {"file://", false, true},
     93   {"http://example.com:8000", false, true},
     94 };
     95 
     96 FileSystemURL FileSystemURLAppend(
     97     const FileSystemURL& url, const base::FilePath::StringType& child) {
     98   return FileSystemURL::CreateForTest(
     99       url.origin(), url.mount_type(), url.virtual_path().Append(child));
    100 }
    101 
    102 FileSystemURL FileSystemURLAppendUTF8(
    103     const FileSystemURL& url, const std::string& child) {
    104   return FileSystemURL::CreateForTest(
    105       url.origin(),
    106       url.mount_type(),
    107       url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
    108 }
    109 
    110 FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
    111   return FileSystemURL::CreateForTest(
    112       url.origin(), url.mount_type(), VirtualPath::DirName(url.virtual_path()));
    113 }
    114 
    115 }  // namespace (anonymous)
    116 
    117 // TODO(ericu): The vast majority of this and the other FSFU subclass tests
    118 // could theoretically be shared.  It would basically be a FSFU interface
    119 // compliance test, and only the subclass-specific bits that look into the
    120 // implementation would need to be written per-subclass.
    121 class ObfuscatedFileUtilTest : public testing::Test {
    122  public:
    123   ObfuscatedFileUtilTest()
    124       : origin_(GURL("http://www.example.com")),
    125         type_(kFileSystemTypeTemporary),
    126         weak_factory_(this),
    127         sandbox_file_system_(origin_, type_),
    128         quota_status_(quota::kQuotaStatusUnknown),
    129         usage_(-1) {
    130   }
    131 
    132   virtual void SetUp() {
    133     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
    134 
    135     storage_policy_ = new quota::MockSpecialStoragePolicy();
    136 
    137     quota_manager_ =
    138         new quota::QuotaManager(false /* is_incognito */,
    139                                 data_dir_.path(),
    140                                 base::MessageLoopProxy::current().get(),
    141                                 base::MessageLoopProxy::current().get(),
    142                                 storage_policy_.get());
    143 
    144     // Every time we create a new sandbox_file_system helper,
    145     // it creates another context, which creates another path manager,
    146     // another sandbox_backend, and another OFU.
    147     // We need to pass in the context to skip all that.
    148     file_system_context_ = CreateFileSystemContextForTesting(
    149         quota_manager_->proxy(),
    150         data_dir_.path());
    151 
    152     sandbox_file_system_.SetUp(file_system_context_.get());
    153 
    154     change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
    155   }
    156 
    157   virtual void TearDown() {
    158     quota_manager_ = NULL;
    159     sandbox_file_system_.TearDown();
    160   }
    161 
    162   scoped_ptr<FileSystemOperationContext> LimitedContext(
    163       int64 allowed_bytes_growth) {
    164     scoped_ptr<FileSystemOperationContext> context(
    165         sandbox_file_system_.NewOperationContext());
    166     context->set_allowed_bytes_growth(allowed_bytes_growth);
    167     return context.Pass();
    168   }
    169 
    170   scoped_ptr<FileSystemOperationContext> UnlimitedContext() {
    171     return LimitedContext(kint64max);
    172   }
    173 
    174   FileSystemOperationContext* NewContext(
    175       SandboxFileSystemTestHelper* file_system) {
    176     change_observer()->ResetCount();
    177     FileSystemOperationContext* context;
    178     if (file_system)
    179       context = file_system->NewOperationContext();
    180     else
    181       context = sandbox_file_system_.NewOperationContext();
    182     // Setting allowed_bytes_growth big enough for all tests.
    183     context->set_allowed_bytes_growth(1024 * 1024);
    184     context->set_change_observers(change_observers());
    185     return context;
    186   }
    187 
    188   const ChangeObserverList& change_observers() const {
    189     return change_observers_;
    190   }
    191 
    192   MockFileChangeObserver* change_observer() {
    193     return &change_observer_;
    194   }
    195 
    196   // This can only be used after SetUp has run and created file_system_context_
    197   // and obfuscated_file_util_.
    198   // Use this for tests which need to run in multiple origins; we need a test
    199   // helper per origin.
    200   SandboxFileSystemTestHelper* NewFileSystem(
    201       const GURL& origin, fileapi::FileSystemType type) {
    202     SandboxFileSystemTestHelper* file_system =
    203         new SandboxFileSystemTestHelper(origin, type);
    204 
    205     file_system->SetUp(file_system_context_.get());
    206     return file_system;
    207   }
    208 
    209   ObfuscatedFileUtil* ofu() {
    210     return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
    211   }
    212 
    213   const base::FilePath& test_directory() const {
    214     return data_dir_.path();
    215   }
    216 
    217   const GURL& origin() const {
    218     return origin_;
    219   }
    220 
    221   fileapi::FileSystemType type() const {
    222     return type_;
    223   }
    224 
    225   int64 ComputeTotalFileSize() {
    226     return sandbox_file_system_.ComputeCurrentOriginUsage() -
    227         sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
    228   }
    229 
    230   void GetUsageFromQuotaManager() {
    231     int64 quota = -1;
    232     quota_status_ =
    233         AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
    234                                               origin(),
    235                                               sandbox_file_system_.type(),
    236                                               &usage_,
    237                                               &quota);
    238     EXPECT_EQ(quota::kQuotaStatusOk, quota_status_);
    239   }
    240 
    241   void RevokeUsageCache() {
    242     quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
    243     usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
    244   }
    245 
    246   int64 SizeByQuotaUtil() {
    247     return sandbox_file_system_.GetCachedOriginUsage();
    248   }
    249 
    250   int64 SizeInUsageFile() {
    251     base::MessageLoop::current()->RunUntilIdle();
    252     int64 usage = 0;
    253     return usage_cache()->GetUsage(
    254         sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
    255   }
    256 
    257   bool PathExists(const FileSystemURL& url) {
    258     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    259     base::PlatformFileInfo file_info;
    260     base::FilePath platform_path;
    261     base::PlatformFileError error = ofu()->GetFileInfo(
    262         context.get(), url, &file_info, &platform_path);
    263     return error == base::PLATFORM_FILE_OK;
    264   }
    265 
    266   bool DirectoryExists(const FileSystemURL& url) {
    267     return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
    268   }
    269 
    270   int64 usage() const { return usage_; }
    271   FileSystemUsageCache* usage_cache() {
    272     return sandbox_file_system_.usage_cache();
    273   }
    274 
    275   FileSystemURL CreateURLFromUTF8(const std::string& path) {
    276     return sandbox_file_system_.CreateURLFromUTF8(path);
    277   }
    278 
    279   int64 PathCost(const FileSystemURL& url) {
    280     return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
    281   }
    282 
    283   FileSystemURL CreateURL(const base::FilePath& path) {
    284     return sandbox_file_system_.CreateURL(path);
    285   }
    286 
    287   void CheckFileAndCloseHandle(
    288       const FileSystemURL& url, base::PlatformFile file_handle) {
    289     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    290     base::FilePath local_path;
    291     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
    292         context.get(), url, &local_path));
    293 
    294     base::PlatformFileInfo file_info0;
    295     base::FilePath data_path;
    296     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    297         context.get(), url, &file_info0, &data_path));
    298     EXPECT_EQ(data_path, local_path);
    299     EXPECT_TRUE(FileExists(data_path));
    300     EXPECT_EQ(0, GetSize(data_path));
    301 
    302     const char data[] = "test data";
    303     const int length = arraysize(data) - 1;
    304 
    305     if (base::kInvalidPlatformFileValue == file_handle) {
    306       bool created = true;
    307       base::PlatformFileError error;
    308       file_handle = base::CreatePlatformFile(
    309           data_path,
    310           base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
    311           &created,
    312           &error);
    313       ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
    314       ASSERT_EQ(base::PLATFORM_FILE_OK, error);
    315       EXPECT_FALSE(created);
    316     }
    317     ASSERT_EQ(length, base::WritePlatformFile(file_handle, 0, data, length));
    318     EXPECT_TRUE(base::ClosePlatformFile(file_handle));
    319 
    320     base::PlatformFileInfo file_info1;
    321     EXPECT_EQ(length, GetSize(data_path));
    322     context.reset(NewContext(NULL));
    323     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    324         context.get(), url, &file_info1, &data_path));
    325     EXPECT_EQ(data_path, local_path);
    326 
    327     EXPECT_FALSE(file_info0.is_directory);
    328     EXPECT_FALSE(file_info1.is_directory);
    329     EXPECT_FALSE(file_info0.is_symbolic_link);
    330     EXPECT_FALSE(file_info1.is_symbolic_link);
    331     EXPECT_EQ(0, file_info0.size);
    332     EXPECT_EQ(length, file_info1.size);
    333     EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
    334 
    335     context.reset(NewContext(NULL));
    336     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
    337         context.get(), url, length * 2));
    338     EXPECT_EQ(length * 2, GetSize(data_path));
    339 
    340     context.reset(NewContext(NULL));
    341     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
    342         context.get(), url, 0));
    343     EXPECT_EQ(0, GetSize(data_path));
    344   }
    345 
    346   void ValidateTestDirectory(
    347       const FileSystemURL& root_url,
    348       const std::set<base::FilePath::StringType>& files,
    349       const std::set<base::FilePath::StringType>& directories) {
    350     scoped_ptr<FileSystemOperationContext> context;
    351     std::set<base::FilePath::StringType>::const_iterator iter;
    352     for (iter = files.begin(); iter != files.end(); ++iter) {
    353       bool created = true;
    354       context.reset(NewContext(NULL));
    355       ASSERT_EQ(base::PLATFORM_FILE_OK,
    356           ofu()->EnsureFileExists(
    357               context.get(), FileSystemURLAppend(root_url, *iter),
    358               &created));
    359       ASSERT_FALSE(created);
    360     }
    361     for (iter = directories.begin(); iter != directories.end(); ++iter) {
    362       context.reset(NewContext(NULL));
    363       EXPECT_TRUE(DirectoryExists(
    364           FileSystemURLAppend(root_url, *iter)));
    365     }
    366   }
    367 
    368   class UsageVerifyHelper {
    369    public:
    370     UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context,
    371                       SandboxFileSystemTestHelper* file_system,
    372                       int64 expected_usage)
    373         : context_(context.Pass()),
    374           sandbox_file_system_(file_system),
    375           expected_usage_(expected_usage) {}
    376 
    377     ~UsageVerifyHelper() {
    378       base::MessageLoop::current()->RunUntilIdle();
    379       Check();
    380     }
    381 
    382     FileSystemOperationContext* context() {
    383       return context_.get();
    384     }
    385 
    386    private:
    387     void Check() {
    388       ASSERT_EQ(expected_usage_,
    389                 sandbox_file_system_->GetCachedOriginUsage());
    390     }
    391 
    392     scoped_ptr<FileSystemOperationContext> context_;
    393     SandboxFileSystemTestHelper* sandbox_file_system_;
    394     int64 expected_usage_;
    395   };
    396 
    397   scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) {
    398     int64 usage = sandbox_file_system_.GetCachedOriginUsage();
    399     return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
    400         LimitedContext(requested_growth),
    401         &sandbox_file_system_, usage + requested_growth));
    402   }
    403 
    404   scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) {
    405     int64 usage = sandbox_file_system_.GetCachedOriginUsage();
    406     return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
    407         LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
    408   }
    409 
    410   void FillTestDirectory(
    411       const FileSystemURL& root_url,
    412       std::set<base::FilePath::StringType>* files,
    413       std::set<base::FilePath::StringType>* directories) {
    414     scoped_ptr<FileSystemOperationContext> context;
    415     std::vector<DirectoryEntry> entries;
    416     EXPECT_EQ(base::PLATFORM_FILE_OK,
    417               AsyncFileTestHelper::ReadDirectory(
    418                   file_system_context(), root_url, &entries));
    419     EXPECT_EQ(0UL, entries.size());
    420 
    421     files->clear();
    422     files->insert(FILE_PATH_LITERAL("first"));
    423     files->insert(FILE_PATH_LITERAL("second"));
    424     files->insert(FILE_PATH_LITERAL("third"));
    425     directories->clear();
    426     directories->insert(FILE_PATH_LITERAL("fourth"));
    427     directories->insert(FILE_PATH_LITERAL("fifth"));
    428     directories->insert(FILE_PATH_LITERAL("sixth"));
    429     std::set<base::FilePath::StringType>::iterator iter;
    430     for (iter = files->begin(); iter != files->end(); ++iter) {
    431       bool created = false;
    432       context.reset(NewContext(NULL));
    433       ASSERT_EQ(base::PLATFORM_FILE_OK,
    434           ofu()->EnsureFileExists(
    435               context.get(),
    436               FileSystemURLAppend(root_url, *iter),
    437               &created));
    438       ASSERT_TRUE(created);
    439     }
    440     for (iter = directories->begin(); iter != directories->end(); ++iter) {
    441       bool exclusive = true;
    442       bool recursive = false;
    443       context.reset(NewContext(NULL));
    444       EXPECT_EQ(base::PLATFORM_FILE_OK,
    445           ofu()->CreateDirectory(
    446               context.get(),
    447               FileSystemURLAppend(root_url, *iter),
    448               exclusive, recursive));
    449     }
    450     ValidateTestDirectory(root_url, *files, *directories);
    451   }
    452 
    453   void TestReadDirectoryHelper(const FileSystemURL& root_url) {
    454     std::set<base::FilePath::StringType> files;
    455     std::set<base::FilePath::StringType> directories;
    456     FillTestDirectory(root_url, &files, &directories);
    457 
    458     scoped_ptr<FileSystemOperationContext> context;
    459     std::vector<DirectoryEntry> entries;
    460     context.reset(NewContext(NULL));
    461     EXPECT_EQ(base::PLATFORM_FILE_OK,
    462               AsyncFileTestHelper::ReadDirectory(
    463                   file_system_context(), root_url, &entries));
    464     std::vector<DirectoryEntry>::iterator entry_iter;
    465     EXPECT_EQ(files.size() + directories.size(), entries.size());
    466     EXPECT_TRUE(change_observer()->HasNoChange());
    467     for (entry_iter = entries.begin(); entry_iter != entries.end();
    468         ++entry_iter) {
    469       const DirectoryEntry& entry = *entry_iter;
    470       std::set<base::FilePath::StringType>::iterator iter =
    471           files.find(entry.name);
    472       if (iter != files.end()) {
    473         EXPECT_FALSE(entry.is_directory);
    474         files.erase(iter);
    475         continue;
    476       }
    477       iter = directories.find(entry.name);
    478       EXPECT_FALSE(directories.end() == iter);
    479       EXPECT_TRUE(entry.is_directory);
    480       directories.erase(iter);
    481     }
    482   }
    483 
    484   void TestTouchHelper(const FileSystemURL& url, bool is_file) {
    485     base::Time last_access_time = base::Time::Now();
    486     base::Time last_modified_time = base::Time::Now();
    487 
    488     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    489     EXPECT_EQ(base::PLATFORM_FILE_OK,
    490               ofu()->Touch(
    491                   context.get(), url, last_access_time, last_modified_time));
    492     // Currently we fire no change notifications for Touch.
    493     EXPECT_TRUE(change_observer()->HasNoChange());
    494     base::FilePath local_path;
    495     base::PlatformFileInfo file_info;
    496     context.reset(NewContext(NULL));
    497     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    498         context.get(), url, &file_info, &local_path));
    499     // We compare as time_t here to lower our resolution, to avoid false
    500     // negatives caused by conversion to the local filesystem's native
    501     // representation and back.
    502     EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
    503 
    504     context.reset(NewContext(NULL));
    505     last_modified_time += base::TimeDelta::FromHours(1);
    506     last_access_time += base::TimeDelta::FromHours(14);
    507     EXPECT_EQ(base::PLATFORM_FILE_OK,
    508               ofu()->Touch(
    509                   context.get(), url, last_access_time, last_modified_time));
    510     EXPECT_TRUE(change_observer()->HasNoChange());
    511     context.reset(NewContext(NULL));
    512     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    513         context.get(), url, &file_info, &local_path));
    514     EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
    515     if (is_file)  // Directories in OFU don't support atime.
    516       EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
    517   }
    518 
    519   void TestCopyInForeignFileHelper(bool overwrite) {
    520     base::ScopedTempDir source_dir;
    521     ASSERT_TRUE(source_dir.CreateUniqueTempDir());
    522     base::FilePath root_file_path = source_dir.path();
    523     base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
    524     FileSystemURL dest_url = CreateURLFromUTF8("new file");
    525     int64 src_file_length = 87;
    526 
    527     base::PlatformFileError error_code;
    528     bool created = false;
    529     int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
    530     base::PlatformFile file_handle =
    531         base::CreatePlatformFile(
    532             src_file_path, file_flags, &created, &error_code);
    533     EXPECT_TRUE(created);
    534     ASSERT_EQ(base::PLATFORM_FILE_OK, error_code);
    535     ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
    536     ASSERT_TRUE(base::TruncatePlatformFile(file_handle, src_file_length));
    537     EXPECT_TRUE(base::ClosePlatformFile(file_handle));
    538 
    539     scoped_ptr<FileSystemOperationContext> context;
    540 
    541     if (overwrite) {
    542       context.reset(NewContext(NULL));
    543       EXPECT_EQ(base::PLATFORM_FILE_OK,
    544           ofu()->EnsureFileExists(context.get(), dest_url, &created));
    545       EXPECT_TRUE(created);
    546 
    547       // We must have observed one (and only one) create_file_count.
    548       EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    549       EXPECT_TRUE(change_observer()->HasNoChange());
    550     }
    551 
    552     const int64 path_cost =
    553         ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
    554     if (!overwrite) {
    555       // Verify that file creation requires sufficient quota for the path.
    556       context.reset(NewContext(NULL));
    557       context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
    558       EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
    559                 ofu()->CopyInForeignFile(context.get(),
    560                                          src_file_path, dest_url));
    561     }
    562 
    563     context.reset(NewContext(NULL));
    564     context->set_allowed_bytes_growth(path_cost + src_file_length);
    565     EXPECT_EQ(base::PLATFORM_FILE_OK,
    566               ofu()->CopyInForeignFile(context.get(),
    567                                        src_file_path, dest_url));
    568 
    569     EXPECT_TRUE(PathExists(dest_url));
    570     EXPECT_FALSE(DirectoryExists(dest_url));
    571 
    572     context.reset(NewContext(NULL));
    573     base::PlatformFileInfo file_info;
    574     base::FilePath data_path;
    575     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    576         context.get(), dest_url, &file_info, &data_path));
    577     EXPECT_NE(data_path, src_file_path);
    578     EXPECT_TRUE(FileExists(data_path));
    579     EXPECT_EQ(src_file_length, GetSize(data_path));
    580 
    581     EXPECT_EQ(base::PLATFORM_FILE_OK,
    582         ofu()->DeleteFile(context.get(), dest_url));
    583   }
    584 
    585   void ClearTimestamp(const FileSystemURL& url) {
    586     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    587     EXPECT_EQ(base::PLATFORM_FILE_OK,
    588               ofu()->Touch(context.get(), url, base::Time(), base::Time()));
    589     EXPECT_EQ(base::Time(), GetModifiedTime(url));
    590   }
    591 
    592   base::Time GetModifiedTime(const FileSystemURL& url) {
    593     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    594     base::FilePath data_path;
    595     base::PlatformFileInfo file_info;
    596     context.reset(NewContext(NULL));
    597     EXPECT_EQ(base::PLATFORM_FILE_OK,
    598               ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
    599     EXPECT_TRUE(change_observer()->HasNoChange());
    600     return file_info.last_modified;
    601   }
    602 
    603   void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
    604                                     bool copy,
    605                                     bool overwrite) {
    606     scoped_ptr<FileSystemOperationContext> context;
    607     const FileSystemURL src_dir_url(
    608         FileSystemURLAppendUTF8(base_dir, "foo_dir"));
    609     const FileSystemURL dest_dir_url(
    610         FileSystemURLAppendUTF8(base_dir, "bar_dir"));
    611 
    612     const FileSystemURL src_file_url(
    613         FileSystemURLAppendUTF8(src_dir_url, "hoge"));
    614     const FileSystemURL dest_file_url(
    615         FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
    616 
    617     context.reset(NewContext(NULL));
    618     EXPECT_EQ(base::PLATFORM_FILE_OK,
    619               ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
    620     context.reset(NewContext(NULL));
    621     EXPECT_EQ(base::PLATFORM_FILE_OK,
    622               ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
    623 
    624     bool created = false;
    625     context.reset(NewContext(NULL));
    626     EXPECT_EQ(base::PLATFORM_FILE_OK,
    627               ofu()->EnsureFileExists(context.get(), src_file_url, &created));
    628     if (overwrite) {
    629       context.reset(NewContext(NULL));
    630       EXPECT_EQ(base::PLATFORM_FILE_OK,
    631                 ofu()->EnsureFileExists(context.get(),
    632                                         dest_file_url, &created));
    633     }
    634 
    635     ClearTimestamp(src_dir_url);
    636     ClearTimestamp(dest_dir_url);
    637     context.reset(NewContext(NULL));
    638     EXPECT_EQ(base::PLATFORM_FILE_OK,
    639               ofu()->CopyOrMoveFile(context.get(),
    640                                     src_file_url, dest_file_url,
    641                                     copy));
    642     if (copy)
    643       EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
    644     else
    645       EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
    646     EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
    647   }
    648 
    649   int64 ComputeCurrentUsage() {
    650     return sandbox_file_system_.ComputeCurrentOriginUsage() -
    651         sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
    652   }
    653 
    654   FileSystemContext* file_system_context() {
    655     return sandbox_file_system_.file_system_context();
    656   }
    657 
    658   const base::FilePath& data_dir_path() const {
    659     return data_dir_.path();
    660   }
    661 
    662  protected:
    663   base::ScopedTempDir data_dir_;
    664   base::MessageLoop message_loop_;
    665   scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy_;
    666   scoped_refptr<quota::QuotaManager> quota_manager_;
    667   scoped_refptr<FileSystemContext> file_system_context_;
    668   GURL origin_;
    669   fileapi::FileSystemType type_;
    670   base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
    671   SandboxFileSystemTestHelper sandbox_file_system_;
    672   quota::QuotaStatusCode quota_status_;
    673   int64 usage_;
    674   MockFileChangeObserver change_observer_;
    675   ChangeObserverList change_observers_;
    676 
    677   DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
    678 };
    679 
    680 TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
    681   base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
    682   bool created;
    683   FileSystemURL url = CreateURLFromUTF8("fake/file");
    684   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    685   int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
    686 
    687   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    688             ofu()->CreateOrOpen(
    689                 context.get(), url, file_flags, &file_handle,
    690                 &created));
    691 
    692   context.reset(NewContext(NULL));
    693   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    694             ofu()->DeleteFile(context.get(), url));
    695 
    696   url = CreateURLFromUTF8("test file");
    697 
    698   EXPECT_TRUE(change_observer()->HasNoChange());
    699 
    700   // Verify that file creation requires sufficient quota for the path.
    701   context.reset(NewContext(NULL));
    702   context->set_allowed_bytes_growth(
    703       ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
    704   ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
    705             ofu()->CreateOrOpen(
    706                 context.get(), url, file_flags, &file_handle, &created));
    707 
    708   context.reset(NewContext(NULL));
    709   context->set_allowed_bytes_growth(
    710       ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
    711   ASSERT_EQ(base::PLATFORM_FILE_OK,
    712             ofu()->CreateOrOpen(
    713                 context.get(), url, file_flags, &file_handle, &created));
    714   ASSERT_TRUE(created);
    715   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    716   EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
    717 
    718   CheckFileAndCloseHandle(url, file_handle);
    719 
    720   context.reset(NewContext(NULL));
    721   base::FilePath local_path;
    722   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
    723       context.get(), url, &local_path));
    724   EXPECT_TRUE(base::PathExists(local_path));
    725 
    726   // Verify that deleting a file isn't stopped by zero quota, and that it frees
    727   // up quote from its path.
    728   context.reset(NewContext(NULL));
    729   context->set_allowed_bytes_growth(0);
    730   EXPECT_EQ(base::PLATFORM_FILE_OK,
    731             ofu()->DeleteFile(context.get(), url));
    732   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
    733   EXPECT_FALSE(base::PathExists(local_path));
    734   EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
    735       context->allowed_bytes_growth());
    736 
    737   context.reset(NewContext(NULL));
    738   bool exclusive = true;
    739   bool recursive = true;
    740   FileSystemURL directory_url = CreateURLFromUTF8(
    741       "series/of/directories");
    742   url = FileSystemURLAppendUTF8(directory_url, "file name");
    743   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
    744       context.get(), directory_url, exclusive, recursive));
    745   // The oepration created 3 directories recursively.
    746   EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
    747 
    748   context.reset(NewContext(NULL));
    749   file_handle = base::kInvalidPlatformFileValue;
    750   ASSERT_EQ(base::PLATFORM_FILE_OK,
    751             ofu()->CreateOrOpen(
    752                 context.get(), url, file_flags, &file_handle, &created));
    753   ASSERT_TRUE(created);
    754   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    755   EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
    756 
    757   CheckFileAndCloseHandle(url, file_handle);
    758 
    759   context.reset(NewContext(NULL));
    760   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
    761       context.get(), url, &local_path));
    762   EXPECT_TRUE(base::PathExists(local_path));
    763 
    764   context.reset(NewContext(NULL));
    765   EXPECT_EQ(base::PLATFORM_FILE_OK,
    766             ofu()->DeleteFile(context.get(), url));
    767   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
    768   EXPECT_FALSE(base::PathExists(local_path));
    769 
    770   // Make sure we have no unexpected changes.
    771   EXPECT_TRUE(change_observer()->HasNoChange());
    772 }
    773 
    774 TEST_F(ObfuscatedFileUtilTest, TestTruncate) {
    775   bool created = false;
    776   FileSystemURL url = CreateURLFromUTF8("file");
    777   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    778 
    779   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    780             ofu()->Truncate(context.get(), url, 4));
    781 
    782   context.reset(NewContext(NULL));
    783   ASSERT_EQ(base::PLATFORM_FILE_OK,
    784       ofu()->EnsureFileExists(context.get(), url, &created));
    785   ASSERT_TRUE(created);
    786   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    787 
    788   context.reset(NewContext(NULL));
    789   base::FilePath local_path;
    790   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
    791       context.get(), url, &local_path));
    792   EXPECT_EQ(0, GetSize(local_path));
    793 
    794   context.reset(NewContext(NULL));
    795   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
    796       context.get(), url, 10));
    797   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
    798   EXPECT_EQ(10, GetSize(local_path));
    799 
    800   context.reset(NewContext(NULL));
    801   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
    802       context.get(), url, 1));
    803   EXPECT_EQ(1, GetSize(local_path));
    804   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
    805 
    806   EXPECT_FALSE(DirectoryExists(url));
    807   EXPECT_TRUE(PathExists(url));
    808 
    809   // Make sure we have no unexpected changes.
    810   EXPECT_TRUE(change_observer()->HasNoChange());
    811 }
    812 
    813 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
    814   bool created = false;
    815   FileSystemURL url = CreateURLFromUTF8("file");
    816 
    817   ASSERT_EQ(base::PLATFORM_FILE_OK,
    818             ofu()->EnsureFileExists(
    819                 AllowUsageIncrease(PathCost(url))->context(),
    820                 url, &created));
    821   ASSERT_TRUE(created);
    822   ASSERT_EQ(0, ComputeTotalFileSize());
    823 
    824   ASSERT_EQ(base::PLATFORM_FILE_OK,
    825             ofu()->Truncate(
    826                 AllowUsageIncrease(1020)->context(),
    827                 url, 1020));
    828   ASSERT_EQ(1020, ComputeTotalFileSize());
    829 
    830   ASSERT_EQ(base::PLATFORM_FILE_OK,
    831             ofu()->Truncate(
    832                 AllowUsageIncrease(-1020)->context(),
    833                 url, 0));
    834   ASSERT_EQ(0, ComputeTotalFileSize());
    835 
    836   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
    837             ofu()->Truncate(
    838                 DisallowUsageIncrease(1021)->context(),
    839                 url, 1021));
    840   ASSERT_EQ(0, ComputeTotalFileSize());
    841 
    842   EXPECT_EQ(base::PLATFORM_FILE_OK,
    843             ofu()->Truncate(
    844                 AllowUsageIncrease(1020)->context(),
    845                 url, 1020));
    846   ASSERT_EQ(1020, ComputeTotalFileSize());
    847 
    848   EXPECT_EQ(base::PLATFORM_FILE_OK,
    849             ofu()->Truncate(
    850                 AllowUsageIncrease(0)->context(),
    851                 url, 1020));
    852   ASSERT_EQ(1020, ComputeTotalFileSize());
    853 
    854   // quota exceeded
    855   {
    856     scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1);
    857     helper->context()->set_allowed_bytes_growth(
    858         helper->context()->allowed_bytes_growth() - 1);
    859     EXPECT_EQ(base::PLATFORM_FILE_OK,
    860               ofu()->Truncate(helper->context(), url, 1019));
    861     ASSERT_EQ(1019, ComputeTotalFileSize());
    862   }
    863 
    864   // Delete backing file to make following truncation fail.
    865   base::FilePath local_path;
    866   ASSERT_EQ(base::PLATFORM_FILE_OK,
    867             ofu()->GetLocalFilePath(
    868                 UnlimitedContext().get(),
    869                 url, &local_path));
    870   ASSERT_FALSE(local_path.empty());
    871   ASSERT_TRUE(base::DeleteFile(local_path, false));
    872 
    873   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    874             ofu()->Truncate(
    875                 LimitedContext(1234).get(),
    876                 url, 1234));
    877   ASSERT_EQ(0, ComputeTotalFileSize());
    878 }
    879 
    880 TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) {
    881   FileSystemURL url = CreateURLFromUTF8("fake/file");
    882   bool created = false;
    883   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    884   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    885             ofu()->EnsureFileExists(
    886                 context.get(), url, &created));
    887   EXPECT_TRUE(change_observer()->HasNoChange());
    888 
    889   // Verify that file creation requires sufficient quota for the path.
    890   context.reset(NewContext(NULL));
    891   url = CreateURLFromUTF8("test file");
    892   created = false;
    893   context->set_allowed_bytes_growth(
    894       ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
    895   ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
    896             ofu()->EnsureFileExists(context.get(), url, &created));
    897   ASSERT_FALSE(created);
    898   EXPECT_TRUE(change_observer()->HasNoChange());
    899 
    900   context.reset(NewContext(NULL));
    901   context->set_allowed_bytes_growth(
    902       ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
    903   ASSERT_EQ(base::PLATFORM_FILE_OK,
    904             ofu()->EnsureFileExists(context.get(), url, &created));
    905   ASSERT_TRUE(created);
    906   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    907 
    908   CheckFileAndCloseHandle(url, base::kInvalidPlatformFileValue);
    909 
    910   context.reset(NewContext(NULL));
    911   ASSERT_EQ(base::PLATFORM_FILE_OK,
    912             ofu()->EnsureFileExists(context.get(), url, &created));
    913   ASSERT_FALSE(created);
    914   EXPECT_TRUE(change_observer()->HasNoChange());
    915 
    916   // Also test in a subdirectory.
    917   url = CreateURLFromUTF8("path/to/file.txt");
    918   context.reset(NewContext(NULL));
    919   bool exclusive = true;
    920   bool recursive = true;
    921   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
    922       context.get(),
    923       FileSystemURLDirName(url),
    924       exclusive, recursive));
    925   // 2 directories: path/ and path/to.
    926   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
    927 
    928   context.reset(NewContext(NULL));
    929   ASSERT_EQ(base::PLATFORM_FILE_OK,
    930             ofu()->EnsureFileExists(context.get(), url, &created));
    931   ASSERT_TRUE(created);
    932   EXPECT_FALSE(DirectoryExists(url));
    933   EXPECT_TRUE(PathExists(url));
    934   EXPECT_TRUE(change_observer()->HasNoChange());
    935 }
    936 
    937 TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) {
    938   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
    939 
    940   bool exclusive = false;
    941   bool recursive = false;
    942   FileSystemURL url = CreateURLFromUTF8("foo/bar");
    943   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CreateDirectory(
    944       context.get(), url, exclusive, recursive));
    945 
    946   context.reset(NewContext(NULL));
    947   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
    948       ofu()->DeleteDirectory(context.get(), url));
    949 
    950   FileSystemURL root = CreateURLFromUTF8(std::string());
    951   EXPECT_FALSE(DirectoryExists(url));
    952   EXPECT_FALSE(PathExists(url));
    953   context.reset(NewContext(NULL));
    954   EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
    955 
    956   context.reset(NewContext(NULL));
    957   exclusive = false;
    958   recursive = true;
    959   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
    960       context.get(), url, exclusive, recursive));
    961   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
    962 
    963   EXPECT_TRUE(DirectoryExists(url));
    964   EXPECT_TRUE(PathExists(url));
    965 
    966   context.reset(NewContext(NULL));
    967   EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
    968   EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
    969 
    970   context.reset(NewContext(NULL));
    971   EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(),
    972                                        FileSystemURLDirName(url)));
    973 
    974   // Can't remove a non-empty directory.
    975   context.reset(NewContext(NULL));
    976   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
    977       ofu()->DeleteDirectory(context.get(),
    978                              FileSystemURLDirName(url)));
    979   EXPECT_TRUE(change_observer()->HasNoChange());
    980 
    981   base::PlatformFileInfo file_info;
    982   base::FilePath local_path;
    983   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
    984       context.get(), url, &file_info, &local_path));
    985   EXPECT_TRUE(local_path.empty());
    986   EXPECT_TRUE(file_info.is_directory);
    987   EXPECT_FALSE(file_info.is_symbolic_link);
    988 
    989   // Same create again should succeed, since exclusive is false.
    990   context.reset(NewContext(NULL));
    991   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
    992       context.get(), url, exclusive, recursive));
    993   EXPECT_TRUE(change_observer()->HasNoChange());
    994 
    995   exclusive = true;
    996   recursive = true;
    997   context.reset(NewContext(NULL));
    998   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
    999       context.get(), url, exclusive, recursive));
   1000   EXPECT_TRUE(change_observer()->HasNoChange());
   1001 
   1002   // Verify that deleting a directory isn't stopped by zero quota, and that it
   1003   // frees up quota from its path.
   1004   context.reset(NewContext(NULL));
   1005   context->set_allowed_bytes_growth(0);
   1006   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
   1007   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
   1008   EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
   1009       context->allowed_bytes_growth());
   1010 
   1011   url = CreateURLFromUTF8("foo/bop");
   1012 
   1013   EXPECT_FALSE(DirectoryExists(url));
   1014   EXPECT_FALSE(PathExists(url));
   1015 
   1016   context.reset(NewContext(NULL));
   1017   EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
   1018   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
   1019       context.get(), url, &file_info, &local_path));
   1020 
   1021   // Verify that file creation requires sufficient quota for the path.
   1022   exclusive = true;
   1023   recursive = false;
   1024   context.reset(NewContext(NULL));
   1025   context->set_allowed_bytes_growth(
   1026       ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
   1027   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->CreateDirectory(
   1028       context.get(), url, exclusive, recursive));
   1029   EXPECT_TRUE(change_observer()->HasNoChange());
   1030 
   1031   context.reset(NewContext(NULL));
   1032   context->set_allowed_bytes_growth(
   1033       ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
   1034   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1035       context.get(), url, exclusive, recursive));
   1036   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
   1037 
   1038   EXPECT_TRUE(DirectoryExists(url));
   1039   EXPECT_TRUE(PathExists(url));
   1040 
   1041   exclusive = true;
   1042   recursive = false;
   1043   context.reset(NewContext(NULL));
   1044   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
   1045       context.get(), url, exclusive, recursive));
   1046   EXPECT_TRUE(change_observer()->HasNoChange());
   1047 
   1048   exclusive = true;
   1049   recursive = false;
   1050   url = CreateURLFromUTF8("foo");
   1051   context.reset(NewContext(NULL));
   1052   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
   1053       context.get(), url, exclusive, recursive));
   1054   EXPECT_TRUE(change_observer()->HasNoChange());
   1055 
   1056   url = CreateURLFromUTF8("blah");
   1057 
   1058   EXPECT_FALSE(DirectoryExists(url));
   1059   EXPECT_FALSE(PathExists(url));
   1060 
   1061   exclusive = true;
   1062   recursive = false;
   1063   context.reset(NewContext(NULL));
   1064   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1065       context.get(), url, exclusive, recursive));
   1066   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
   1067 
   1068   EXPECT_TRUE(DirectoryExists(url));
   1069   EXPECT_TRUE(PathExists(url));
   1070 
   1071   exclusive = true;
   1072   recursive = false;
   1073   context.reset(NewContext(NULL));
   1074   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
   1075       context.get(), url, exclusive, recursive));
   1076   EXPECT_TRUE(change_observer()->HasNoChange());
   1077 }
   1078 
   1079 TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) {
   1080   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1081   bool exclusive = true;
   1082   bool recursive = true;
   1083   FileSystemURL url = CreateURLFromUTF8("directory/to/use");
   1084   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1085       context.get(), url, exclusive, recursive));
   1086   TestReadDirectoryHelper(url);
   1087 }
   1088 
   1089 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
   1090   TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
   1091 }
   1092 
   1093 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
   1094   TestReadDirectoryHelper(CreateURLFromUTF8("/"));
   1095 }
   1096 
   1097 TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
   1098   FileSystemURL url = CreateURLFromUTF8("file");
   1099   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1100 
   1101   bool created = false;
   1102   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1103       ofu()->EnsureFileExists(context.get(), url, &created));
   1104   ASSERT_TRUE(created);
   1105 
   1106   std::vector<DirectoryEntry> entries;
   1107   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
   1108             AsyncFileTestHelper::ReadDirectory(
   1109                 file_system_context(), url, &entries));
   1110 
   1111   EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
   1112 }
   1113 
   1114 TEST_F(ObfuscatedFileUtilTest, TestTouch) {
   1115   FileSystemURL url = CreateURLFromUTF8("file");
   1116   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1117 
   1118   base::Time last_access_time = base::Time::Now();
   1119   base::Time last_modified_time = base::Time::Now();
   1120 
   1121   // It's not there yet.
   1122   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1123             ofu()->Touch(
   1124                 context.get(), url, last_access_time, last_modified_time));
   1125 
   1126   // OK, now create it.
   1127   context.reset(NewContext(NULL));
   1128   bool created = false;
   1129   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1130             ofu()->EnsureFileExists(context.get(), url, &created));
   1131   ASSERT_TRUE(created);
   1132   TestTouchHelper(url, true);
   1133 
   1134   // Now test a directory:
   1135   context.reset(NewContext(NULL));
   1136   bool exclusive = true;
   1137   bool recursive = false;
   1138   url = CreateURLFromUTF8("dir");
   1139   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(context.get(),
   1140       url, exclusive, recursive));
   1141   TestTouchHelper(url, false);
   1142 }
   1143 
   1144 TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) {
   1145   FileSystemURL url = CreateURLFromUTF8("fake/file");
   1146   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1147 
   1148   url = CreateURLFromUTF8("file name");
   1149   context->set_allowed_bytes_growth(5);
   1150   bool created = false;
   1151   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
   1152       ofu()->EnsureFileExists(context.get(), url, &created));
   1153   EXPECT_FALSE(created);
   1154   context->set_allowed_bytes_growth(1024);
   1155   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1156       ofu()->EnsureFileExists(context.get(), url, &created));
   1157   EXPECT_TRUE(created);
   1158   int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
   1159   EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
   1160 
   1161   context->set_allowed_bytes_growth(1024);
   1162   bool exclusive = true;
   1163   bool recursive = true;
   1164   url = CreateURLFromUTF8("directory/to/use");
   1165   std::vector<base::FilePath::StringType> components;
   1166   url.path().GetComponents(&components);
   1167   path_cost = 0;
   1168   typedef std::vector<base::FilePath::StringType>::iterator iterator;
   1169   for (iterator iter = components.begin();
   1170        iter != components.end(); ++iter) {
   1171     path_cost += ObfuscatedFileUtil::ComputeFilePathCost(
   1172         base::FilePath(*iter));
   1173   }
   1174   context.reset(NewContext(NULL));
   1175   context->set_allowed_bytes_growth(1024);
   1176   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1177       context.get(), url, exclusive, recursive));
   1178   EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
   1179 }
   1180 
   1181 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
   1182   FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
   1183   FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
   1184   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1185 
   1186   bool is_copy_not_move = false;
   1187   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1188       ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
   1189           is_copy_not_move));
   1190   EXPECT_TRUE(change_observer()->HasNoChange());
   1191   context.reset(NewContext(NULL));
   1192   is_copy_not_move = true;
   1193   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1194       ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
   1195           is_copy_not_move));
   1196   EXPECT_TRUE(change_observer()->HasNoChange());
   1197   source_url = CreateURLFromUTF8("dir/dir/file");
   1198   bool exclusive = true;
   1199   bool recursive = true;
   1200   context.reset(NewContext(NULL));
   1201   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1202       context.get(),
   1203       FileSystemURLDirName(source_url),
   1204       exclusive, recursive));
   1205   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
   1206   is_copy_not_move = false;
   1207   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1208       ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
   1209           is_copy_not_move));
   1210   EXPECT_TRUE(change_observer()->HasNoChange());
   1211   context.reset(NewContext(NULL));
   1212   is_copy_not_move = true;
   1213   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1214       ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
   1215           is_copy_not_move));
   1216   EXPECT_TRUE(change_observer()->HasNoChange());
   1217 }
   1218 
   1219 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
   1220   const int64 kSourceLength = 5;
   1221   const int64 kDestLength = 50;
   1222 
   1223   for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
   1224     SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
   1225     const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
   1226     SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
   1227       test_case.is_copy_not_move);
   1228     SCOPED_TRACE(testing::Message() << "\t source_path " <<
   1229       test_case.source_path);
   1230     SCOPED_TRACE(testing::Message() << "\t dest_path " <<
   1231       test_case.dest_path);
   1232     SCOPED_TRACE(testing::Message() << "\t cause_overwrite " <<
   1233       test_case.cause_overwrite);
   1234     scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1235 
   1236     bool exclusive = false;
   1237     bool recursive = true;
   1238     FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
   1239     FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
   1240 
   1241     context.reset(NewContext(NULL));
   1242     ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1243         context.get(),
   1244         FileSystemURLDirName(source_url),
   1245         exclusive, recursive));
   1246     context.reset(NewContext(NULL));
   1247     ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1248         context.get(),
   1249         FileSystemURLDirName(dest_url),
   1250         exclusive, recursive));
   1251 
   1252     bool created = false;
   1253     context.reset(NewContext(NULL));
   1254     ASSERT_EQ(base::PLATFORM_FILE_OK,
   1255               ofu()->EnsureFileExists(context.get(), source_url, &created));
   1256     ASSERT_TRUE(created);
   1257     context.reset(NewContext(NULL));
   1258     ASSERT_EQ(base::PLATFORM_FILE_OK,
   1259               ofu()->Truncate(context.get(), source_url, kSourceLength));
   1260 
   1261     if (test_case.cause_overwrite) {
   1262       context.reset(NewContext(NULL));
   1263       created = false;
   1264       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1265                 ofu()->EnsureFileExists(context.get(), dest_url, &created));
   1266       ASSERT_TRUE(created);
   1267       context.reset(NewContext(NULL));
   1268       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1269                 ofu()->Truncate(context.get(), dest_url, kDestLength));
   1270     }
   1271 
   1272     context.reset(NewContext(NULL));
   1273     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyOrMoveFile(context.get(),
   1274         source_url, dest_url, test_case.is_copy_not_move));
   1275 
   1276     if (test_case.is_copy_not_move) {
   1277       base::PlatformFileInfo file_info;
   1278       base::FilePath local_path;
   1279       context.reset(NewContext(NULL));
   1280       EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
   1281           context.get(), source_url, &file_info, &local_path));
   1282       EXPECT_EQ(kSourceLength, file_info.size);
   1283       EXPECT_EQ(base::PLATFORM_FILE_OK,
   1284                 ofu()->DeleteFile(context.get(), source_url));
   1285     } else {
   1286       base::PlatformFileInfo file_info;
   1287       base::FilePath local_path;
   1288       context.reset(NewContext(NULL));
   1289       EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
   1290           context.get(), source_url, &file_info, &local_path));
   1291     }
   1292     base::PlatformFileInfo file_info;
   1293     base::FilePath local_path;
   1294     EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
   1295         context.get(), dest_url, &file_info, &local_path));
   1296     EXPECT_EQ(kSourceLength, file_info.size);
   1297 
   1298     EXPECT_EQ(base::PLATFORM_FILE_OK,
   1299               ofu()->DeleteFile(context.get(), dest_url));
   1300   }
   1301 }
   1302 
   1303 TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
   1304   FileSystemURL src_url = CreateURLFromUTF8("src path");
   1305   FileSystemURL dest_url = CreateURLFromUTF8("destination path");
   1306   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1307   bool created = false;
   1308   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
   1309       context.get(), src_url, &created));
   1310 
   1311   bool is_copy = true;
   1312   // Copy, no overwrite.
   1313   context->set_allowed_bytes_growth(
   1314       ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
   1315   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
   1316       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1317   context.reset(NewContext(NULL));
   1318   context->set_allowed_bytes_growth(
   1319       ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
   1320   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1321       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1322 
   1323   // Copy, with overwrite.
   1324   context.reset(NewContext(NULL));
   1325   context->set_allowed_bytes_growth(0);
   1326   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1327       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1328 }
   1329 
   1330 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
   1331   FileSystemURL src_url = CreateURLFromUTF8("src path");
   1332   FileSystemURL dest_url = CreateURLFromUTF8("destination path");
   1333   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1334   bool created = false;
   1335   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
   1336       context.get(), src_url, &created));
   1337 
   1338   bool is_copy = false;
   1339   // Move, rename, no overwrite.
   1340   context.reset(NewContext(NULL));
   1341   context->set_allowed_bytes_growth(
   1342       ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
   1343       ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
   1344   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
   1345       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1346   context.reset(NewContext(NULL));
   1347   context->set_allowed_bytes_growth(
   1348       ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
   1349       ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
   1350   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1351       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1352 
   1353   context.reset(NewContext(NULL));
   1354   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
   1355       context.get(), src_url, &created));
   1356 
   1357   // Move, rename, with overwrite.
   1358   context.reset(NewContext(NULL));
   1359   context->set_allowed_bytes_growth(0);
   1360   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1361       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1362 }
   1363 
   1364 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
   1365   FileSystemURL src_url = CreateURLFromUTF8("src path");
   1366   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1367   bool created = false;
   1368   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
   1369       context.get(), src_url, &created));
   1370 
   1371   bool exclusive = true;
   1372   bool recursive = false;
   1373   FileSystemURL dir_url = CreateURLFromUTF8("directory path");
   1374   context.reset(NewContext(NULL));
   1375   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1376       context.get(), dir_url, exclusive, recursive));
   1377 
   1378   FileSystemURL dest_url = FileSystemURLAppend(
   1379       dir_url, src_url.path().value());
   1380 
   1381   bool is_copy = false;
   1382   int64 allowed_bytes_growth = -1000;  // Over quota, this should still work.
   1383   // Move, no rename, no overwrite.
   1384   context.reset(NewContext(NULL));
   1385   context->set_allowed_bytes_growth(allowed_bytes_growth);
   1386   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1387       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1388   EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
   1389 
   1390   // Move, no rename, with overwrite.
   1391   context.reset(NewContext(NULL));
   1392   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
   1393       context.get(), src_url, &created));
   1394   context.reset(NewContext(NULL));
   1395   context->set_allowed_bytes_growth(allowed_bytes_growth);
   1396   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1397       ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
   1398   EXPECT_EQ(
   1399       allowed_bytes_growth +
   1400           ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
   1401       context->allowed_bytes_growth());
   1402 }
   1403 
   1404 TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
   1405   TestCopyInForeignFileHelper(false /* overwrite */);
   1406   TestCopyInForeignFileHelper(true /* overwrite */);
   1407 }
   1408 
   1409 TEST_F(ObfuscatedFileUtilTest, TestEnumerator) {
   1410   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1411   FileSystemURL src_url = CreateURLFromUTF8("source dir");
   1412   bool exclusive = true;
   1413   bool recursive = false;
   1414   ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
   1415       context.get(), src_url, exclusive, recursive));
   1416 
   1417   std::set<base::FilePath::StringType> files;
   1418   std::set<base::FilePath::StringType> directories;
   1419   FillTestDirectory(src_url, &files, &directories);
   1420 
   1421   FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
   1422 
   1423   EXPECT_FALSE(DirectoryExists(dest_url));
   1424   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1425             AsyncFileTestHelper::Copy(
   1426                 file_system_context(), src_url, dest_url));
   1427 
   1428   ValidateTestDirectory(dest_url, files, directories);
   1429   EXPECT_TRUE(DirectoryExists(src_url));
   1430   EXPECT_TRUE(DirectoryExists(dest_url));
   1431   recursive = true;
   1432   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1433             AsyncFileTestHelper::Remove(
   1434                 file_system_context(), dest_url, recursive));
   1435   EXPECT_FALSE(DirectoryExists(dest_url));
   1436 }
   1437 
   1438 TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
   1439   scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator>
   1440       enumerator(ofu()->CreateOriginEnumerator());
   1441   // The test helper starts out with a single filesystem.
   1442   EXPECT_TRUE(enumerator.get());
   1443   EXPECT_EQ(origin(), enumerator->Next());
   1444   ASSERT_TRUE(type() == kFileSystemTypeTemporary);
   1445   EXPECT_TRUE(enumerator->HasFileSystemType(kFileSystemTypeTemporary));
   1446   EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
   1447   EXPECT_EQ(GURL(), enumerator->Next());
   1448   EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypeTemporary));
   1449   EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
   1450 
   1451   std::set<GURL> origins_expected;
   1452   origins_expected.insert(origin());
   1453 
   1454   for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
   1455     SCOPED_TRACE(testing::Message() <<
   1456         "Validating kOriginEnumerationTestRecords " << i);
   1457     const OriginEnumerationTestRecord& record =
   1458         kOriginEnumerationTestRecords[i];
   1459     GURL origin_url(record.origin_url);
   1460     origins_expected.insert(origin_url);
   1461     if (record.has_temporary) {
   1462       scoped_ptr<SandboxFileSystemTestHelper> file_system(
   1463           NewFileSystem(origin_url, kFileSystemTypeTemporary));
   1464       scoped_ptr<FileSystemOperationContext> context(
   1465           NewContext(file_system.get()));
   1466       bool created = false;
   1467       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1468                 ofu()->EnsureFileExists(
   1469                     context.get(),
   1470                     file_system->CreateURLFromUTF8("file"),
   1471                     &created));
   1472       EXPECT_TRUE(created);
   1473     }
   1474     if (record.has_persistent) {
   1475       scoped_ptr<SandboxFileSystemTestHelper> file_system(
   1476           NewFileSystem(origin_url, kFileSystemTypePersistent));
   1477       scoped_ptr<FileSystemOperationContext> context(
   1478           NewContext(file_system.get()));
   1479       bool created = false;
   1480       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1481                 ofu()->EnsureFileExists(
   1482                     context.get(),
   1483                     file_system->CreateURLFromUTF8("file"),
   1484                     &created));
   1485       EXPECT_TRUE(created);
   1486     }
   1487   }
   1488   enumerator.reset(ofu()->CreateOriginEnumerator());
   1489   EXPECT_TRUE(enumerator.get());
   1490   std::set<GURL> origins_found;
   1491   GURL origin_url;
   1492   while (!(origin_url = enumerator->Next()).is_empty()) {
   1493     origins_found.insert(origin_url);
   1494     SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
   1495     bool found = false;
   1496     for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
   1497         ++i) {
   1498       const OriginEnumerationTestRecord& record =
   1499           kOriginEnumerationTestRecords[i];
   1500       if (GURL(record.origin_url) != origin_url)
   1501         continue;
   1502       found = true;
   1503       EXPECT_EQ(record.has_temporary,
   1504           enumerator->HasFileSystemType(kFileSystemTypeTemporary));
   1505       EXPECT_EQ(record.has_persistent,
   1506           enumerator->HasFileSystemType(kFileSystemTypePersistent));
   1507     }
   1508     // Deal with the default filesystem created by the test helper.
   1509     if (!found && origin_url == origin()) {
   1510       ASSERT_TRUE(type() == kFileSystemTypeTemporary);
   1511       EXPECT_EQ(true,
   1512           enumerator->HasFileSystemType(kFileSystemTypeTemporary));
   1513       EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
   1514       found = true;
   1515     }
   1516     EXPECT_TRUE(found);
   1517   }
   1518 
   1519   std::set<GURL> diff;
   1520   std::set_symmetric_difference(origins_expected.begin(),
   1521       origins_expected.end(), origins_found.begin(), origins_found.end(),
   1522       inserter(diff, diff.begin()));
   1523   EXPECT_TRUE(diff.empty());
   1524 }
   1525 
   1526 TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
   1527   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1528 
   1529   int64 expected_quota = 0;
   1530 
   1531   for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
   1532     SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
   1533     const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
   1534     base::FilePath file_path(test_case.path);
   1535     expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
   1536     if (test_case.is_directory) {
   1537       bool exclusive = true;
   1538       bool recursive = false;
   1539       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1540           ofu()->CreateDirectory(context.get(), CreateURL(file_path),
   1541                                  exclusive, recursive));
   1542     } else {
   1543       bool created = false;
   1544       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1545           ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
   1546                                   &created));
   1547       ASSERT_TRUE(created);
   1548       ASSERT_EQ(base::PLATFORM_FILE_OK,
   1549           ofu()->Truncate(context.get(),
   1550                           CreateURL(file_path),
   1551                           test_case.data_file_size));
   1552       expected_quota += test_case.data_file_size;
   1553     }
   1554   }
   1555 
   1556   // Usually raw size in usage cache and the usage returned by QuotaUtil
   1557   // should be same.
   1558   EXPECT_EQ(expected_quota, SizeInUsageFile());
   1559   EXPECT_EQ(expected_quota, SizeByQuotaUtil());
   1560 
   1561   RevokeUsageCache();
   1562   EXPECT_EQ(-1, SizeInUsageFile());
   1563   EXPECT_EQ(expected_quota, SizeByQuotaUtil());
   1564 
   1565   // This should reconstruct the cache.
   1566   GetUsageFromQuotaManager();
   1567   EXPECT_EQ(expected_quota, SizeInUsageFile());
   1568   EXPECT_EQ(expected_quota, SizeByQuotaUtil());
   1569   EXPECT_EQ(expected_quota, usage());
   1570 }
   1571 
   1572 TEST_F(ObfuscatedFileUtilTest, TestInconsistency) {
   1573   const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
   1574   const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
   1575 
   1576   scoped_ptr<FileSystemOperationContext> context;
   1577   base::PlatformFile file;
   1578   base::PlatformFileInfo file_info;
   1579   base::FilePath data_path;
   1580   bool created = false;
   1581 
   1582   // Create a non-empty file.
   1583   context.reset(NewContext(NULL));
   1584   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1585             ofu()->EnsureFileExists(context.get(), kPath1, &created));
   1586   EXPECT_TRUE(created);
   1587   context.reset(NewContext(NULL));
   1588   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1589             ofu()->Truncate(context.get(), kPath1, 10));
   1590   context.reset(NewContext(NULL));
   1591   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1592             ofu()->GetFileInfo(
   1593                 context.get(), kPath1, &file_info, &data_path));
   1594   EXPECT_EQ(10, file_info.size);
   1595 
   1596   // Destroy database to make inconsistency between database and filesystem.
   1597   ofu()->DestroyDirectoryDatabase(origin(), type());
   1598 
   1599   // Try to get file info of broken file.
   1600   EXPECT_FALSE(PathExists(kPath1));
   1601   context.reset(NewContext(NULL));
   1602   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1603             ofu()->EnsureFileExists(context.get(), kPath1, &created));
   1604   EXPECT_TRUE(created);
   1605   context.reset(NewContext(NULL));
   1606   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1607             ofu()->GetFileInfo(
   1608                 context.get(), kPath1, &file_info, &data_path));
   1609   EXPECT_EQ(0, file_info.size);
   1610 
   1611   // Make another broken file to |kPath2|.
   1612   context.reset(NewContext(NULL));
   1613   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1614             ofu()->EnsureFileExists(context.get(), kPath2, &created));
   1615   EXPECT_TRUE(created);
   1616 
   1617   // Destroy again.
   1618   ofu()->DestroyDirectoryDatabase(origin(), type());
   1619 
   1620   // Repair broken |kPath1|.
   1621   context.reset(NewContext(NULL));
   1622   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1623             ofu()->Touch(context.get(), kPath1, base::Time::Now(),
   1624                            base::Time::Now()));
   1625   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1626             ofu()->EnsureFileExists(context.get(), kPath1, &created));
   1627   EXPECT_TRUE(created);
   1628 
   1629   // Copy from sound |kPath1| to broken |kPath2|.
   1630   context.reset(NewContext(NULL));
   1631   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1632             ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
   1633                                   true /* copy */));
   1634 
   1635   ofu()->DestroyDirectoryDatabase(origin(), type());
   1636   context.reset(NewContext(NULL));
   1637   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1638             ofu()->CreateOrOpen(
   1639                 context.get(), kPath1,
   1640                 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_CREATE,
   1641                 &file, &created));
   1642   EXPECT_TRUE(created);
   1643   EXPECT_TRUE(base::GetPlatformFileInfo(file, &file_info));
   1644   EXPECT_EQ(0, file_info.size);
   1645   EXPECT_TRUE(base::ClosePlatformFile(file));
   1646 }
   1647 
   1648 TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
   1649   const FileSystemURL kPath[] = {
   1650     CreateURLFromUTF8("foo"),
   1651     CreateURLFromUTF8("bar"),
   1652     CreateURLFromUTF8("baz")
   1653   };
   1654   const FileSystemURL empty_path = CreateURL(base::FilePath());
   1655   scoped_ptr<FileSystemOperationContext> context;
   1656 
   1657   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) {
   1658     bool created = false;
   1659     context.reset(NewContext(NULL));
   1660     EXPECT_EQ(base::PLATFORM_FILE_OK,
   1661               ofu()->EnsureFileExists(context.get(), kPath[i], &created));
   1662     EXPECT_TRUE(created);
   1663   }
   1664 
   1665   std::vector<DirectoryEntry> entries;
   1666   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1667             AsyncFileTestHelper::ReadDirectory(
   1668                 file_system_context(), empty_path, &entries));
   1669   EXPECT_EQ(3u, entries.size());
   1670 
   1671   base::FilePath local_path;
   1672   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1673             ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path));
   1674   EXPECT_TRUE(base::DeleteFile(local_path, false));
   1675 
   1676   entries.clear();
   1677   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1678             AsyncFileTestHelper::ReadDirectory(
   1679                 file_system_context(), empty_path, &entries));
   1680   EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size());
   1681 }
   1682 
   1683 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
   1684   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1685   const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
   1686 
   1687   // Create working directory.
   1688   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1689             ofu()->CreateDirectory(context.get(), dir_url, false, false));
   1690 
   1691   // EnsureFileExists, create case.
   1692   FileSystemURL url(FileSystemURLAppendUTF8(
   1693           dir_url, "EnsureFileExists_file"));
   1694   bool created = false;
   1695   ClearTimestamp(dir_url);
   1696   context.reset(NewContext(NULL));
   1697   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1698             ofu()->EnsureFileExists(context.get(), url, &created));
   1699   EXPECT_TRUE(created);
   1700   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1701 
   1702   // non create case.
   1703   created = true;
   1704   ClearTimestamp(dir_url);
   1705   context.reset(NewContext(NULL));
   1706   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1707             ofu()->EnsureFileExists(context.get(), url, &created));
   1708   EXPECT_FALSE(created);
   1709   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1710 
   1711   // fail case.
   1712   url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
   1713   context.reset(NewContext(NULL));
   1714   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1715             ofu()->CreateDirectory(context.get(), url, false, false));
   1716 
   1717   ClearTimestamp(dir_url);
   1718   context.reset(NewContext(NULL));
   1719   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
   1720             ofu()->EnsureFileExists(context.get(), url, &created));
   1721   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1722 
   1723   // CreateOrOpen, create case.
   1724   url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
   1725   base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
   1726   created = false;
   1727   ClearTimestamp(dir_url);
   1728   context.reset(NewContext(NULL));
   1729   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1730             ofu()->CreateOrOpen(
   1731                 context.get(), url,
   1732                 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
   1733                 &file_handle, &created));
   1734   EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
   1735   EXPECT_TRUE(created);
   1736   EXPECT_TRUE(base::ClosePlatformFile(file_handle));
   1737   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1738 
   1739   // open case.
   1740   file_handle = base::kInvalidPlatformFileValue;
   1741   created = true;
   1742   ClearTimestamp(dir_url);
   1743   context.reset(NewContext(NULL));
   1744   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1745             ofu()->CreateOrOpen(
   1746                 context.get(), url,
   1747                 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
   1748                 &file_handle, &created));
   1749   EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
   1750   EXPECT_FALSE(created);
   1751   EXPECT_TRUE(base::ClosePlatformFile(file_handle));
   1752   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1753 
   1754   // fail case
   1755   file_handle = base::kInvalidPlatformFileValue;
   1756   ClearTimestamp(dir_url);
   1757   context.reset(NewContext(NULL));
   1758   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
   1759             ofu()->CreateOrOpen(
   1760                 context.get(), url,
   1761                 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
   1762                 &file_handle, &created));
   1763   EXPECT_EQ(base::kInvalidPlatformFileValue, file_handle);
   1764   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1765 
   1766   // CreateDirectory, create case.
   1767   // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
   1768   url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
   1769   FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
   1770   ClearTimestamp(dir_url);
   1771   context.reset(NewContext(NULL));
   1772   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1773             ofu()->CreateDirectory(context.get(), subdir_url,
   1774                                    true /* exclusive */, true /* recursive */));
   1775   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1776 
   1777   // create subdir case.
   1778   // Creating CreateDirectory_dir/subdir2.
   1779   subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
   1780   ClearTimestamp(dir_url);
   1781   ClearTimestamp(url);
   1782   context.reset(NewContext(NULL));
   1783   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1784             ofu()->CreateDirectory(context.get(), subdir_url,
   1785                                    true /* exclusive */, true /* recursive */));
   1786   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1787   EXPECT_NE(base::Time(), GetModifiedTime(url));
   1788 
   1789   // fail case.
   1790   url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
   1791   ClearTimestamp(dir_url);
   1792   context.reset(NewContext(NULL));
   1793   EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
   1794             ofu()->CreateDirectory(context.get(), url,
   1795                                    true /* exclusive */, true /* recursive */));
   1796   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1797 
   1798   // CopyInForeignFile, create case.
   1799   url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
   1800   FileSystemURL src_path = FileSystemURLAppendUTF8(
   1801       dir_url, "CopyInForeignFile_src_file");
   1802   context.reset(NewContext(NULL));
   1803   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1804             ofu()->EnsureFileExists(context.get(), src_path, &created));
   1805   EXPECT_TRUE(created);
   1806   base::FilePath src_local_path;
   1807   context.reset(NewContext(NULL));
   1808   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1809             ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path));
   1810 
   1811   ClearTimestamp(dir_url);
   1812   context.reset(NewContext(NULL));
   1813   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1814             ofu()->CopyInForeignFile(context.get(),
   1815                                      src_local_path,
   1816                                      url));
   1817   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1818 }
   1819 
   1820 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
   1821   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1822   const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
   1823 
   1824   // Create working directory.
   1825   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1826             ofu()->CreateDirectory(context.get(), dir_url, false, false));
   1827 
   1828   // DeleteFile, delete case.
   1829   FileSystemURL url = FileSystemURLAppendUTF8(
   1830       dir_url, "DeleteFile_file");
   1831   bool created = false;
   1832   context.reset(NewContext(NULL));
   1833   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1834             ofu()->EnsureFileExists(context.get(), url, &created));
   1835   EXPECT_TRUE(created);
   1836 
   1837   ClearTimestamp(dir_url);
   1838   context.reset(NewContext(NULL));
   1839   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1840             ofu()->DeleteFile(context.get(), url));
   1841   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1842 
   1843   // fail case.
   1844   ClearTimestamp(dir_url);
   1845   context.reset(NewContext(NULL));
   1846   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
   1847             ofu()->DeleteFile(context.get(), url));
   1848   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1849 
   1850   // DeleteDirectory, fail case.
   1851   url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
   1852   FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
   1853   context.reset(NewContext(NULL));
   1854   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1855             ofu()->CreateDirectory(context.get(), url, true, true));
   1856   created = false;
   1857   context.reset(NewContext(NULL));
   1858   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1859             ofu()->EnsureFileExists(context.get(), file_path, &created));
   1860   EXPECT_TRUE(created);
   1861 
   1862   ClearTimestamp(dir_url);
   1863   context.reset(NewContext(NULL));
   1864   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
   1865             ofu()->DeleteDirectory(context.get(), url));
   1866   EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
   1867 
   1868   // delete case.
   1869   context.reset(NewContext(NULL));
   1870   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1871             ofu()->DeleteFile(context.get(), file_path));
   1872 
   1873   ClearTimestamp(dir_url);
   1874   context.reset(NewContext(NULL));
   1875   EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
   1876   EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
   1877 }
   1878 
   1879 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
   1880   TestDirectoryTimestampHelper(
   1881       CreateURLFromUTF8("copy overwrite"), true, true);
   1882   TestDirectoryTimestampHelper(
   1883       CreateURLFromUTF8("copy non-overwrite"), true, false);
   1884   TestDirectoryTimestampHelper(
   1885       CreateURLFromUTF8("move overwrite"), false, true);
   1886   TestDirectoryTimestampHelper(
   1887       CreateURLFromUTF8("move non-overwrite"), false, false);
   1888 }
   1889 
   1890 TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
   1891   FileSystemURL dir = CreateURLFromUTF8("foo");
   1892   FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
   1893   FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
   1894 
   1895   scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
   1896   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1897             ofu()->CreateDirectory(context.get(), dir, false, false));
   1898 
   1899   bool created = false;
   1900   context.reset(NewContext(NULL));
   1901   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1902             ofu()->EnsureFileExists(context.get(), url1, &created));
   1903   EXPECT_TRUE(created);
   1904 
   1905   context.reset(NewContext(NULL));
   1906   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1907             ofu()->CreateDirectory(context.get(), url2, false, false));
   1908 
   1909   base::FilePath file_path;
   1910   context.reset(NewContext(NULL));
   1911   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1912             ofu()->GetLocalFilePath(context.get(), url1, &file_path));
   1913   EXPECT_FALSE(file_path.empty());
   1914 
   1915   context.reset(NewContext(NULL));
   1916   EXPECT_EQ(base::PLATFORM_FILE_OK,
   1917             ofu()->Touch(context.get(), url1,
   1918                          base::Time::Now() + base::TimeDelta::FromHours(1),
   1919                          base::Time()));
   1920 
   1921   context.reset(NewContext(NULL));
   1922   scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
   1923       ofu()->CreateFileEnumerator(context.get(), dir, false));
   1924 
   1925   int count = 0;
   1926   base::FilePath file_path_each;
   1927   while (!(file_path_each = file_enum->Next()).empty()) {
   1928     context.reset(NewContext(NULL));
   1929     base::PlatformFileInfo file_info;
   1930     base::FilePath file_path;
   1931     EXPECT_EQ(base::PLATFORM_FILE_OK,
   1932               ofu()->GetFileInfo(context.get(),
   1933                                  FileSystemURL::CreateForTest(
   1934                                      dir.origin(),
   1935                                      dir.mount_type(),
   1936                                      file_path_each),
   1937                                  &file_info, &file_path));
   1938     EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
   1939     EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
   1940     EXPECT_EQ(file_info.size, file_enum->Size());
   1941     ++count;
   1942   }
   1943   EXPECT_EQ(2, count);
   1944 }
   1945 
   1946 // crbug.com/176470
   1947 #if defined(OS_WIN) || defined(OS_ANDROID)
   1948 #define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
   1949 #else
   1950 #define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
   1951 #endif
   1952 TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) {
   1953   FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
   1954   FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
   1955   FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
   1956   FileSystemURL to_file2(CreateURLFromUTF8("tofile2"));
   1957   bool created;
   1958 
   1959   int64 expected_total_file_size = 0;
   1960   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1961             ofu()->EnsureFileExists(
   1962                 AllowUsageIncrease(PathCost(from_file))->context(),
   1963                 from_file, &created));
   1964   ASSERT_TRUE(created);
   1965   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   1966 
   1967   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1968             ofu()->EnsureFileExists(
   1969                 AllowUsageIncrease(PathCost(obstacle_file))->context(),
   1970                 obstacle_file, &created));
   1971   ASSERT_TRUE(created);
   1972   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   1973 
   1974   int64 from_file_size = 1020;
   1975   expected_total_file_size += from_file_size;
   1976   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1977             ofu()->Truncate(
   1978                 AllowUsageIncrease(from_file_size)->context(),
   1979                 from_file, from_file_size));
   1980   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   1981 
   1982   int64 obstacle_file_size = 1;
   1983   expected_total_file_size += obstacle_file_size;
   1984   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1985             ofu()->Truncate(
   1986                 AllowUsageIncrease(obstacle_file_size)->context(),
   1987                 obstacle_file, obstacle_file_size));
   1988   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   1989 
   1990   int64 to_file1_size = from_file_size;
   1991   expected_total_file_size += to_file1_size;
   1992   ASSERT_EQ(base::PLATFORM_FILE_OK,
   1993             ofu()->CopyOrMoveFile(
   1994                 AllowUsageIncrease(
   1995                     PathCost(to_file1) + to_file1_size)->context(),
   1996                 from_file, to_file1, true /* copy */));
   1997   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   1998 
   1999   ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
   2000             ofu()->CopyOrMoveFile(
   2001                 DisallowUsageIncrease(
   2002                     PathCost(to_file2) + from_file_size)->context(),
   2003                 from_file, to_file2, true /* copy */));
   2004   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2005 
   2006   int64 old_obstacle_file_size = obstacle_file_size;
   2007   obstacle_file_size = from_file_size;
   2008   expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
   2009   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2010             ofu()->CopyOrMoveFile(
   2011                 AllowUsageIncrease(
   2012                     obstacle_file_size - old_obstacle_file_size)->context(),
   2013                 from_file, obstacle_file, true /* copy */));
   2014   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2015 
   2016   int64 old_from_file_size = from_file_size;
   2017   from_file_size = old_from_file_size - 1;
   2018   expected_total_file_size += from_file_size - old_from_file_size;
   2019   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2020             ofu()->Truncate(
   2021                 AllowUsageIncrease(
   2022                     from_file_size - old_from_file_size)->context(),
   2023                 from_file, from_file_size));
   2024   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2025 
   2026   // quota exceeded
   2027   {
   2028     old_obstacle_file_size = obstacle_file_size;
   2029     obstacle_file_size = from_file_size;
   2030     expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
   2031     scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(
   2032         obstacle_file_size - old_obstacle_file_size);
   2033     helper->context()->set_allowed_bytes_growth(
   2034         helper->context()->allowed_bytes_growth() - 1);
   2035     ASSERT_EQ(base::PLATFORM_FILE_OK,
   2036               ofu()->CopyOrMoveFile(
   2037                   helper->context(),
   2038                   from_file, obstacle_file, true /* copy */));
   2039     ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2040   }
   2041 }
   2042 
   2043 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
   2044   FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
   2045   FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
   2046   FileSystemURL to_file(CreateURLFromUTF8("tofile"));
   2047   bool created;
   2048 
   2049   int64 expected_total_file_size = 0;
   2050   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2051             ofu()->EnsureFileExists(
   2052                 AllowUsageIncrease(PathCost(from_file))->context(),
   2053                 from_file, &created));
   2054   ASSERT_TRUE(created);
   2055   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2056 
   2057   int64 from_file_size = 1020;
   2058   expected_total_file_size += from_file_size;
   2059   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2060             ofu()->Truncate(
   2061                 AllowUsageIncrease(from_file_size)->context(),
   2062                 from_file, from_file_size));
   2063   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2064 
   2065   int64 to_file_size ALLOW_UNUSED = from_file_size;
   2066   from_file_size = 0;
   2067   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2068             ofu()->CopyOrMoveFile(
   2069                 AllowUsageIncrease(-PathCost(from_file) +
   2070                                    PathCost(to_file))->context(),
   2071                 from_file, to_file, false /* move */));
   2072   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2073 
   2074   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2075             ofu()->EnsureFileExists(
   2076                 AllowUsageIncrease(PathCost(from_file))->context(),
   2077                 from_file, &created));
   2078   ASSERT_TRUE(created);
   2079   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2080 
   2081   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2082             ofu()->EnsureFileExists(
   2083                 AllowUsageIncrease(PathCost(obstacle_file))->context(),
   2084                 obstacle_file, &created));
   2085   ASSERT_TRUE(created);
   2086   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2087 
   2088   from_file_size = 1020;
   2089   expected_total_file_size += from_file_size;
   2090   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2091             ofu()->Truncate(
   2092                 AllowUsageIncrease(from_file_size)->context(),
   2093                 from_file, from_file_size));
   2094   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2095 
   2096   int64 obstacle_file_size = 1;
   2097   expected_total_file_size += obstacle_file_size;
   2098   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2099             ofu()->Truncate(
   2100                 AllowUsageIncrease(1)->context(),
   2101                 obstacle_file, obstacle_file_size));
   2102   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2103 
   2104   int64 old_obstacle_file_size = obstacle_file_size;
   2105   obstacle_file_size = from_file_size;
   2106   from_file_size = 0;
   2107   expected_total_file_size -= old_obstacle_file_size;
   2108   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2109             ofu()->CopyOrMoveFile(
   2110                 AllowUsageIncrease(
   2111                     -old_obstacle_file_size - PathCost(from_file))->context(),
   2112                 from_file, obstacle_file,
   2113                 false /* move */));
   2114   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2115 
   2116   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2117             ofu()->EnsureFileExists(
   2118                 AllowUsageIncrease(PathCost(from_file))->context(),
   2119                 from_file, &created));
   2120   ASSERT_TRUE(created);
   2121   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2122 
   2123   from_file_size = 10;
   2124   expected_total_file_size += from_file_size;
   2125   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2126             ofu()->Truncate(
   2127                 AllowUsageIncrease(from_file_size)->context(),
   2128                 from_file, from_file_size));
   2129   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2130 
   2131   // quota exceeded even after operation
   2132   old_obstacle_file_size = obstacle_file_size;
   2133   obstacle_file_size = from_file_size;
   2134   from_file_size = 0;
   2135   expected_total_file_size -= old_obstacle_file_size;
   2136   scoped_ptr<FileSystemOperationContext> context =
   2137       LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1);
   2138   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2139             ofu()->CopyOrMoveFile(
   2140                 context.get(), from_file, obstacle_file, false /* move */));
   2141   ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
   2142   context.reset();
   2143 }
   2144 
   2145 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) {
   2146   FileSystemURL dir(CreateURLFromUTF8("dir"));
   2147   FileSystemURL file(CreateURLFromUTF8("file"));
   2148   FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
   2149   FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2"));
   2150   bool created;
   2151 
   2152   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2153             ofu()->EnsureFileExists(
   2154                 AllowUsageIncrease(PathCost(file))->context(),
   2155                 file, &created));
   2156   ASSERT_TRUE(created);
   2157   ASSERT_EQ(0, ComputeTotalFileSize());
   2158 
   2159   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2160             ofu()->CreateDirectory(
   2161                 AllowUsageIncrease(PathCost(dir))->context(),
   2162                 dir, false, false));
   2163   ASSERT_EQ(0, ComputeTotalFileSize());
   2164 
   2165   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2166             ofu()->EnsureFileExists(
   2167                 AllowUsageIncrease(PathCost(dfile1))->context(),
   2168                 dfile1, &created));
   2169   ASSERT_TRUE(created);
   2170   ASSERT_EQ(0, ComputeTotalFileSize());
   2171 
   2172   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2173             ofu()->EnsureFileExists(
   2174                 AllowUsageIncrease(PathCost(dfile2))->context(),
   2175                 dfile2, &created));
   2176   ASSERT_TRUE(created);
   2177   ASSERT_EQ(0, ComputeTotalFileSize());
   2178 
   2179   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2180             ofu()->Truncate(
   2181                 AllowUsageIncrease(340)->context(),
   2182                 file, 340));
   2183   ASSERT_EQ(340, ComputeTotalFileSize());
   2184 
   2185   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2186             ofu()->Truncate(
   2187                 AllowUsageIncrease(1020)->context(),
   2188                 dfile1, 1020));
   2189   ASSERT_EQ(1360, ComputeTotalFileSize());
   2190 
   2191   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2192             ofu()->Truncate(
   2193                 AllowUsageIncrease(120)->context(),
   2194                 dfile2, 120));
   2195   ASSERT_EQ(1480, ComputeTotalFileSize());
   2196 
   2197   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2198             ofu()->DeleteFile(
   2199                 AllowUsageIncrease(-PathCost(file) - 340)->context(),
   2200                 file));
   2201   ASSERT_EQ(1140, ComputeTotalFileSize());
   2202 
   2203   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2204             AsyncFileTestHelper::Remove(
   2205                 file_system_context(), dir, true /* recursive */));
   2206   ASSERT_EQ(0, ComputeTotalFileSize());
   2207 }
   2208 
   2209 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
   2210   FileSystemURL file(CreateURLFromUTF8("file"));
   2211   base::PlatformFile file_handle;
   2212   bool created;
   2213 
   2214   // Creating a file.
   2215   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2216             ofu()->EnsureFileExists(
   2217                 AllowUsageIncrease(PathCost(file))->context(),
   2218                 file, &created));
   2219   ASSERT_TRUE(created);
   2220   ASSERT_EQ(0, ComputeTotalFileSize());
   2221 
   2222   // Opening it, which shouldn't change the usage.
   2223   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2224             ofu()->CreateOrOpen(
   2225                 AllowUsageIncrease(0)->context(), file,
   2226                 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
   2227                 &file_handle, &created));
   2228   ASSERT_EQ(0, ComputeTotalFileSize());
   2229   EXPECT_TRUE(base::ClosePlatformFile(file_handle));
   2230 
   2231   const int length = 33;
   2232   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2233             ofu()->Truncate(
   2234                 AllowUsageIncrease(length)->context(), file, length));
   2235   ASSERT_EQ(length, ComputeTotalFileSize());
   2236 
   2237   // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
   2238   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2239             ofu()->CreateOrOpen(
   2240                 AllowUsageIncrease(-length)->context(), file,
   2241                 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
   2242                 &file_handle, &created));
   2243   ASSERT_EQ(0, ComputeTotalFileSize());
   2244   EXPECT_TRUE(base::ClosePlatformFile(file_handle));
   2245 
   2246   // Extending the file again.
   2247   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2248             ofu()->Truncate(
   2249                 AllowUsageIncrease(length)->context(), file, length));
   2250   ASSERT_EQ(length, ComputeTotalFileSize());
   2251 
   2252   // Opening it with TRUNCATED flag, which should truncate the file size.
   2253   ASSERT_EQ(base::PLATFORM_FILE_OK,
   2254             ofu()->CreateOrOpen(
   2255                 AllowUsageIncrease(-length)->context(), file,
   2256                 base::PLATFORM_FILE_OPEN_TRUNCATED | base::PLATFORM_FILE_WRITE,
   2257                 &file_handle, &created));
   2258   ASSERT_EQ(0, ComputeTotalFileSize());
   2259   EXPECT_TRUE(base::ClosePlatformFile(file_handle));
   2260 }
   2261 
   2262 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
   2263   ObfuscatedFileUtil file_util(NULL,
   2264                                data_dir_path(),
   2265                                base::MessageLoopProxy::current().get());
   2266   file_util.InitOriginDatabase(true /*create*/);
   2267   ASSERT_TRUE(file_util.origin_database_ != NULL);
   2268 
   2269   // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive.
   2270   file_util.db_flush_delay_seconds_ = 0;
   2271   file_util.MarkUsed();
   2272   base::MessageLoop::current()->RunUntilIdle();
   2273 
   2274   ASSERT_TRUE(file_util.origin_database_ == NULL);
   2275 }
   2276 
   2277 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
   2278   // Run message loop after OFU is already deleted to make sure callback doesn't
   2279   // cause a crash for use after free.
   2280   {
   2281     ObfuscatedFileUtil file_util(NULL,
   2282                                  data_dir_path(),
   2283                                  base::MessageLoopProxy::current().get());
   2284     file_util.InitOriginDatabase(true /*create*/);
   2285     file_util.db_flush_delay_seconds_ = 0;
   2286     file_util.MarkUsed();
   2287   }
   2288 
   2289   // At this point the callback is still in the message queue but OFU is gone.
   2290   base::MessageLoop::current()->RunUntilIdle();
   2291 }
   2292 
   2293 TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
   2294   storage_policy_->AddIsolated(origin_);
   2295   ObfuscatedFileUtil file_util(
   2296       storage_policy_.get(), data_dir_path(),
   2297       base::MessageLoopProxy::current().get());
   2298 
   2299   // Create DirectoryDatabase for isolated origin.
   2300   SandboxDirectoryDatabase* db = file_util.GetDirectoryDatabase(
   2301       origin_, kFileSystemTypePersistent, true /* create */);
   2302   ASSERT_TRUE(db != NULL);
   2303 
   2304   // Destory it.
   2305   ASSERT_TRUE(
   2306       file_util.DestroyDirectoryDatabase(origin_, kFileSystemTypePersistent));
   2307   ASSERT_TRUE(file_util.directories_.empty());
   2308 }
   2309 
   2310 TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
   2311   storage_policy_->AddIsolated(origin_);
   2312   ObfuscatedFileUtil file_util(
   2313       storage_policy_.get(), data_dir_path(),
   2314       base::MessageLoopProxy::current().get());
   2315 
   2316   // Create DirectoryDatabase for isolated origin.
   2317   SandboxDirectoryDatabase* db = file_util.GetDirectoryDatabase(
   2318       origin_, kFileSystemTypePersistent, true /* create */);
   2319   ASSERT_TRUE(db != NULL);
   2320   ASSERT_EQ(1U, file_util.directories_.size());
   2321 
   2322   // Remove isolated.
   2323   storage_policy_->RemoveIsolated(origin_);
   2324 
   2325   // This should still get the same database.
   2326   SandboxDirectoryDatabase* db2 = file_util.GetDirectoryDatabase(
   2327       origin_, kFileSystemTypePersistent, false /* create */);
   2328   ASSERT_EQ(db, db2);
   2329 }
   2330 
   2331 TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) {
   2332   std::string kFakeDirectoryData("0123456789");
   2333   base::FilePath old_directory_db_path;
   2334 
   2335   // Initialize the directory with one origin using
   2336   // SandboxIsolatedOriginDatabase.
   2337   {
   2338     std::string origin_string =
   2339         webkit_database::GetIdentifierFromOrigin(origin_);
   2340     SandboxIsolatedOriginDatabase database_old(origin_string, data_dir_path());
   2341     base::FilePath path;
   2342     EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path));
   2343     EXPECT_FALSE(path.empty());
   2344 
   2345     // Populate the origin directory with some fake data.
   2346     old_directory_db_path = data_dir_path().Append(path);
   2347     ASSERT_TRUE(file_util::CreateDirectory(old_directory_db_path));
   2348     EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
   2349               file_util::WriteFile(old_directory_db_path.AppendASCII("dummy"),
   2350                                    kFakeDirectoryData.data(),
   2351                                    kFakeDirectoryData.size()));
   2352   }
   2353 
   2354   storage_policy_->AddIsolated(origin_);
   2355   ObfuscatedFileUtil file_util(
   2356       storage_policy_.get(), data_dir_path(),
   2357       base::MessageLoopProxy::current().get());
   2358   base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
   2359   base::FilePath origin_directory = file_util.GetDirectoryForOrigin(
   2360       origin_, true /* create */, &error);
   2361   EXPECT_EQ(base::PLATFORM_FILE_OK, error);
   2362 
   2363   // The database is migrated from the old one.
   2364   EXPECT_TRUE(base::DirectoryExists(origin_directory));
   2365   EXPECT_FALSE(base::DirectoryExists(old_directory_db_path));
   2366 
   2367   // Check we see the same contents in the new origin directory.
   2368   std::string origin_db_data;
   2369   EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy")));
   2370   EXPECT_TRUE(file_util::ReadFileToString(
   2371       origin_directory.AppendASCII("dummy"), &origin_db_data));
   2372   EXPECT_EQ(kFakeDirectoryData, origin_db_data);
   2373 }
   2374 
   2375 }  // namespace fileapi
   2376