1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file.
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/renderer/safe_builtins.h"
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/logging.h"
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/stl_util.h"
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/renderer/script_context.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace extensions {
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace {
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kClassName[] = "extensions::SafeBuiltins";
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Documentation for makeCallback in the JavaScript, out here to reduce the
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// (very small) amount of effort that the v8 parser needs to do:
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Returns a new object with every function on |obj| configured to call()\n"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// itself with the given arguments.\n"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// E.g. given\n"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//    var result = makeCallable(Function.prototype)\n"
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// |result| will be a object including 'bind' such that\n"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//    result.bind(foo, 1, 2, 3);\n"
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// is equivalent to Function.prototype.bind.call(foo, 1, 2, 3), and so on.\n"
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// This is a convenient way to save functions that user scripts may clobber.\n"
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kScript[] =
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "(function() {\n"
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "'use strict';\n"
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "native function Apply();\n"
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "native function Save();\n"
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "\n"
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "// Used in the callback implementation, could potentially be clobbered.\n"
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "function makeCallable(obj, target, isStatic, propertyNames) {\n"
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "  propertyNames.forEach(function(propertyName) {\n"
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "    var property = obj[propertyName];\n"
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "    target[propertyName] = function() {\n"
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "      var recv = obj;\n"
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "      var firstArgIndex = 0;\n"
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "      if (!isStatic) {\n"
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "        if (arguments.length == 0)\n"
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "          throw 'There must be at least one argument, the receiver';\n"
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "        recv = arguments[0];\n"
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "        firstArgIndex = 1;\n"
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "      }\n"
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "      return Apply(\n"
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "          property, recv, arguments, firstArgIndex, arguments.length);\n"
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "    };\n"
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "  });\n"
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "}\n"
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "\n"
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "function saveBuiltin(builtin, protoPropertyNames, staticPropertyNames) {\n"
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  var safe = function() {\n"
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    throw 'Safe objects cannot be called nor constructed. ' +\n"
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "          'Use $Foo.self() or new $Foo.self() instead.';\n"
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  };\n"
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  safe.self = builtin;\n"
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "  makeCallable(builtin.prototype, safe, false, protoPropertyNames);\n"
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "  if (staticPropertyNames)\n"
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "    makeCallable(builtin, safe, true, staticPropertyNames);\n"
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "  Save(builtin.name, safe);\n"
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "}\n"
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "\n"
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "// Save only what is needed by the extension modules.\n"
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "saveBuiltin(Object,\n"
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "            ['hasOwnProperty'],\n"
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "            ['create', 'defineProperty', 'getOwnPropertyDescriptor',\n"
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "             'getPrototypeOf', 'keys']);\n"
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "saveBuiltin(Function,\n"
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "            ['apply', 'bind', 'call']);\n"
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "saveBuiltin(Array,\n"
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "            ['concat', 'forEach', 'indexOf', 'join', 'push', 'slice',\n"
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "             'splice', 'map', 'filter']);\n"
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "saveBuiltin(String,\n"
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "            ['indexOf', 'slice', 'split']);\n"
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "saveBuiltin(RegExp,\n"
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "            ['test']);\n"
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "saveBuiltin(Error,\n"
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "            [],\n"
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    "            ['captureStackTrace']);\n"
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "\n"
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "// JSON is trickier because extensions can override toJSON in\n"
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "// incompatible ways, and we need to prevent that.\n"
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "var builtinTypes = [\n"
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "  Object, Function, Array, String, Boolean, Number, Date, RegExp\n"
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    "];\n"
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "var builtinToJSONs = builtinTypes.map(function(t) {\n"
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  return t.toJSON;\n"
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "});\n"
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "var builtinArray = Array;\n"
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "var builtinJSONStringify = JSON.stringify;\n"
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "Save('JSON', {\n"
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  parse: JSON.parse,\n"
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  stringify: function(obj) {\n"
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    var savedToJSONs = new builtinArray(builtinTypes.length);\n"
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    try {\n"
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "      for (var i = 0; i < builtinTypes.length; ++i) {\n"
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "        try {\n"
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "          if (builtinTypes[i].prototype.toJSON !==\n"
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "              builtinToJSONs[i]) {\n"
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "            savedToJSONs[i] = builtinTypes[i].prototype.toJSON;\n"
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "            builtinTypes[i].prototype.toJSON = builtinToJSONs[i];\n"
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "          }\n"
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "        } catch (e) {}\n"
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "      }\n"
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    } catch (e) {}\n"
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    try {\n"
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "      return builtinJSONStringify(obj);\n"
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    } finally {\n"
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "      for (var i = 0; i < builtinTypes.length; ++i) {\n"
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "        try {\n"
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "          if (i in savedToJSONs)\n"
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "            builtinTypes[i].prototype.toJSON = savedToJSONs[i];\n"
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "        } catch (e) {}\n"
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "      }\n"
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "    }\n"
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "  }\n"
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "});\n"
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "\n"
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "}());\n";
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)v8::Local<v8::String> MakeKey(const char* name, v8::Isolate* isolate) {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewFromUtf8(
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      isolate, base::StringPrintf("%s::%s", kClassName, name).c_str());
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SaveImpl(const char* name,
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              v8::Local<v8::Value> value,
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              v8::Local<v8::Context> context) {
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK(!value.IsEmpty() && value->IsObject()) << name;
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  context->Global()->SetHiddenValue(MakeKey(name, context->GetIsolate()),
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    value);
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)v8::Local<v8::Object> Load(const char* name, v8::Handle<v8::Context> context) {
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  v8::Local<v8::Value> value =
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      context->Global()->GetHiddenValue(MakeKey(name, context->GetIsolate()));
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK(!value.IsEmpty() && value->IsObject()) << name;
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return value->ToObject();
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class ExtensionImpl : public v8::Extension {
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) public:
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExtensionImpl() : v8::Extension(kClassName, kScript) {}
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) private:
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      v8::Isolate* isolate,
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      v8::Handle<v8::String> name) OVERRIDE {
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (name->Equals(v8::String::NewFromUtf8(isolate, "Apply")))
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return v8::FunctionTemplate::New(isolate, Apply);
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (name->Equals(v8::String::NewFromUtf8(isolate, "Save")))
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return v8::FunctionTemplate::New(isolate, Save);
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    NOTREACHED() << *v8::String::Utf8Value(name);
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return v8::Handle<v8::FunctionTemplate>();
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void Apply(const v8::FunctionCallbackInfo<v8::Value>& info) {
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    CHECK(info.Length() == 5 && info[0]->IsFunction() &&  // function
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          // info[1] could be an object or a string
163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          info[2]->IsObject() &&  // args
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          info[3]->IsInt32() &&   // first_arg_index
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          info[4]->IsInt32());    // args_length
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    v8::Local<v8::Function> function = info[0].As<v8::Function>();
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    v8::Local<v8::Object> recv;
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (info[1]->IsObject()) {
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      recv = info[1]->ToObject();
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (info[1]->IsString()) {
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      recv = v8::StringObject::New(info[1]->ToString())->ToObject();
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      info.GetIsolate()->ThrowException(
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          v8::Exception::TypeError(v8::String::NewFromUtf8(
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              info.GetIsolate(),
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "The first argument is the receiver and must be an object")));
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    v8::Local<v8::Object> args = info[2]->ToObject();
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int first_arg_index = static_cast<int>(info[3]->ToInt32()->Value());
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int args_length = static_cast<int>(info[4]->ToInt32()->Value());
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int argc = args_length - first_arg_index;
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    scoped_ptr<v8::Local<v8::Value> []> argv(new v8::Local<v8::Value>[argc]);
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (int i = 0; i < argc; ++i) {
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CHECK(args->Has(i + first_arg_index));
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      argv[i] = args->Get(i + first_arg_index);
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    v8::Local<v8::Value> return_value = function->Call(recv, argc, argv.get());
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!return_value.IsEmpty())
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      info.GetReturnValue().Set(return_value);
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void Save(const v8::FunctionCallbackInfo<v8::Value>& info) {
196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    CHECK(info.Length() == 2 && info[0]->IsString() && info[1]->IsObject());
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SaveImpl(*v8::String::Utf8Value(info[0]),
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)             info[1],
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             info.GetIsolate()->GetCallingContext());
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)};
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// static
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochv8::Extension* SafeBuiltins::CreateV8Extension() { return new ExtensionImpl(); }
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
208a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSafeBuiltins::SafeBuiltins(ScriptContext* context) : context_(context) {}
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SafeBuiltins::~SafeBuiltins() {}
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)v8::Local<v8::Object> SafeBuiltins::GetArray() const {
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return Load("Array", context_->v8_context());
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)v8::Local<v8::Object> SafeBuiltins::GetFunction() const {
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return Load("Function", context_->v8_context());
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochv8::Local<v8::Object> SafeBuiltins::GetJSON() const {
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return Load("JSON", context_->v8_context());
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)v8::Local<v8::Object> SafeBuiltins::GetObjekt() const {
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return Load("Object", context_->v8_context());
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochv8::Local<v8::Object> SafeBuiltins::GetRegExp() const {
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return Load("RegExp", context_->v8_context());
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochv8::Local<v8::Object> SafeBuiltins::GetString() const {
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return Load("String", context_->v8_context());
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)v8::Local<v8::Object> SafeBuiltins::GetError() const {
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return Load("Error", context_->v8_context());
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  //  namespace extensions
241