// Copyright (c) 2013 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. #ifndef SHELL_COMMON_NODE_BINDINGS_H_ #define SHELL_COMMON_NODE_BINDINGS_H_ #include #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "uv.h" // NOLINT(build/include_directory) #include "v8/include/v8.h" namespace base { class MessageLoop; } namespace node { class Environment; class MultiIsolatePlatform; class IsolateData; } // namespace node namespace electron { // A helper class to manage uv_handle_t types, e.g. uv_async_t. // // As per the uv docs: "uv_close() MUST be called on each handle before // memory is released. Moreover, the memory can only be released in // close_cb or after it has returned." This class encapsulates the work // needed to follow those requirements. template ::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value>::type* = nullptr> class UvHandle { public: UvHandle() : t_(new T) {} ~UvHandle() { reset(); } T* get() { return t_; } uv_handle_t* handle() { return reinterpret_cast(t_); } void reset() { auto* h = handle(); if (h != nullptr) { DCHECK_EQ(0, uv_is_closing(h)); uv_close(h, OnClosed); t_ = nullptr; } } private: static void OnClosed(uv_handle_t* handle) { delete reinterpret_cast(handle); } T* t_ = {}; }; class NodeBindings { public: enum class BrowserEnvironment { kBrowser, kRenderer, kWorker }; static NodeBindings* Create(BrowserEnvironment browser_env); static void RegisterBuiltinModules(); static bool IsInitialized(); virtual ~NodeBindings(); // Setup V8, libuv. void Initialize(); // Create the environment and load node.js. node::Environment* CreateEnvironment(v8::Handle context, node::MultiIsolatePlatform* platform); // Load node.js in the environment. void LoadEnvironment(node::Environment* env); // Prepare for message loop integration. void PrepareMessageLoop(); // Do message loop integration. virtual void RunMessageLoop(); node::IsolateData* isolate_data() const { return isolate_data_; } // Gets/sets the environment to wrap uv loop. void set_uv_env(node::Environment* env) { uv_env_ = env; } node::Environment* uv_env() const { return uv_env_; } uv_loop_t* uv_loop() const { return uv_loop_; } bool in_worker_loop() const { return uv_loop_ == &worker_loop_; } protected: explicit NodeBindings(BrowserEnvironment browser_env); // Called to poll events in new thread. virtual void PollEvents() = 0; // Run the libuv loop for once. void UvRunOnce(); // Make the main thread run libuv loop. void WakeupMainThread(); // Interrupt the PollEvents. void WakeupEmbedThread(); // Which environment we are running. const BrowserEnvironment browser_env_; // Current thread's MessageLoop. scoped_refptr task_runner_; // Current thread's libuv loop. uv_loop_t* uv_loop_; private: // Thread to poll uv events. static void EmbedThreadRunner(void* arg); // Whether the libuv loop has ended. bool embed_closed_ = false; // Loop used when constructed in WORKER mode uv_loop_t worker_loop_; // Dummy handle to make uv's loop not quit. UvHandle dummy_uv_handle_; // Thread for polling events. uv_thread_t embed_thread_; // Semaphore to wait for main loop in the embed thread. uv_sem_t embed_sem_; // Environment that to wrap the uv loop. node::Environment* uv_env_ = nullptr; // Isolate data used in creating the environment node::IsolateData* isolate_data_ = nullptr; base::WeakPtrFactory weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NodeBindings); }; } // namespace electron #endif // SHELL_COMMON_NODE_BINDINGS_H_