From 2da2701bb2bc3580fa5bac16fee5b9d20d4eedb1 Mon Sep 17 00:00:00 2001 From: bridiver Date: Thu, 13 Apr 2017 11:48:12 -0700 Subject: [PATCH] add file api for writeImportant auditors @bbondy @bsclifton --- atom/browser/javascript_environment.cc | 14 +- brave/browser/extensions/BUILD.gn | 2 + brave/browser/extensions/file_bindings.cc | 133 ++++++++++++++++++ brave/browser/extensions/file_bindings.h | 46 ++++++ brave/common/converters/string16_converter.h | 5 +- .../extensions/shared_memory_bindings.cc | 6 +- 6 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 brave/browser/extensions/file_bindings.cc create mode 100644 brave/browser/extensions/file_bindings.h diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index 8d335d74d9..16b86ccb04 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -17,6 +17,7 @@ #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/threading/thread_task_runner_handle.h" +#include "brave/browser/extensions/file_bindings.h" #include "brave/browser/extensions/path_bindings.h" #include "brave/common/extensions/shared_memory_bindings.h" #include "content/public/common/content_switches.h" @@ -149,10 +150,6 @@ JavascriptEnvironment::JavascriptEnvironment() script_context_->module_system()->RegisterNativeHandler( "path", std::unique_ptr( new brave::PathBindings(script_context_.get(), &source_map_))); - script_context_->module_system()->RegisterNativeHandler( - "shared_memory", std::unique_ptr( - new extensions::SharedMemoryBindings( - script_context_.get()))); } ModuleRegistry* registry = ModuleRegistry::From(context()); @@ -164,8 +161,13 @@ JavascriptEnvironment::JavascriptEnvironment() v8::Local muon = v8::Object::New(isolate_); global->Set(v8::String::NewFromUtf8(isolate_, "muon"), muon); - v8::Local api = extensions::SharedMemoryBindings::API(script_context_.get()); - muon->Set(v8::String::NewFromUtf8(isolate_, "shared_memory"), api); + v8::Local shared_memory = + extensions::SharedMemoryBindings::API(script_context_.get()); + muon->Set(v8::String::NewFromUtf8(isolate_, "shared_memory"), shared_memory); + + v8::Local file = + extensions::FileBindings::API(script_context_.get()); + muon->Set(v8::String::NewFromUtf8(isolate_, "file"), file); } JavascriptEnvironment::~JavascriptEnvironment() { diff --git a/brave/browser/extensions/BUILD.gn b/brave/browser/extensions/BUILD.gn index 993e9ee106..4fae068ea2 100644 --- a/brave/browser/extensions/BUILD.gn +++ b/brave/browser/extensions/BUILD.gn @@ -14,6 +14,8 @@ static_library("extensions") { ] sources = [ + "file_bindings.cc", + "file_bindings.h", "path_bindings.cc", "path_bindings.h", "api/guest_view/tab_view/tab_view_internal_api.cc", diff --git a/brave/browser/extensions/file_bindings.cc b/brave/browser/extensions/file_bindings.cc new file mode 100644 index 0000000000..708d22afd2 --- /dev/null +++ b/brave/browser/extensions/file_bindings.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2017 The Brave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "brave/browser/extensions/file_bindings.h" + +#include "base/files/important_file_writer.h" +#include "base/memory/ptr_util.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "brave/common/converters/string16_converter.h" +#include "content/public/browser/browser_thread.h" +#include "extensions/renderer/script_context.h" +#include "extensions/renderer/v8_helpers.h" +#include "v8/include/v8.h" + +using content::BrowserThread; + +namespace extensions { + +namespace { + +void PostWriteCallback( + const base::Callback& callback, + scoped_refptr reply_task_runner, + bool write_success) { + // We can't run |callback| on the current thread. Bounce back to + // the |reply_task_runner| which is the correct sequenced thread. + reply_task_runner->PostTask(FROM_HERE, + base::Bind(callback, write_success)); +} + +} // namespace + +FileBindings::FileBindings(extensions::ScriptContext* context) + : extensions::ObjectBackedNativeHandler(context) { + RouteFunction("WriteImportantFile", + base::Bind(&FileBindings::WriteImportantFile, base::Unretained(this))); +} + +FileBindings::~FileBindings() { +} + +// static +v8::Local FileBindings::API( + extensions::ScriptContext* context) { + context->module_system()->RegisterNativeHandler( + "muon_file", std::unique_ptr( + new FileBindings(context))); + + v8::Local file_api = v8::Object::New(context->isolate()); + context->module_system()->SetNativeLazyField( + file_api, "writeImportant", "muon_file", "WriteImportantFile"); + + return file_api; +} + +void FileBindings::WriteImportantFile( + const v8::FunctionCallbackInfo& args) { + auto isolate = args.GetIsolate(); + + if (args.Length() < 2) { + isolate->ThrowException(v8::String::NewFromUtf8( + isolate, + "Wrong number of arguments: expected 2 and received " + args.Length())); + return; + } + + base::FilePath::StringType path_name; + if (!args[0]->IsString() || + !gin::Converter::FromV8( + isolate, args[0], &path_name)) { + isolate->ThrowException(v8::String::NewFromUtf8( + isolate, "`path` must be a string")); + return; + } + base::FilePath path(path_name); + + if (!args[1]->IsString()) { + isolate->ThrowException(v8::String::NewFromUtf8( + isolate, "`data` must be a string")); + return; + } + std::string data = *v8::String::Utf8Value(args[1]); + + std::unique_ptr> callback; + if (args.Length() > 2 && args[2]->IsFunction()) { + callback.reset( + new v8::Global(isolate, args[2].As())); + } + + auto task_runner = GetTaskRunnerForFile(path, + BrowserThread::GetBlockingPool()); + base::ImportantFileWriter writer(path, task_runner); + + writer.RegisterOnNextWriteCallbacks( + base::Closure(), + base::Bind( + &PostWriteCallback, + base::Bind(&FileBindings::RunCallback, AsWeakPtr(), + base::Passed(&callback)), + base::SequencedTaskRunnerHandle::Get())); + + writer.WriteNow(base::MakeUnique(data)); +} + +scoped_refptr FileBindings::GetTaskRunnerForFile( + const base::FilePath& filename, + base::SequencedWorkerPool* worker_pool) { + std::string token("muon-file-"); + token.append(filename.AsUTF8Unsafe()); + return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( + worker_pool->GetNamedSequenceToken(token), + base::SequencedWorkerPool::BLOCK_SHUTDOWN); +} + +void FileBindings::RunCallback( + std::unique_ptr> callback, bool success) { + if (!context()->is_valid() || !callback.get() || callback->IsEmpty()) + return; + + auto isolate = context()->isolate(); + v8::HandleScope handle_scope(isolate); + + v8::Local callback_args[] = { + v8::Boolean::New(isolate, success) }; + context()->SafeCallFunction( + v8::Local::New(isolate, *callback), 1, callback_args); +} + +} // namespace extensions diff --git a/brave/browser/extensions/file_bindings.h b/brave/browser/extensions/file_bindings.h new file mode 100644 index 0000000000..9b7148c131 --- /dev/null +++ b/brave/browser/extensions/file_bindings.h @@ -0,0 +1,46 @@ +// Copyright (c) 2017 The Brave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BRAVE_BROWSER_EXTENSIONS_FILE_BINDINGS_H_ +#define BRAVE_BROWSER_EXTENSIONS_FILE_BINDINGS_H_ + +#include + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "extensions/renderer/object_backed_native_handler.h" +#include "v8/include/v8.h" + +namespace base { +class FilePath; +class SequencedTaskRunner; +class SequencedWorkerPool; +} + +namespace extensions { + +class FileBindings : public extensions::ObjectBackedNativeHandler, + public base::SupportsWeakPtr { + public: + explicit FileBindings(extensions::ScriptContext* context); + ~FileBindings() override; + + static v8::Local API(extensions::ScriptContext* context); + + private: + void WriteImportantFile(const v8::FunctionCallbackInfo& args); + void RunCallback( + std::unique_ptr> holder, bool success); + + static scoped_refptr GetTaskRunnerForFile( + const base::FilePath& filename, + base::SequencedWorkerPool* worker_pool); + + DISALLOW_COPY_AND_ASSIGN(FileBindings); +}; + +} // namespace extensions + +#endif // BRAVE_BROWSER_EXTENSIONS_FILE_BINDINGS_H_ diff --git a/brave/common/converters/string16_converter.h b/brave/common/converters/string16_converter.h index 09122633ba..d69cfff192 100644 --- a/brave/common/converters/string16_converter.h +++ b/brave/common/converters/string16_converter.h @@ -14,8 +14,9 @@ template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, const base::string16& val) { - return MATE_STRING_NEW_FROM_UTF16( - isolate, reinterpret_cast(val.data()), val.size()); + return v8::String::NewFromTwoByte( + isolate, reinterpret_cast(val.data()), + v8::String::kNormalString, val.size()); } static bool FromV8(v8::Isolate* isolate, v8::Local val, diff --git a/brave/common/extensions/shared_memory_bindings.cc b/brave/common/extensions/shared_memory_bindings.cc index f5a6ed5942..ccd10d1a74 100644 --- a/brave/common/extensions/shared_memory_bindings.cc +++ b/brave/common/extensions/shared_memory_bindings.cc @@ -166,9 +166,13 @@ SharedMemoryBindings::~SharedMemoryBindings() { // static v8::Local SharedMemoryBindings::API( extensions::ScriptContext* context) { + context->module_system()->RegisterNativeHandler( + "muon_shared_memory", std::unique_ptr( + new SharedMemoryBindings(context))); + v8::Local shared_memory_api = v8::Object::New(context->isolate()); context->module_system()->SetNativeLazyField( - shared_memory_api, "create", "shared_memory", "Create"); + shared_memory_api, "create", "muon_shared_memory", "Create"); return shared_memory_api; }