1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/utils_native_handler.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h"
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/script_context.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace extensions {
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
140529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochUtilsNativeHandler::UtilsNativeHandler(ScriptContext* context)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : ObjectBackedNativeHandler(context) {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RouteFunction("createClassWrapper",
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                base::Bind(&UtilsNativeHandler::CreateClassWrapper,
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                           base::Unretained(this)));
196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RouteFunction(
206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      "deepCopy",
216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      base::Bind(&UtilsNativeHandler::DeepCopy, base::Unretained(this)));
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)UtilsNativeHandler::~UtilsNativeHandler() {}
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void UtilsNativeHandler::CreateClassWrapper(
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const v8::FunctionCallbackInfo<v8::Value>& args) {
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_EQ(3, args.Length());
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(args[0]->IsString());
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string name = *v8::String::Utf8Value(args[0]);
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(args[1]->IsObject());
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Local<v8::Object> cls = args[1].As<v8::Object>();
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(args[2]->IsObject() || args[2]->IsUndefined());
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Local<v8::Value> superclass = args[2];
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::HandleScope handle_scope(GetIsolate());
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(fsamuel): Consider moving the source wrapping to ModuleSystem.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::String> source = v8::String::NewFromUtf8(
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetIsolate(),
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::StringPrintf(
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "(function($Object, $Function, privates, cls, superclass) {"
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          "'use strict';\n"
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "  function %s() {\n"
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "    var privateObj = $Object.create(cls.prototype);\n"
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "    $Function.apply(cls, privateObj, arguments);\n"
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "    privateObj.wrapper = this;\n"
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "    privates(this).impl = privateObj;\n"
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "  };\n"
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "  if (superclass) {\n"
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "    %s.prototype = Object.create(superclass.prototype);\n"
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "  }\n"
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "  return %s;\n"
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "})",
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          name.c_str(),
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          name.c_str(),
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          name.c_str()).c_str());
570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  v8::Handle<v8::Value> func_as_value = context()->module_system()->RunString(
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      source, v8::String::NewFromUtf8(GetIsolate(), name.c_str()));
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    args.GetReturnValue().SetUndefined();
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(fsamuel): Move privates from ModuleSystem to a shared location.
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> natives(context()->module_system()->NewInstance());
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(!natives.IsEmpty());  // this can happen if v8 has issues
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Function> func = func_as_value.As<v8::Function>();
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Value> func_args[] = {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context()->safe_builtins()->GetObjekt(),
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context()->safe_builtins()->GetFunction(),
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      natives->Get(v8::String::NewFromUtf8(
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          GetIsolate(), "privates", v8::String::kInternalizedString)),
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      cls,
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      superclass};
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Local<v8::Value> result;
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::TryCatch try_catch;
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    try_catch.SetCaptureMessage(true);
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    result = context()->CallFunction(func, arraysize(func_args), func_args);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (try_catch.HasCaught()) {
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      args.GetReturnValue().SetUndefined();
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  args.GetReturnValue().Set(result);
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void UtilsNativeHandler::DeepCopy(
896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const v8::FunctionCallbackInfo<v8::Value>& args) {
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  CHECK_EQ(1, args.Length());
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  args.GetReturnValue().Set(
926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      blink::WebSerializedScriptValue::serialize(args[0]).deserialize());
936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace extensions
96