filesystem_proxy_file_stream_reader.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright 2020 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. #include "storage/browser/file_system/filesystem_proxy_file_stream_reader.h"
  5. #include <stdint.h>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/files/file_util.h"
  10. #include "base/location.h"
  11. #include "base/memory/ptr_util.h"
  12. #include "base/metrics/histogram_macros.h"
  13. #include "base/task/task_runner.h"
  14. #include "base/task/task_runner_util.h"
  15. #include "net/base/file_stream.h"
  16. #include "net/base/io_buffer.h"
  17. #include "net/base/net_errors.h"
  18. namespace storage {
  19. namespace {
  20. const int kOpenFlagsForRead =
  21. base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
  22. using GetFileInfoCallback =
  23. base::OnceCallback<void(base::File::Error, const base::File::Info&)>;
  24. base::FileErrorOr<base::File::Info> DoGetFileInfo(
  25. const base::FilePath& path,
  26. scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy>
  27. shared_filesystem_proxy) {
  28. if (!shared_filesystem_proxy->data->PathExists(path)) {
  29. return base::File::FILE_ERROR_NOT_FOUND;
  30. }
  31. absl::optional<base::File::Info> info =
  32. shared_filesystem_proxy->data->GetFileInfo(path);
  33. if (!info.has_value()) {
  34. return base::File::FILE_ERROR_FAILED;
  35. }
  36. return std::move(*info);
  37. }
  38. base::FileErrorOr<base::File> DoOpenFile(
  39. const base::FilePath& path,
  40. scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy>
  41. shared_filesystem_proxy) {
  42. return shared_filesystem_proxy->data->OpenFile(path, kOpenFlagsForRead);
  43. }
  44. } // namespace
  45. std::unique_ptr<FileStreamReader> FileStreamReader::CreateForFilesystemProxy(
  46. scoped_refptr<base::TaskRunner> task_runner,
  47. const base::FilePath& file_path,
  48. std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
  49. int64_t initial_offset,
  50. const base::Time& expected_modification_time) {
  51. DCHECK(filesystem_proxy);
  52. constexpr bool emit_metrics = false;
  53. return base::WrapUnique(new FilesystemProxyFileStreamReader(
  54. std::move(task_runner), file_path, std::move(filesystem_proxy),
  55. initial_offset, expected_modification_time, emit_metrics));
  56. }
  57. std::unique_ptr<FileStreamReader>
  58. FileStreamReader::CreateForIndexedDBDataItemReader(
  59. scoped_refptr<base::TaskRunner> task_runner,
  60. const base::FilePath& file_path,
  61. std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
  62. int64_t initial_offset,
  63. const base::Time& expected_modification_time) {
  64. DCHECK(filesystem_proxy);
  65. constexpr bool emit_metrics = true;
  66. return base::WrapUnique(new FilesystemProxyFileStreamReader(
  67. std::move(task_runner), file_path, std::move(filesystem_proxy),
  68. initial_offset, expected_modification_time, emit_metrics));
  69. }
  70. FilesystemProxyFileStreamReader::~FilesystemProxyFileStreamReader() = default;
  71. int FilesystemProxyFileStreamReader::Read(
  72. net::IOBuffer* buf,
  73. int buf_len,
  74. net::CompletionOnceCallback callback) {
  75. DCHECK(!has_pending_open_);
  76. if (stream_impl_)
  77. return stream_impl_->Read(buf, buf_len, std::move(callback));
  78. Open(base::BindOnce(&FilesystemProxyFileStreamReader::DidOpenForRead,
  79. weak_factory_.GetWeakPtr(), base::RetainedRef(buf),
  80. buf_len, std::move(callback)));
  81. return net::ERR_IO_PENDING;
  82. }
  83. int64_t FilesystemProxyFileStreamReader::GetLength(
  84. net::Int64CompletionOnceCallback callback) {
  85. base::PostTaskAndReplyWithResult(
  86. task_runner_.get(), FROM_HERE,
  87. base::BindOnce(&DoGetFileInfo, file_path_, shared_filesystem_proxy_),
  88. base::BindOnce(
  89. &FilesystemProxyFileStreamReader::DidGetFileInfoForGetLength,
  90. weak_factory_.GetWeakPtr(), std::move(callback)));
  91. return net::ERR_IO_PENDING;
  92. }
  93. FilesystemProxyFileStreamReader::FilesystemProxyFileStreamReader(
  94. scoped_refptr<base::TaskRunner> task_runner,
  95. const base::FilePath& file_path,
  96. std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
  97. int64_t initial_offset,
  98. const base::Time& expected_modification_time,
  99. bool emit_metrics)
  100. : task_runner_(std::move(task_runner)),
  101. shared_filesystem_proxy_(base::MakeRefCounted<SharedFilesystemProxy>(
  102. std::move(filesystem_proxy))),
  103. file_path_(file_path),
  104. initial_offset_(initial_offset),
  105. expected_modification_time_(expected_modification_time),
  106. emit_metrics_(emit_metrics) {}
  107. void FilesystemProxyFileStreamReader::Open(
  108. net::CompletionOnceCallback callback) {
  109. DCHECK(!has_pending_open_);
  110. DCHECK(!stream_impl_.get());
  111. has_pending_open_ = true;
  112. // Call GetLength first to make it perform last-modified-time verification,
  113. // and then call DidVerifyForOpen to do the rest.
  114. int64_t verify_result = GetLength(
  115. base::BindOnce(&FilesystemProxyFileStreamReader::DidVerifyForOpen,
  116. weak_factory_.GetWeakPtr(), std::move(callback)));
  117. DCHECK_EQ(verify_result, net::ERR_IO_PENDING);
  118. }
  119. void FilesystemProxyFileStreamReader::DidVerifyForOpen(
  120. net::CompletionOnceCallback callback,
  121. int64_t get_length_result) {
  122. if (get_length_result < 0) {
  123. std::move(callback).Run(static_cast<int>(get_length_result));
  124. return;
  125. }
  126. callback_ = std::move(callback);
  127. base::PostTaskAndReplyWithResult(
  128. task_runner_.get(), FROM_HERE,
  129. base::BindOnce(&DoOpenFile, file_path_, shared_filesystem_proxy_),
  130. base::BindOnce(&FilesystemProxyFileStreamReader::DidOpenFile,
  131. weak_factory_.GetWeakPtr()));
  132. }
  133. void FilesystemProxyFileStreamReader::DidOpenFile(
  134. base::FileErrorOr<base::File> open_result) {
  135. if (open_result.is_error()) {
  136. std::move(callback_).Run(open_result.error());
  137. return;
  138. }
  139. stream_impl_ = std::make_unique<net::FileStream>(
  140. std::move(open_result.value()), task_runner_);
  141. int seek_result = stream_impl_->Seek(
  142. initial_offset_,
  143. base::BindOnce(&FilesystemProxyFileStreamReader::DidSeekFileStream,
  144. weak_factory_.GetWeakPtr()));
  145. if (seek_result != net::ERR_IO_PENDING) {
  146. std::move(callback_).Run(seek_result);
  147. }
  148. }
  149. void FilesystemProxyFileStreamReader::DidSeekFileStream(int64_t seek_result) {
  150. if (seek_result < 0) {
  151. std::move(callback_).Run(static_cast<int>(seek_result));
  152. return;
  153. }
  154. if (seek_result != initial_offset_) {
  155. std::move(callback_).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
  156. return;
  157. }
  158. std::move(callback_).Run(net::OK);
  159. }
  160. void FilesystemProxyFileStreamReader::DidOpenForRead(
  161. net::IOBuffer* buf,
  162. int buf_len,
  163. net::CompletionOnceCallback callback,
  164. int open_result) {
  165. DCHECK(has_pending_open_);
  166. has_pending_open_ = false;
  167. if (open_result != net::OK) {
  168. stream_impl_.reset();
  169. std::move(callback).Run(open_result);
  170. return;
  171. }
  172. DCHECK(stream_impl_.get());
  173. callback_ = std::move(callback);
  174. const int read_result = stream_impl_->Read(
  175. buf, buf_len,
  176. base::BindOnce(&FilesystemProxyFileStreamReader::OnRead,
  177. weak_factory_.GetWeakPtr()));
  178. if (read_result != net::ERR_IO_PENDING)
  179. std::move(callback_).Run(read_result);
  180. }
  181. void FilesystemProxyFileStreamReader::DidGetFileInfoForGetLength(
  182. net::Int64CompletionOnceCallback callback,
  183. base::FileErrorOr<base::File::Info> result) {
  184. // TODO(enne): track rate of missing blobs for http://crbug.com/1131151
  185. if (emit_metrics_) {
  186. bool file_was_found = !result.is_error() ||
  187. result.error() != base::File::FILE_ERROR_NOT_FOUND;
  188. UMA_HISTOGRAM_BOOLEAN("WebCore.IndexedDB.FoundBlobFileForValue",
  189. file_was_found);
  190. }
  191. if (result.is_error()) {
  192. std::move(callback).Run(net::FileErrorToNetError(result.error()));
  193. return;
  194. }
  195. const auto& file_info = result.value();
  196. if (file_info.is_directory) {
  197. std::move(callback).Run(net::ERR_FILE_NOT_FOUND);
  198. return;
  199. }
  200. if (!VerifySnapshotTime(expected_modification_time_, file_info)) {
  201. std::move(callback).Run(net::ERR_UPLOAD_FILE_CHANGED);
  202. return;
  203. }
  204. std::move(callback).Run(file_info.size);
  205. }
  206. void FilesystemProxyFileStreamReader::OnRead(int read_result) {
  207. std::move(callback_).Run(read_result);
  208. }
  209. } // namespace storage