atom_blob_reader.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright (c) 2016 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/atom_blob_reader.h"
  5. #include <utility>
  6. #include "base/task/post_task.h"
  7. #include "content/browser/blob_storage/chrome_blob_storage_context.h"
  8. #include "content/public/browser/browser_task_traits.h"
  9. #include "content/public/browser/browser_thread.h"
  10. #include "net/base/io_buffer.h"
  11. #include "net/base/net_errors.h"
  12. #include "storage/browser/blob/blob_data_handle.h"
  13. #include "storage/browser/blob/blob_reader.h"
  14. #include "storage/browser/blob/blob_storage_context.h"
  15. #include "atom/common/node_includes.h"
  16. using content::BrowserThread;
  17. namespace atom {
  18. namespace {
  19. void FreeNodeBufferData(char* data, void* hint) {
  20. delete[] data;
  21. }
  22. void RunCallbackInUI(const AtomBlobReader::CompletionCallback& callback,
  23. char* blob_data,
  24. int size) {
  25. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  26. v8::Isolate* isolate = v8::Isolate::GetCurrent();
  27. v8::Locker locker(isolate);
  28. v8::HandleScope handle_scope(isolate);
  29. if (blob_data) {
  30. v8::Local<v8::Value> buffer =
  31. node::Buffer::New(isolate, blob_data, static_cast<size_t>(size),
  32. &FreeNodeBufferData, nullptr)
  33. .ToLocalChecked();
  34. callback.Run(buffer);
  35. } else {
  36. callback.Run(v8::Null(isolate));
  37. }
  38. }
  39. } // namespace
  40. AtomBlobReader::AtomBlobReader(content::ChromeBlobStorageContext* blob_context)
  41. : blob_context_(blob_context) {}
  42. AtomBlobReader::~AtomBlobReader() {}
  43. void AtomBlobReader::StartReading(
  44. const std::string& uuid,
  45. const AtomBlobReader::CompletionCallback& completion_callback) {
  46. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  47. auto blob_data_handle = blob_context_->context()->GetBlobDataFromUUID(uuid);
  48. auto callback = base::Bind(&RunCallbackInUI, completion_callback);
  49. if (!blob_data_handle) {
  50. base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
  51. base::BindOnce(callback, nullptr, 0));
  52. return;
  53. }
  54. auto blob_reader = blob_data_handle->CreateReader();
  55. BlobReadHelper* blob_read_helper =
  56. new BlobReadHelper(std::move(blob_reader), callback);
  57. blob_read_helper->Read();
  58. }
  59. AtomBlobReader::BlobReadHelper::BlobReadHelper(
  60. std::unique_ptr<storage::BlobReader> blob_reader,
  61. const BlobReadHelper::CompletionCallback& callback)
  62. : blob_reader_(std::move(blob_reader)), completion_callback_(callback) {}
  63. AtomBlobReader::BlobReadHelper::~BlobReadHelper() {}
  64. void AtomBlobReader::BlobReadHelper::Read() {
  65. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  66. storage::BlobReader::Status size_status = blob_reader_->CalculateSize(
  67. base::Bind(&AtomBlobReader::BlobReadHelper::DidCalculateSize,
  68. base::Unretained(this)));
  69. if (size_status != storage::BlobReader::Status::IO_PENDING)
  70. DidCalculateSize(net::OK);
  71. }
  72. void AtomBlobReader::BlobReadHelper::DidCalculateSize(int result) {
  73. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  74. if (result != net::OK) {
  75. DidReadBlobData(nullptr, 0);
  76. return;
  77. }
  78. uint64_t total_size = blob_reader_->total_size();
  79. int bytes_read = 0;
  80. scoped_refptr<net::IOBuffer> blob_data =
  81. new net::IOBuffer(static_cast<size_t>(total_size));
  82. auto callback =
  83. base::Bind(&AtomBlobReader::BlobReadHelper::DidReadBlobData,
  84. base::Unretained(this), base::RetainedRef(blob_data));
  85. storage::BlobReader::Status read_status =
  86. blob_reader_->Read(blob_data.get(), total_size, &bytes_read, callback);
  87. if (read_status != storage::BlobReader::Status::IO_PENDING)
  88. callback.Run(bytes_read);
  89. }
  90. void AtomBlobReader::BlobReadHelper::DidReadBlobData(
  91. const scoped_refptr<net::IOBuffer>& blob_data,
  92. int size) {
  93. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  94. char* data = new char[size];
  95. memcpy(data, blob_data->data(), size);
  96. base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
  97. base::BindOnce(completion_callback_, data, size));
  98. delete this;
  99. }
  100. } // namespace atom