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 "content/browser/renderer_host/pepper/quota_reservation.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "content/public/browser/browser_thread.h" 10#include "storage/browser/fileapi/file_system_operation_runner.h" 11#include "storage/browser/fileapi/quota/open_file_handle.h" 12#include "storage/browser/fileapi/quota/quota_reservation.h" 13#include "storage/common/fileapi/file_system_util.h" 14 15namespace content { 16 17// static 18scoped_refptr<QuotaReservation> QuotaReservation::Create( 19 scoped_refptr<storage::FileSystemContext> file_system_context, 20 const GURL& origin_url, 21 storage::FileSystemType type) { 22 return scoped_refptr<QuotaReservation>( 23 new QuotaReservation(file_system_context, origin_url, type)); 24} 25 26QuotaReservation::QuotaReservation( 27 scoped_refptr<storage::FileSystemContext> file_system_context, 28 const GURL& origin_url, 29 storage::FileSystemType file_system_type) 30 : file_system_context_(file_system_context) { 31 quota_reservation_ = 32 file_system_context->CreateQuotaReservationOnFileTaskRunner( 33 origin_url, file_system_type); 34} 35 36// For unit testing only. 37QuotaReservation::QuotaReservation( 38 scoped_refptr<storage::QuotaReservation> quota_reservation, 39 const GURL& /* origin_url */, 40 storage::FileSystemType /* file_system_type */) 41 : quota_reservation_(quota_reservation) { 42} 43 44QuotaReservation::~QuotaReservation() { 45 // We should have no open files at this point. 46 DCHECK(files_.size() == 0); 47 for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it) 48 delete it->second; 49} 50 51int64_t QuotaReservation::OpenFile(int32_t id, 52 const storage::FileSystemURL& url) { 53 base::FilePath platform_file_path; 54 if (file_system_context_.get()) { 55 base::File::Error error = 56 file_system_context_->operation_runner()->SyncGetPlatformPath( 57 url, &platform_file_path); 58 if (error != base::File::FILE_OK) { 59 NOTREACHED(); 60 return 0; 61 } 62 } else { 63 // For test. 64 platform_file_path = url.path(); 65 } 66 67 scoped_ptr<storage::OpenFileHandle> file_handle = 68 quota_reservation_->GetOpenFileHandle(platform_file_path); 69 std::pair<FileMap::iterator, bool> insert_result = 70 files_.insert(std::make_pair(id, file_handle.get())); 71 if (insert_result.second) { 72 int64_t max_written_offset = file_handle->GetMaxWrittenOffset(); 73 ignore_result(file_handle.release()); 74 return max_written_offset; 75 } 76 NOTREACHED(); 77 return 0; 78} 79 80void QuotaReservation::CloseFile(int32_t id, 81 const ppapi::FileGrowth& file_growth) { 82 FileMap::iterator it = files_.find(id); 83 if (it != files_.end()) { 84 it->second->UpdateMaxWrittenOffset(file_growth.max_written_offset); 85 it->second->AddAppendModeWriteAmount(file_growth.append_mode_write_amount); 86 delete it->second; 87 files_.erase(it); 88 } else { 89 NOTREACHED(); 90 } 91} 92 93void QuotaReservation::ReserveQuota(int64_t amount, 94 const ppapi::FileGrowthMap& file_growths, 95 const ReserveQuotaCallback& callback) { 96 for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it) { 97 ppapi::FileGrowthMap::const_iterator growth_it = 98 file_growths.find(it->first); 99 if (growth_it != file_growths.end()) { 100 it->second->UpdateMaxWrittenOffset(growth_it->second.max_written_offset); 101 it->second->AddAppendModeWriteAmount( 102 growth_it->second.append_mode_write_amount); 103 } else { 104 NOTREACHED(); 105 } 106 } 107 108 quota_reservation_->RefreshReservation( 109 amount, base::Bind(&QuotaReservation::GotReservedQuota, this, callback)); 110} 111 112void QuotaReservation::OnClientCrash() { quota_reservation_->OnClientCrash(); } 113 114void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback, 115 base::File::Error error) { 116 ppapi::FileSizeMap file_sizes; 117 for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it) 118 file_sizes[it->first] = it->second->GetMaxWrittenOffset(); 119 120 if (file_system_context_.get()) { 121 BrowserThread::PostTask( 122 BrowserThread::IO, 123 FROM_HERE, 124 base::Bind( 125 callback, quota_reservation_->remaining_quota(), file_sizes)); 126 } else { 127 // Unit testing code path. 128 callback.Run(quota_reservation_->remaining_quota(), file_sizes); 129 } 130} 131 132void QuotaReservation::DeleteOnCorrectThread() const { 133 if (file_system_context_.get() && 134 !file_system_context_->default_file_task_runner() 135 ->RunsTasksOnCurrentThread()) { 136 file_system_context_->default_file_task_runner()->DeleteSoon(FROM_HERE, 137 this); 138 } else { 139 // We're on the right thread to delete, or unit test. 140 delete this; 141 } 142} 143 144} // namespace content 145