atom_blob_reader.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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 "content/browser/blob_storage/chrome_blob_storage_context.h"
  6. #include "content/public/browser/browser_thread.h"
  7. #include "net/base/io_buffer.h"
  8. #include "net/base/net_errors.h"
  9. #include "storage/browser/blob/blob_data_handle.h"
  10. #include "storage/browser/blob/blob_reader.h"
  11. #include "storage/browser/blob/blob_storage_context.h"
  12. #include "storage/browser/fileapi/file_system_context.h"
  13. #include "atom/common/node_includes.h"
  14. using content::BrowserThread;
  15. namespace atom {
  16. namespace {
  17. void FreeNodeBufferData(char* data, void* hint) {
  18. delete[] data;
  19. }
  20. void RunCallbackInUI(
  21. const AtomBlobReader::CompletionCallback& callback,
  22. char* blob_data,
  23. int size) {
  24. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  25. v8::Isolate* isolate = v8::Isolate::GetCurrent();
  26. v8::Locker locker(isolate);
  27. v8::HandleScope handle_scope(isolate);
  28. if (blob_data) {
  29. v8::Local<v8::Value> buffer = node::Buffer::New(isolate,
  30. blob_data, static_cast<size_t>(size), &FreeNodeBufferData, nullptr)
  31. .ToLocalChecked();
  32. callback.Run(buffer);
  33. } else {
  34. callback.Run(v8::Null(isolate));
  35. }
  36. }
  37. } // namespace
  38. AtomBlobReader::AtomBlobReader(
  39. content::ChromeBlobStorageContext* blob_context,
  40. storage::FileSystemContext* file_system_context)
  41. : blob_context_(blob_context),
  42. file_system_context_(file_system_context) {
  43. }
  44. AtomBlobReader::~AtomBlobReader() {
  45. }
  46. void AtomBlobReader::StartReading(
  47. const std::string& uuid,
  48. const AtomBlobReader::CompletionCallback& completion_callback) {
  49. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  50. auto blob_data_handle =
  51. blob_context_->context()->GetBlobDataFromUUID(uuid);
  52. auto callback = base::Bind(&RunCallbackInUI,
  53. completion_callback);
  54. if (!blob_data_handle) {
  55. BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
  56. base::Bind(callback, nullptr, 0));
  57. return;
  58. }
  59. auto blob_reader = blob_data_handle->CreateReader(
  60. file_system_context_.get(),
  61. BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get());
  62. BlobReadHelper* blob_read_helper =
  63. new BlobReadHelper(std::move(blob_reader), callback);
  64. blob_read_helper->Read();
  65. }
  66. AtomBlobReader::BlobReadHelper::BlobReadHelper(
  67. std::unique_ptr<storage::BlobReader> blob_reader,
  68. const BlobReadHelper::CompletionCallback& callback)
  69. : blob_reader_(std::move(blob_reader)),
  70. completion_callback_(callback) {
  71. }
  72. AtomBlobReader::BlobReadHelper::~BlobReadHelper() {
  73. }
  74. void AtomBlobReader::BlobReadHelper::Read() {
  75. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  76. storage::BlobReader::Status size_status = blob_reader_->CalculateSize(
  77. base::Bind(&AtomBlobReader::BlobReadHelper::DidCalculateSize,
  78. base::Unretained(this)));
  79. if (size_status != storage::BlobReader::Status::IO_PENDING)
  80. DidCalculateSize(net::OK);
  81. }
  82. void AtomBlobReader::BlobReadHelper::DidCalculateSize(int result) {
  83. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  84. if (result != net::OK) {
  85. DidReadBlobData(nullptr, 0);
  86. return;
  87. }
  88. uint64_t total_size = blob_reader_->total_size();
  89. int bytes_read = 0;
  90. scoped_refptr<net::IOBuffer> blob_data =
  91. new net::IOBuffer(static_cast<size_t>(total_size));
  92. auto callback = base::Bind(&AtomBlobReader::BlobReadHelper::DidReadBlobData,
  93. base::Unretained(this),
  94. base::RetainedRef(blob_data));
  95. storage::BlobReader::Status read_status = blob_reader_->Read(
  96. blob_data.get(),
  97. total_size,
  98. &bytes_read,
  99. callback);
  100. if (read_status != storage::BlobReader::Status::IO_PENDING)
  101. callback.Run(bytes_read);
  102. }
  103. void AtomBlobReader::BlobReadHelper::DidReadBlobData(
  104. const scoped_refptr<net::IOBuffer>& blob_data,
  105. int size) {
  106. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  107. char* data = new char[size];
  108. memcpy(data, blob_data->data(), size);
  109. BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
  110. base::Bind(completion_callback_, data, size));
  111. delete this;
  112. }
  113. } // namespace atom