OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/extensions/safe_builtins.h" | 5 #include "extensions/renderer/safe_builtins.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "chrome/renderer/extensions/chrome_v8_context.h" | 10 #include "extensions/renderer/script_context.h" |
11 | 11 |
12 namespace extensions { | 12 namespace extensions { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 const char kClassName[] = "extensions::SafeBuiltins"; | 16 const char kClassName[] = "extensions::SafeBuiltins"; |
17 | 17 |
18 // Documentation for makeCallback in the JavaScript, out here to reduce the | 18 // Documentation for makeCallback in the JavaScript, out here to reduce the |
19 // (very small) amount of effort that the v8 parser needs to do: | 19 // (very small) amount of effort that the v8 parser needs to do: |
20 // | 20 // |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 | 120 |
121 v8::Local<v8::String> MakeKey(const char* name, v8::Isolate* isolate) { | 121 v8::Local<v8::String> MakeKey(const char* name, v8::Isolate* isolate) { |
122 return v8::String::NewFromUtf8( | 122 return v8::String::NewFromUtf8( |
123 isolate, base::StringPrintf("%s::%s", kClassName, name).c_str()); | 123 isolate, base::StringPrintf("%s::%s", kClassName, name).c_str()); |
124 } | 124 } |
125 | 125 |
126 void SaveImpl(const char* name, | 126 void SaveImpl(const char* name, |
127 v8::Local<v8::Value> value, | 127 v8::Local<v8::Value> value, |
128 v8::Local<v8::Context> context) { | 128 v8::Local<v8::Context> context) { |
129 CHECK(!value.IsEmpty() && value->IsObject()) << name; | 129 CHECK(!value.IsEmpty() && value->IsObject()) << name; |
130 context->Global() | 130 context->Global()->SetHiddenValue(MakeKey(name, context->GetIsolate()), |
131 ->SetHiddenValue(MakeKey(name, context->GetIsolate()), value); | 131 value); |
132 } | 132 } |
133 | 133 |
134 v8::Local<v8::Object> Load(const char* name, v8::Handle<v8::Context> context) { | 134 v8::Local<v8::Object> Load(const char* name, v8::Handle<v8::Context> context) { |
135 v8::Local<v8::Value> value = | 135 v8::Local<v8::Value> value = |
136 context->Global()->GetHiddenValue(MakeKey(name, context->GetIsolate())); | 136 context->Global()->GetHiddenValue(MakeKey(name, context->GetIsolate())); |
137 CHECK(!value.IsEmpty() && value->IsObject()) << name; | 137 CHECK(!value.IsEmpty() && value->IsObject()) << name; |
138 return value->ToObject(); | 138 return value->ToObject(); |
139 } | 139 } |
140 | 140 |
141 class ExtensionImpl : public v8::Extension { | 141 class ExtensionImpl : public v8::Extension { |
142 public: | 142 public: |
143 ExtensionImpl() : v8::Extension(kClassName, kScript) {} | 143 ExtensionImpl() : v8::Extension(kClassName, kScript) {} |
144 | 144 |
145 private: | 145 private: |
146 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( | 146 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( |
147 v8::Isolate* isolate, | 147 v8::Isolate* isolate, |
148 v8::Handle<v8::String> name) OVERRIDE { | 148 v8::Handle<v8::String> name) OVERRIDE { |
149 if (name->Equals(v8::String::NewFromUtf8(isolate, "Apply"))) | 149 if (name->Equals(v8::String::NewFromUtf8(isolate, "Apply"))) |
150 return v8::FunctionTemplate::New(isolate, Apply); | 150 return v8::FunctionTemplate::New(isolate, Apply); |
151 if (name->Equals(v8::String::NewFromUtf8(isolate, "Save"))) | 151 if (name->Equals(v8::String::NewFromUtf8(isolate, "Save"))) |
152 return v8::FunctionTemplate::New(isolate, Save); | 152 return v8::FunctionTemplate::New(isolate, Save); |
153 NOTREACHED() << *v8::String::Utf8Value(name); | 153 NOTREACHED() << *v8::String::Utf8Value(name); |
154 return v8::Handle<v8::FunctionTemplate>(); | 154 return v8::Handle<v8::FunctionTemplate>(); |
155 } | 155 } |
156 | 156 |
157 static void Apply(const v8::FunctionCallbackInfo<v8::Value>& info) { | 157 static void Apply(const v8::FunctionCallbackInfo<v8::Value>& info) { |
158 CHECK(info.Length() == 5 && | 158 CHECK(info.Length() == 5 && info[0]->IsFunction() && // function |
159 info[0]->IsFunction() && // function | |
160 // info[1] could be an object or a string | 159 // info[1] could be an object or a string |
161 info[2]->IsObject() && // args | 160 info[2]->IsObject() && // args |
162 info[3]->IsInt32() && // first_arg_index | 161 info[3]->IsInt32() && // first_arg_index |
163 info[4]->IsInt32()); // args_length | 162 info[4]->IsInt32()); // args_length |
164 v8::Local<v8::Function> function = info[0].As<v8::Function>(); | 163 v8::Local<v8::Function> function = info[0].As<v8::Function>(); |
165 v8::Local<v8::Object> recv; | 164 v8::Local<v8::Object> recv; |
166 if (info[1]->IsObject()) { | 165 if (info[1]->IsObject()) { |
167 recv = info[1]->ToObject(); | 166 recv = info[1]->ToObject(); |
168 } else if (info[1]->IsString()) { | 167 } else if (info[1]->IsString()) { |
169 recv = v8::StringObject::New(info[1]->ToString())->ToObject(); | 168 recv = v8::StringObject::New(info[1]->ToString())->ToObject(); |
170 } else { | 169 } else { |
171 info.GetIsolate()->ThrowException( | 170 info.GetIsolate()->ThrowException( |
172 v8::Exception::TypeError(v8::String::NewFromUtf8( | 171 v8::Exception::TypeError(v8::String::NewFromUtf8( |
173 info.GetIsolate(), | 172 info.GetIsolate(), |
174 "The first argument is the receiver and must be an object"))); | 173 "The first argument is the receiver and must be an object"))); |
175 return; | 174 return; |
176 } | 175 } |
177 v8::Local<v8::Object> args = info[2]->ToObject(); | 176 v8::Local<v8::Object> args = info[2]->ToObject(); |
178 int first_arg_index = static_cast<int>(info[3]->ToInt32()->Value()); | 177 int first_arg_index = static_cast<int>(info[3]->ToInt32()->Value()); |
179 int args_length = static_cast<int>(info[4]->ToInt32()->Value()); | 178 int args_length = static_cast<int>(info[4]->ToInt32()->Value()); |
180 | 179 |
181 int argc = args_length - first_arg_index; | 180 int argc = args_length - first_arg_index; |
182 scoped_ptr<v8::Local<v8::Value>[]> argv(new v8::Local<v8::Value>[argc]); | 181 scoped_ptr<v8::Local<v8::Value> []> argv(new v8::Local<v8::Value>[argc]); |
183 for (int i = 0; i < argc; ++i) { | 182 for (int i = 0; i < argc; ++i) { |
184 CHECK(args->Has(i + first_arg_index)); | 183 CHECK(args->Has(i + first_arg_index)); |
185 argv[i] = args->Get(i + first_arg_index); | 184 argv[i] = args->Get(i + first_arg_index); |
186 } | 185 } |
187 | 186 |
188 v8::Local<v8::Value> return_value = function->Call(recv, argc, argv.get()); | 187 v8::Local<v8::Value> return_value = function->Call(recv, argc, argv.get()); |
189 if (!return_value.IsEmpty()) | 188 if (!return_value.IsEmpty()) |
190 info.GetReturnValue().Set(return_value); | 189 info.GetReturnValue().Set(return_value); |
191 } | 190 } |
192 | 191 |
193 static void Save(const v8::FunctionCallbackInfo<v8::Value>& info) { | 192 static void Save(const v8::FunctionCallbackInfo<v8::Value>& info) { |
194 CHECK(info.Length() == 2 && | 193 CHECK(info.Length() == 2 && info[0]->IsString() && info[1]->IsObject()); |
195 info[0]->IsString() && | |
196 info[1]->IsObject()); | |
197 SaveImpl(*v8::String::Utf8Value(info[0]), | 194 SaveImpl(*v8::String::Utf8Value(info[0]), |
198 info[1], | 195 info[1], |
199 info.GetIsolate()->GetCallingContext()); | 196 info.GetIsolate()->GetCallingContext()); |
200 } | 197 } |
201 }; | 198 }; |
202 | 199 |
203 } // namespace | 200 } // namespace |
204 | 201 |
205 // static | 202 // static |
206 v8::Extension* SafeBuiltins::CreateV8Extension() { | 203 v8::Extension* SafeBuiltins::CreateV8Extension() { return new ExtensionImpl(); } |
207 return new ExtensionImpl(); | |
208 } | |
209 | 204 |
210 SafeBuiltins::SafeBuiltins(ChromeV8Context* context) : context_(context) {} | 205 SafeBuiltins::SafeBuiltins(ScriptContext* context) : context_(context) {} |
211 | 206 |
212 SafeBuiltins::~SafeBuiltins() {} | 207 SafeBuiltins::~SafeBuiltins() {} |
213 | 208 |
214 v8::Local<v8::Object> SafeBuiltins::GetArray() const { | 209 v8::Local<v8::Object> SafeBuiltins::GetArray() const { |
215 return Load("Array", context_->v8_context()); | 210 return Load("Array", context_->v8_context()); |
216 } | 211 } |
217 | 212 |
218 v8::Local<v8::Object> SafeBuiltins::GetFunction() const { | 213 v8::Local<v8::Object> SafeBuiltins::GetFunction() const { |
219 return Load("Function", context_->v8_context()); | 214 return Load("Function", context_->v8_context()); |
220 } | 215 } |
221 | 216 |
222 v8::Local<v8::Object> SafeBuiltins::GetJSON() const { | 217 v8::Local<v8::Object> SafeBuiltins::GetJSON() const { |
223 return Load("JSON", context_->v8_context()); | 218 return Load("JSON", context_->v8_context()); |
224 } | 219 } |
225 | 220 |
226 v8::Local<v8::Object> SafeBuiltins::GetObjekt() const { | 221 v8::Local<v8::Object> SafeBuiltins::GetObjekt() const { |
227 return Load("Object", context_->v8_context()); | 222 return Load("Object", context_->v8_context()); |
228 } | 223 } |
229 | 224 |
230 v8::Local<v8::Object> SafeBuiltins::GetRegExp() const { | 225 v8::Local<v8::Object> SafeBuiltins::GetRegExp() const { |
231 return Load("RegExp", context_->v8_context()); | 226 return Load("RegExp", context_->v8_context()); |
232 } | 227 } |
233 | 228 |
234 v8::Local<v8::Object> SafeBuiltins::GetString() const { | 229 v8::Local<v8::Object> SafeBuiltins::GetString() const { |
235 return Load("String", context_->v8_context()); | 230 return Load("String", context_->v8_context()); |
236 } | 231 } |
237 | 232 |
238 } // namespace extensions | 233 } // namespace extensions |
OLD | NEW |