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