44
55#include < vector>
66
7+ #include " base/numerics/safe_math.h"
78#include " gin/handle.h"
89#include " gin/object_template_builder.h"
910#include " gin/wrappable.h"
1213#include " shell/common/gin_converters/callback_converter.h"
1314#include " shell/common/gin_converters/file_path_converter.h"
1415#include " shell/common/gin_helper/dictionary.h"
16+ #include " shell/common/gin_helper/error_thrower.h"
17+ #include " shell/common/gin_helper/function_template_extensions.h"
18+ #include " shell/common/gin_helper/promise.h"
1519#include " shell/common/node_includes.h"
1620#include " shell/common/node_util.h"
1721
@@ -38,7 +42,8 @@ class Archive : public gin::Wrappable<Archive> {
3842 .SetMethod (" readdir" , &Archive::Readdir)
3943 .SetMethod (" realpath" , &Archive::Realpath)
4044 .SetMethod (" copyFileOut" , &Archive::CopyFileOut)
41- .SetMethod (" getFd" , &Archive::GetFD);
45+ .SetMethod (" read" , &Archive::Read)
46+ .SetMethod (" readSync" , &Archive::ReadSync);
4247 }
4348
4449 const char * GetTypeName () override { return " Archive" ; }
@@ -104,15 +109,68 @@ class Archive : public gin::Wrappable<Archive> {
104109 return gin::ConvertToV8 (isolate, new_path);
105110 }
106111
107- // Return the file descriptor.
108- int GetFD () const {
109- if (!archive_)
110- return -1 ;
111- return archive_->GetFD ();
112+ v8::Local<v8::ArrayBuffer> ReadSync (gin_helper::ErrorThrower thrower,
113+ uint64_t offset,
114+ uint64_t length) {
115+ base::CheckedNumeric<uint64_t > safe_offset (offset);
116+ base::CheckedNumeric<uint64_t > safe_end = safe_offset + length;
117+ if (!safe_end.IsValid () ||
118+ safe_end.ValueOrDie () > archive_->file ()->length ()) {
119+ thrower.ThrowError (" Out of bounds read" );
120+ return v8::Local<v8::ArrayBuffer>();
121+ }
122+ auto array_buffer = v8::ArrayBuffer::New (thrower.isolate (), length);
123+ auto backing_store = array_buffer->GetBackingStore ();
124+ memcpy (backing_store->Data (), archive_->file ()->data () + offset, length);
125+ return array_buffer;
126+ }
127+
128+ v8::Local<v8::Promise> Read (v8::Isolate* isolate,
129+ uint64_t offset,
130+ uint64_t length) {
131+ gin_helper::Promise<v8::Local<v8::ArrayBuffer>> promise (isolate);
132+ v8::Local<v8::Promise> handle = promise.GetHandle ();
133+
134+ base::CheckedNumeric<uint64_t > safe_offset (offset);
135+ base::CheckedNumeric<uint64_t > safe_end = safe_offset + length;
136+ if (!safe_end.IsValid () ||
137+ safe_end.ValueOrDie () > archive_->file ()->length ()) {
138+ promise.RejectWithErrorMessage (" Out of bounds read" );
139+ return handle;
140+ }
141+
142+ auto backing_store = v8::ArrayBuffer::NewBackingStore (isolate, length);
143+ base::ThreadPool::PostTaskAndReplyWithResult (
144+ FROM_HERE, {base::MayBlock (), base::TaskPriority::USER_VISIBLE},
145+ base::BindOnce (&Archive::ReadOnIO, isolate, archive_,
146+ std::move (backing_store), offset, length),
147+ base::BindOnce (&Archive::ResolveReadOnUI, std::move (promise)));
148+
149+ return handle;
112150 }
113151
114152 private:
115- std::unique_ptr<asar::Archive> archive_;
153+ static std::unique_ptr<v8::BackingStore> ReadOnIO (
154+ v8::Isolate* isolate,
155+ std::shared_ptr<asar::Archive> archive,
156+ std::unique_ptr<v8::BackingStore> backing_store,
157+ uint64_t offset,
158+ uint64_t length) {
159+ memcpy (backing_store->Data (), archive->file ()->data () + offset, length);
160+ return backing_store;
161+ }
162+
163+ static void ResolveReadOnUI (
164+ gin_helper::Promise<v8::Local<v8::ArrayBuffer>> promise,
165+ std::unique_ptr<v8::BackingStore> backing_store) {
166+ v8::HandleScope scope (promise.isolate ());
167+ v8::Context::Scope context_scope (promise.GetContext ());
168+ auto array_buffer =
169+ v8::ArrayBuffer::New (promise.isolate (), std::move (backing_store));
170+ promise.Resolve (array_buffer);
171+ }
172+
173+ std::shared_ptr<asar::Archive> archive_;
116174
117175 DISALLOW_COPY_AND_ASSIGN (Archive);
118176};
0 commit comments