${BASE_SRCDIR}/bundle/extension_module.cc
${BASE_SRCDIR}/bundle/module_system.cc
${BASE_SRCDIR}/bundle/runtime_ipc_client.cc
+ ${BASE_SRCDIR}/bundle/xwalk_v8tools_module.cc
)
# Compiler Flags
} // namespace
-void ExtensionModule::LoadExtensionCode(v8::Handle<v8::Context> context) {
+void ExtensionModule::LoadExtensionCode(
+ v8::Handle<v8::Context> context, v8::Handle<v8::Function> require_native) {
instance_id_ = client_->CreateInstance(extension_name_, this);
std::string exception;
v8::Local<v8::ObjectTemplate>::New(context->GetIsolate(),
object_template_);
- const int argc = 1;
+ const int argc = 2;
v8::Handle<v8::Value> argv[argc] = {
- object_template->NewInstance()
+ object_template->NewInstance(),
+ require_native
};
v8::TryCatch try_catch;
// TODO(cmarcelo): Make this return a v8::Handle<v8::Object>, and
// let the module system set it to the appropriated object.
- void LoadExtensionCode(v8::Handle<v8::Context> context);
+ void LoadExtensionCode(v8::Handle<v8::Context> context,
+ v8::Handle<v8::Function> require_native);
std::string extension_name() const { return extension_name_; }
#include "bundle/extension_client.h"
#include "bundle/extension_module.h"
#include "bundle/module_system.h"
+#include "bundle/xwalk_v8tools_module.h"
namespace wrt {
ModuleSystem::SetModuleSystemInContext(
std::unique_ptr<ModuleSystem>(module_system), context);
+ module_system->RegisterNativeModule(
+ "v8tools", std::unique_ptr<NativeModule>(new XWalkV8ToolsModule));
+
CreateExtensionModules(extensions_client_.get(), module_system);
module_system->Initialize();
}
// pointer back to XWalkExtensionModule.
const char* kWrtModuleSystem = "kWrtModuleSystem";
+void RequireNativeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::ReturnValue<v8::Value> result(info.GetReturnValue());
+
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::Handle<v8::Object> data = info.Data().As<v8::Object>();
+ v8::Handle<v8::Value> module_system_value =
+ data->Get(v8::String::NewFromUtf8(isolate, kWrtModuleSystem));
+ if (module_system_value.IsEmpty() || module_system_value->IsUndefined()) {
+ LOGGER(ERROR) << "Trying to use requireNative from already "
+ << "destroyed module system!";
+ return;
+ }
+
+ ModuleSystem* module_system = static_cast<ModuleSystem*>(
+ module_system_value.As<v8::External>()->Value());
+
+ if (info.Length() < 1) {
+ // TODO(cmarcelo): Throw appropriate exception or warning.
+ result.SetUndefined();
+ return;
+ }
+ v8::Handle<v8::Object> object =
+ module_system->RequireNative(*v8::String::Utf8Value(info[0]));
+ if (object.IsEmpty()) {
+ // TODO(cmarcelo): Throw appropriate exception or warning.
+ result.SetUndefined();
+ return;
+ }
+ result.Set(object);
+}
+
} // namespace
ModuleSystem::ModuleSystem(v8::Handle<v8::Context> context) {
v8::Handle<v8::Object> function_data = v8::Object::New(isolate);
function_data->Set(v8::String::NewFromUtf8(isolate, kWrtModuleSystem),
v8::External::New(isolate, this));
+ v8::Handle<v8::FunctionTemplate> require_native_template =
+ v8::FunctionTemplate::New(isolate, RequireNativeCallback, function_data);
function_data_.Reset(isolate, function_data);
+ require_native_template_.Reset(isolate, require_native_template);
}
ModuleSystem::~ModuleSystem() {
DeleteExtensionModules();
+ auto it = native_modules_.begin();
+ for ( ; it != native_modules_.end(); ++it) {
+ delete it->second;
+ }
+ native_modules_.clear();
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
+ require_native_template_.Reset();
function_data_.Reset();
v8_context_.Reset();
}
ExtensionModuleEntry(extension_name, module.release(), entry_points));
}
+void ModuleSystem::RegisterNativeModule(
+ const std::string& name, std::unique_ptr<NativeModule> module) {
+ if (native_modules_.find(name) != native_modules_.end()) {
+ return;
+ }
+ native_modules_[name] = module.release();
+}
+
+
namespace {
v8::Handle<v8::Value> EnsureTargetObjectForTrampoline(
return true;
}
+v8::Handle<v8::Object> ModuleSystem::RequireNative(
+ const std::string& name) {
+ NativeModuleMap::iterator it = native_modules_.find(name);
+ if (it == native_modules_.end())
+ return v8::Handle<v8::Object>();
+ return it->second->NewInstance();
+}
+
void ModuleSystem::Initialize() {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context = GetV8Context();
+ v8::Handle<v8::FunctionTemplate> require_native_template =
+ v8::Local<v8::FunctionTemplate>::New(isolate, require_native_template_);
+ v8::Handle<v8::Function> require_native =
+ require_native_template->GetFunction();
+
+
MarkModulesWithTrampoline();
for (; it != extension_modules_.end(); ++it) {
if (it->use_trampoline && InstallTrampoline(context, &*it))
continue;
- it->module->LoadExtensionCode(context);
+ it->module->LoadExtensionCode(context, require_native);
EnsureExtensionNamespaceIsReadOnly(context, it->name);
}
}
}
ModuleSystem* module_system = GetModuleSystemFromContext(context);
+ v8::Handle<v8::FunctionTemplate> require_native_template =
+ v8::Local<v8::FunctionTemplate>::New(
+ isolate,
+ module_system->require_native_template_);
+
ExtensionModule* module = entry->module;
- module->LoadExtensionCode(module_system->GetV8Context());
+ module->LoadExtensionCode(module_system->GetV8Context(),
+ require_native_template->GetFunction());
module_system->EnsureExtensionNamespaceIsReadOnly(context, entry->name);
}
#include <vector>
#include <string>
#include <memory>
+#include <map>
namespace wrt {
class ExtensionModule;
+// Interface used to expose objects via the requireNative() function in JS API
+// code. Native modules should be registered with the module system.
+class NativeModule {
+ public:
+ virtual v8::Handle<v8::Object> NewInstance() = 0;
+ virtual ~NativeModule() {}
+};
+
+
class ModuleSystem {
public:
explicit ModuleSystem(v8::Handle<v8::Context> context);
void RegisterExtensionModule(std::unique_ptr<ExtensionModule> module,
const std::vector<std::string>& entry_points);
+ void RegisterNativeModule(const std::string& name,
+ std::unique_ptr<NativeModule> module);
+ v8::Handle<v8::Object> RequireNative(const std::string& name);
void Initialize();
typedef std::vector<ExtensionModuleEntry> ExtensionModules;
ExtensionModules extension_modules_;
+ typedef std::map<std::string, NativeModule*> NativeModuleMap;
+ NativeModuleMap native_modules_;
+ v8::Persistent<v8::FunctionTemplate> require_native_template_;
v8::Persistent<v8::Object> function_data_;
// Points back to the current context, used when native wants to callback
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bundle/xwalk_v8tools_module.h"
+
+#include <v8/v8.h>
+
+#include "common/logger.h"
+
+namespace wrt {
+
+namespace {
+
+void ForceSetPropertyCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ if (info.Length() != 3 || !info[0]->IsObject() || !info[1]->IsString()) {
+ return;
+ }
+ info[0].As<v8::Object>()->ForceSet(info[1], info[2]);
+}
+
+void LifecycleTrackerCleanup(
+ const v8::WeakCallbackData<v8::Object,
+ v8::Persistent<v8::Object> >& data) {
+ v8::Isolate* isolate = data.GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::Local<v8::Object> tracker = data.GetValue();
+ v8::Handle<v8::Value> function =
+ tracker->Get(v8::String::NewFromUtf8(isolate, "destructor"));
+
+ if (function.IsEmpty() || !function->IsFunction()) {
+ LOGGER(WARN) << "Destructor function not set for LifecycleTracker.";
+ data.GetParameter()->Reset();
+ delete data.GetParameter();
+ return;
+ }
+
+ v8::Handle<v8::Context> context = v8::Context::New(isolate);
+
+ v8::TryCatch try_catch;
+ v8::Handle<v8::Function>::Cast(function)->Call(context->Global(), 0, NULL);
+ if (try_catch.HasCaught())
+ LOGGER(WARN) << "Exception when running LifecycleTracker destructor";
+
+ data.GetParameter()->Reset();
+ delete data.GetParameter();
+}
+
+void LifecycleTracker(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::Persistent<v8::Object>* tracker =
+ new v8::Persistent<v8::Object>(isolate, v8::Object::New(isolate));
+ tracker->SetWeak(tracker, &LifecycleTrackerCleanup);
+
+ info.GetReturnValue().Set(*tracker);
+}
+
+} // namespace
+
+XWalkV8ToolsModule::XWalkV8ToolsModule() {
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+
+ // TODO(cmarcelo): Use Template::Set() function that takes isolate, once we
+ // update the Chromium (and V8) version.
+ object_template->Set(v8::String::NewFromUtf8(isolate, "forceSetProperty"),
+ v8::FunctionTemplate::New(
+ isolate, ForceSetPropertyCallback));
+ object_template->Set(v8::String::NewFromUtf8(isolate, "lifecycleTracker"),
+ v8::FunctionTemplate::New(isolate, LifecycleTracker));
+
+ object_template_.Reset(isolate, object_template);
+}
+
+XWalkV8ToolsModule::~XWalkV8ToolsModule() {
+ object_template_.Reset();
+}
+
+v8::Handle<v8::Object> XWalkV8ToolsModule::NewInstance() {
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::EscapableHandleScope handle_scope(isolate);
+ v8::Handle<v8::ObjectTemplate> object_template =
+ v8::Local<v8::ObjectTemplate>::New(isolate, object_template_);
+ return handle_scope.Escape(object_template->NewInstance());
+}
+
+} // namespace wrt
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_BUNDLE_XWALK_V8TOOLS_MODULE_H_
+#define WRT_BUNDLE_XWALK_V8TOOLS_MODULE_H_
+
+#include "bundle/module_system.h"
+
+namespace wrt {
+
+// This module provides extra JS functions that help writing JS API code for
+// extensions, for example: allowing setting a read-only property of an object.
+class XWalkV8ToolsModule : public NativeModule {
+ public:
+ XWalkV8ToolsModule();
+ ~XWalkV8ToolsModule() override;
+
+ private:
+ v8::Handle<v8::Object> NewInstance() override;
+
+ v8::Persistent<v8::ObjectTemplate> object_template_;
+};
+
+} // namespace wrt
+
+#endif // WRT_BUNDLE_XWALK_V8TOOLS_MODULE_H_
\ No newline at end of file