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