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