| // Copyright 2014 The Chromium 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 "extensions/renderer/utils_native_handler.h" |
| |
| #include "base/strings/stringprintf.h" |
| #include "extensions/renderer/script_context.h" |
| #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" |
| #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" |
| |
| namespace extensions { |
| |
| UtilsNativeHandler::UtilsNativeHandler(ScriptContext* context) |
| : ObjectBackedNativeHandler(context) { |
| RouteFunction("createClassWrapper", |
| base::Bind(&UtilsNativeHandler::CreateClassWrapper, |
| base::Unretained(this))); |
| RouteFunction( |
| "deepCopy", |
| base::Bind(&UtilsNativeHandler::DeepCopy, base::Unretained(this))); |
| } |
| |
| UtilsNativeHandler::~UtilsNativeHandler() {} |
| |
| void UtilsNativeHandler::CreateClassWrapper( |
| const v8::FunctionCallbackInfo<v8::Value>& args) { |
| CHECK_EQ(3, args.Length()); |
| CHECK(args[0]->IsString()); |
| std::string name = *v8::String::Utf8Value(args[0]); |
| CHECK(args[1]->IsObject()); |
| v8::Local<v8::Object> cls = args[1].As<v8::Object>(); |
| CHECK(args[2]->IsObject() || args[2]->IsUndefined()); |
| v8::Local<v8::Value> superclass = args[2]; |
| |
| v8::HandleScope handle_scope(GetIsolate()); |
| // TODO(fsamuel): Consider moving the source wrapping to ModuleSystem. |
| v8::Handle<v8::String> source = v8::String::NewFromUtf8( |
| GetIsolate(), |
| base::StringPrintf( |
| "(function($Object, $Function, privates, cls, superclass) {" |
| "'use strict';\n" |
| " function %s() {\n" |
| " var privateObj = $Object.create(cls.prototype);\n" |
| " $Function.apply(cls, privateObj, arguments);\n" |
| " privateObj.wrapper = this;\n" |
| " privates(this).impl = privateObj;\n" |
| " };\n" |
| " if (superclass) {\n" |
| " %s.prototype = Object.create(superclass.prototype);\n" |
| " }\n" |
| " return %s;\n" |
| "})", |
| name.c_str(), |
| name.c_str(), |
| name.c_str()).c_str()); |
| v8::Handle<v8::Value> func_as_value = context()->module_system()->RunString( |
| source, v8::String::NewFromUtf8(GetIsolate(), name.c_str())); |
| if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { |
| args.GetReturnValue().SetUndefined(); |
| return; |
| } |
| |
| // TODO(fsamuel): Move privates from ModuleSystem to a shared location. |
| v8::Handle<v8::Object> natives(context()->module_system()->NewInstance()); |
| CHECK(!natives.IsEmpty()); // this can happen if v8 has issues |
| v8::Handle<v8::Function> func = func_as_value.As<v8::Function>(); |
| v8::Handle<v8::Value> func_args[] = { |
| context()->safe_builtins()->GetObjekt(), |
| context()->safe_builtins()->GetFunction(), |
| natives->Get(v8::String::NewFromUtf8( |
| GetIsolate(), "privates", v8::String::kInternalizedString)), |
| cls, |
| superclass}; |
| v8::Local<v8::Value> result; |
| { |
| v8::TryCatch try_catch; |
| try_catch.SetCaptureMessage(true); |
| result = context()->CallFunction(func, arraysize(func_args), func_args); |
| if (try_catch.HasCaught()) { |
| args.GetReturnValue().SetUndefined(); |
| return; |
| } |
| } |
| args.GetReturnValue().Set(result); |
| } |
| |
| void UtilsNativeHandler::DeepCopy( |
| const v8::FunctionCallbackInfo<v8::Value>& args) { |
| CHECK_EQ(1, args.Length()); |
| args.GetReturnValue().Set( |
| blink::WebSerializedScriptValue::serialize(args[0]).deserialize()); |
| } |
| |
| } // namespace extensions |