Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: webkit/plugins/ppapi/v8_var_converter.cc

Issue 16140011: Don't send PP_Vars/V8 values with cycles across PostMessage (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 "webkit/plugins/ppapi/v8_var_converter.h" 5 #include "webkit/plugins/ppapi/v8_var_converter.h"
6 6
7 #include <map> 7 #include <map>
8 #include <stack> 8 #include <stack>
9 #include <string> 9 #include <string>
10 10
11 #include "base/hash_tables.h" 11 #include "base/hash_tables.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "ppapi/shared_impl/array_var.h" 14 #include "ppapi/shared_impl/array_var.h"
15 #include "ppapi/shared_impl/dictionary_var.h" 15 #include "ppapi/shared_impl/dictionary_var.h"
16 #include "ppapi/shared_impl/var.h" 16 #include "ppapi/shared_impl/var.h"
17 #include "ppapi/shared_impl/var_tracker.h" 17 #include "ppapi/shared_impl/var_tracker.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h"
19 #include "webkit/plugins/ppapi/host_array_buffer_var.h" 19 #include "webkit/plugins/ppapi/host_array_buffer_var.h"
20 20
21 using ppapi::ArrayBufferVar; 21 using ppapi::ArrayBufferVar;
22 using ppapi::ArrayVar; 22 using ppapi::ArrayVar;
23 using ppapi::DictionaryVar; 23 using ppapi::DictionaryVar;
24 using ppapi::ScopedPPVar; 24 using ppapi::ScopedPPVar;
25 using ppapi::StringVar; 25 using ppapi::StringVar;
26 using std::make_pair; 26 using std::make_pair;
27 27
28 namespace { 28 namespace {
29 29
30 template <class T>
31 struct StackEntry {
32 StackEntry(T v) : val(v), sentinel(false) {}
33 T val;
34 // Used to track parent nodes on the stack as traversing the graph.
35 bool sentinel;
36 };
37
30 struct HashedHandle { 38 struct HashedHandle {
31 HashedHandle(v8::Handle<v8::Object> h) : handle(h) {} 39 HashedHandle(v8::Handle<v8::Object> h) : handle(h) {}
32 size_t hash() const { return handle->GetIdentityHash(); } 40 size_t hash() const { return handle->GetIdentityHash(); }
33 bool operator==(const HashedHandle& h) const { return handle == h.handle; } 41 bool operator==(const HashedHandle& h) const { return handle == h.handle; }
34 bool operator<(const HashedHandle& h) const { return hash() < h.hash(); } 42 bool operator<(const HashedHandle& h) const { return hash() < h.hash(); }
35 v8::Handle<v8::Object> handle; 43 v8::Handle<v8::Object> handle;
36 }; 44 };
37 45
38 } // namespace 46 } // namespace
39 47
(...skipping 12 matching lines...) Expand all
52 #endif 60 #endif
53 } // namespace BASE_HASH_NAMESPACE 61 } // namespace BASE_HASH_NAMESPACE
54 62
55 namespace webkit { 63 namespace webkit {
56 namespace ppapi { 64 namespace ppapi {
57 65
58 namespace { 66 namespace {
59 67
60 // Maps PP_Var IDs to the V8 value handle they correspond to. 68 // Maps PP_Var IDs to the V8 value handle they correspond to.
61 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; 69 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap;
70 typedef base::hash_set<int64_t> ParentVarSet;
62 71
63 // Maps V8 value handles to the PP_Var they correspond to. 72 // Maps V8 value handles to the PP_Var they correspond to.
64 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap; 73 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap;
74 typedef base::hash_set<HashedHandle> ParentHandleSet;
65 75
66 // Returns a V8 value which corresponds to a given PP_Var. If |var| is a 76 // Returns a V8 value which corresponds to a given PP_Var. If |var| is a
67 // reference counted PP_Var type, and it exists in |visited_ids|, the V8 value 77 // reference counted PP_Var type, and it exists in |visited_ids|, the V8 value
68 // associated with it in the map will be returned, otherwise a new V8 value will 78 // associated with it in the map will be returned, otherwise a new V8 value will
69 // be created and added to the map. |did_create| indicates whether a new v8 79 // be created and added to the map. |did_create| indicates whether a new v8
70 // value was created as a result of calling the function. 80 // value was created as a result of calling the function.
71 bool GetOrCreateV8Value(const PP_Var& var, 81 bool GetOrCreateV8Value(const PP_Var& var,
72 v8::Handle<v8::Value>* result, 82 v8::Handle<v8::Value>* result,
73 bool* did_create, 83 bool* did_create,
74 VarHandleMap* visited_ids) { 84 VarHandleMap* visited_ids,
85 ParentVarSet* parent_ids,
86 bool allow_cycles) {
75 *did_create = false; 87 *did_create = false;
76 88
77 if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { 89 if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
90 if (!allow_cycles && parent_ids->count(var.value.as_id) != 0)
91 return false;
78 VarHandleMap::iterator it = visited_ids->find(var.value.as_id); 92 VarHandleMap::iterator it = visited_ids->find(var.value.as_id);
79 if (it != visited_ids->end()) { 93 if (it != visited_ids->end()) {
80 *result = it->second; 94 *result = it->second;
81 return true; 95 return true;
82 } 96 }
83 } 97 }
84 98
85 switch (var.type) { 99 switch (var.type) {
86 case PP_VARTYPE_UNDEFINED: 100 case PP_VARTYPE_UNDEFINED:
87 *result = v8::Undefined(); 101 *result = v8::Undefined();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 158 }
145 159
146 // For a given V8 value handle, this returns a PP_Var which corresponds to it. 160 // For a given V8 value handle, this returns a PP_Var which corresponds to it.
147 // If the handle already exists in |visited_handles|, the PP_Var associated with 161 // If the handle already exists in |visited_handles|, the PP_Var associated with
148 // it will be returned, otherwise a new V8 value will be created and added to 162 // it will be returned, otherwise a new V8 value will be created and added to
149 // the map. |did_create| indicates if a new PP_Var was created as a result of 163 // the map. |did_create| indicates if a new PP_Var was created as a result of
150 // calling the function. 164 // calling the function.
151 bool GetOrCreateVar(v8::Handle<v8::Value> val, 165 bool GetOrCreateVar(v8::Handle<v8::Value> val,
152 PP_Var* result, 166 PP_Var* result,
153 bool* did_create, 167 bool* did_create,
154 HandleVarMap* visited_handles) { 168 HandleVarMap* visited_handles,
169 ParentHandleSet* parent_handles,
170 bool allow_cycles) {
155 CHECK(!val.IsEmpty()); 171 CHECK(!val.IsEmpty());
156 *did_create = false; 172 *did_create = false;
157 173
158 // Even though every v8 string primitive encountered will be a unique object, 174 // Even though every v8 string primitive encountered will be a unique object,
159 // we still add them to |visited_handles| so that the corresponding string 175 // we still add them to |visited_handles| so that the corresponding string
160 // PP_Var created will be properly refcounted. 176 // PP_Var created will be properly refcounted.
161 if (val->IsObject() || val->IsString()) { 177 if (val->IsObject() || val->IsString()) {
178 if (!allow_cycles &&
179 parent_handles->count(HashedHandle(val->ToObject())) != 0) {
180 return false;
181 }
182
162 HandleVarMap::const_iterator it = visited_handles->find( 183 HandleVarMap::const_iterator it = visited_handles->find(
163 HashedHandle(val->ToObject())); 184 HashedHandle(val->ToObject()));
164 if (it != visited_handles->end()) { 185 if (it != visited_handles->end()) {
165 *result = it->second.get(); 186 *result = it->second.get();
166 return true; 187 return true;
167 } 188 }
168 } 189 }
169 190
170 if (val->IsUndefined()) { 191 if (val->IsUndefined()) {
171 *result = PP_MakeUndefined(); 192 *result = PP_MakeUndefined();
(...skipping 14 matching lines...) Expand all
186 scoped_ptr<WebKit::WebArrayBuffer> web_array_buffer( 207 scoped_ptr<WebKit::WebArrayBuffer> web_array_buffer(
187 WebKit::WebArrayBuffer::createFromV8Value(val)); 208 WebKit::WebArrayBuffer::createFromV8Value(val));
188 if (web_array_buffer.get()) { 209 if (web_array_buffer.get()) {
189 scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar( 210 scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar(
190 *web_array_buffer)); 211 *web_array_buffer));
191 *result = buffer_var->GetPPVar(); 212 *result = buffer_var->GetPPVar();
192 } else { 213 } else {
193 *result = (new DictionaryVar())->GetPPVar(); 214 *result = (new DictionaryVar())->GetPPVar();
194 } 215 }
195 } else { 216 } else {
196 NOTREACHED(); 217 // Silently ignore the case where we can't convert to a Var as we may
197 return false; 218 // be trying to convert a type that doesn't have a corresponding
219 // PP_Var type.
220 return true;
198 } 221 }
199 222
200 *did_create = true; 223 *did_create = true;
201 if (val->IsObject() || val->IsString()) { 224 if (val->IsObject() || val->IsString()) {
202 visited_handles->insert(make_pair( 225 visited_handles->insert(make_pair(
203 HashedHandle(val->ToObject()), 226 HashedHandle(val->ToObject()),
204 ScopedPPVar(ScopedPPVar::PassRef(), *result))); 227 ScopedPPVar(ScopedPPVar::PassRef(), *result)));
205 } 228 }
206 return true; 229 return true;
207 } 230 }
208 231
209 } // namespace 232 } // namespace
210 233
211 V8VarConverter::V8VarConverter() { 234 V8VarConverter::V8VarConverter(bool allow_cycles)
235 : allow_cycles_(allow_cycles) {
212 } 236 }
213 237
214 bool V8VarConverter::ToV8Value(const PP_Var& var, 238 bool V8VarConverter::ToV8Value(const PP_Var& var,
215 v8::Handle<v8::Context> context, 239 v8::Handle<v8::Context> context,
216 v8::Handle<v8::Value>* result) const { 240 v8::Handle<v8::Value>* result) const {
217 v8::Context::Scope context_scope(context); 241 v8::Context::Scope context_scope(context);
218 v8::HandleScope handle_scope; 242 v8::HandleScope handle_scope;
219 243
220 VarHandleMap visited_ids; 244 VarHandleMap visited_ids;
245 ParentVarSet parent_ids;
221 246
222 std::stack<PP_Var> stack; 247 std::stack<StackEntry<PP_Var> > stack;
223 stack.push(var); 248 stack.push(StackEntry<PP_Var>(var));
224 v8::Handle<v8::Value> root; 249 v8::Handle<v8::Value> root;
225 bool is_root = true; 250 bool is_root = true;
226 251
227 while (!stack.empty()) { 252 while (!stack.empty()) {
228 const PP_Var& current_var = stack.top(); 253 const PP_Var& current_var = stack.top().val;
229 v8::Handle<v8::Value> current_v8; 254 v8::Handle<v8::Value> current_v8;
230 stack.pop(); 255
256 if (stack.top().sentinel) {
257 stack.pop();
258 if (::ppapi::VarTracker::IsVarTypeRefcounted(current_var.type))
259 parent_ids.erase(current_var.value.as_id);
260 continue;
261 } else {
262 stack.top().sentinel = true;
263 }
264
231 bool did_create = false; 265 bool did_create = false;
232 if (!GetOrCreateV8Value(current_var, &current_v8, &did_create, 266 if (!GetOrCreateV8Value(current_var, &current_v8, &did_create,
233 &visited_ids)) { 267 &visited_ids, &parent_ids, allow_cycles_)) {
234 return false; 268 return false;
235 } 269 }
236 270
237 if (is_root) { 271 if (is_root) {
238 is_root = false; 272 is_root = false;
239 root = current_v8; 273 root = current_v8;
240 } 274 }
241 275
242 // Add child nodes to the stack. 276 // Add child nodes to the stack.
243 if (current_var.type == PP_VARTYPE_ARRAY) { 277 if (current_var.type == PP_VARTYPE_ARRAY) {
278 parent_ids.insert(current_var.value.as_id);
244 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); 279 ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
245 if (!array_var) { 280 if (!array_var) {
246 NOTREACHED(); 281 NOTREACHED();
247 return false; 282 return false;
248 } 283 }
249 DCHECK(current_v8->IsArray()); 284 DCHECK(current_v8->IsArray());
250 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); 285 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>();
251 286
252 for (size_t i = 0; i < array_var->elements().size(); ++i) { 287 for (size_t i = 0; i < array_var->elements().size(); ++i) {
253 const PP_Var& child_var = array_var->elements()[i].get(); 288 const PP_Var& child_var = array_var->elements()[i].get();
254 v8::Handle<v8::Value> child_v8; 289 v8::Handle<v8::Value> child_v8;
255 if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, 290 if (!GetOrCreateV8Value(child_var, &child_v8, &did_create,
256 &visited_ids)) { 291 &visited_ids, &parent_ids, allow_cycles_)) {
257 return false; 292 return false;
258 } 293 }
259 if (did_create && 294 if (did_create &&
260 (child_var.type == PP_VARTYPE_DICTIONARY || 295 (child_var.type == PP_VARTYPE_DICTIONARY ||
261 child_var.type == PP_VARTYPE_ARRAY)) { 296 child_var.type == PP_VARTYPE_ARRAY)) {
262 stack.push(child_var); 297 stack.push(child_var);
263 } 298 }
264 v8::TryCatch try_catch; 299 v8::TryCatch try_catch;
265 v8_array->Set(static_cast<uint32>(i), child_v8); 300 v8_array->Set(static_cast<uint32>(i), child_v8);
266 if (try_catch.HasCaught()) { 301 if (try_catch.HasCaught()) {
267 LOG(ERROR) << "Setter for index " << i << " threw an exception."; 302 LOG(ERROR) << "Setter for index " << i << " threw an exception.";
268 return false; 303 return false;
269 } 304 }
270 } 305 }
271 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { 306 } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
307 parent_ids.insert(current_var.value.as_id);
272 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); 308 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
273 if (!dict_var) { 309 if (!dict_var) {
274 NOTREACHED(); 310 NOTREACHED();
275 return false; 311 return false;
276 } 312 }
277 DCHECK(current_v8->IsObject()); 313 DCHECK(current_v8->IsObject());
278 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); 314 v8::Handle<v8::Object> v8_object = current_v8->ToObject();
279 315
280 for (DictionaryVar::KeyValueMap::const_iterator iter = 316 for (DictionaryVar::KeyValueMap::const_iterator iter =
281 dict_var->key_value_map().begin(); 317 dict_var->key_value_map().begin();
282 iter != dict_var->key_value_map().end(); 318 iter != dict_var->key_value_map().end();
283 ++iter) { 319 ++iter) {
284 const std::string& key = iter->first; 320 const std::string& key = iter->first;
285 const PP_Var& child_var = iter->second.get(); 321 const PP_Var& child_var = iter->second.get();
286 v8::Handle<v8::Value> child_v8; 322 v8::Handle<v8::Value> child_v8;
287 if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, 323 if (!GetOrCreateV8Value(child_var, &child_v8, &did_create,
288 &visited_ids)) { 324 &visited_ids, &parent_ids, allow_cycles_)) {
289 return false; 325 return false;
290 } 326 }
291 if (did_create && 327 if (did_create &&
292 (child_var.type == PP_VARTYPE_DICTIONARY || 328 (child_var.type == PP_VARTYPE_DICTIONARY ||
293 child_var.type == PP_VARTYPE_ARRAY)) { 329 child_var.type == PP_VARTYPE_ARRAY)) {
294 stack.push(child_var); 330 stack.push(child_var);
295 } 331 }
296 v8::TryCatch try_catch; 332 v8::TryCatch try_catch;
297 v8_object->Set(v8::String::New(key.c_str(), key.length()), child_v8); 333 v8_object->Set(v8::String::New(key.c_str(), key.length()), child_v8);
298 if (try_catch.HasCaught()) { 334 if (try_catch.HasCaught()) {
299 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " 335 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
300 << "exception."; 336 << "exception.";
301 return false; 337 return false;
302 } 338 }
303 } 339 }
304 } 340 }
305 } 341 }
306 342
307 *result = handle_scope.Close(root); 343 *result = handle_scope.Close(root);
308 return true; 344 return true;
309 } 345 }
310 346
311 bool V8VarConverter::FromV8Value(v8::Handle<v8::Value> val, 347 bool V8VarConverter::FromV8Value(v8::Handle<v8::Value> val,
312 v8::Handle<v8::Context> context, 348 v8::Handle<v8::Context> context,
313 PP_Var* result) const { 349 PP_Var* result) const {
314 v8::Context::Scope context_scope(context); 350 v8::Context::Scope context_scope(context);
315 v8::HandleScope handle_scope; 351 v8::HandleScope handle_scope;
316 352
317 HandleVarMap visited_handles; 353 HandleVarMap visited_handles;
354 ParentHandleSet parent_handles;
318 355
319 std::stack<v8::Handle<v8::Value> > stack; 356 std::stack<StackEntry<v8::Handle<v8::Value> > > stack;
320 stack.push(val); 357 stack.push(StackEntry<v8::Handle<v8::Value> >(val));
321 ScopedPPVar root; 358 ScopedPPVar root;
322 bool is_root = true; 359 bool is_root = true;
323 360
324 while (!stack.empty()) { 361 while (!stack.empty()) {
325 v8::Handle<v8::Value> current_v8 = stack.top(); 362 v8::Handle<v8::Value> current_v8 = stack.top().val;
326 PP_Var current_var; 363 PP_Var current_var;
327 stack.pop(); 364
365 if (stack.top().sentinel) {
366 stack.pop();
367 if (current_v8->IsObject())
368 parent_handles.erase(HashedHandle(current_v8->ToObject()));
369 continue;
370 } else {
371 stack.top().sentinel = true;
372 }
373
328 bool did_create = false; 374 bool did_create = false;
329 if (!GetOrCreateVar(current_v8, &current_var, &did_create, 375 if (!GetOrCreateVar(current_v8, &current_var, &did_create,
330 &visited_handles)) { 376 &visited_handles, &parent_handles, allow_cycles_)) {
331 return false; 377 return false;
332 } 378 }
333 379
334 if (is_root) { 380 if (is_root) {
335 is_root = false; 381 is_root = false;
336 root = current_var; 382 root = current_var;
337 } 383 }
338 384
339 // Add child nodes to the stack. 385 // Add child nodes to the stack.
340 if (current_var.type == PP_VARTYPE_ARRAY) { 386 if (current_var.type == PP_VARTYPE_ARRAY) {
341 DCHECK(current_v8->IsArray()); 387 DCHECK(current_v8->IsArray());
342 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); 388 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>();
389 parent_handles.insert(HashedHandle(v8_array));
343 390
344 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); 391 ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
345 if (!array_var) { 392 if (!array_var) {
346 NOTREACHED(); 393 NOTREACHED();
347 return false; 394 return false;
348 } 395 }
349 396
350 for (uint32 i = 0; i < v8_array->Length(); ++i) { 397 for (uint32 i = 0; i < v8_array->Length(); ++i) {
351 v8::TryCatch try_catch; 398 v8::TryCatch try_catch;
352 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); 399 v8::Handle<v8::Value> child_v8 = v8_array->Get(i);
353 if (try_catch.HasCaught()) 400 if (try_catch.HasCaught())
354 return false; 401 return false;
355 402
356 if (!v8_array->HasRealIndexedProperty(i)) 403 if (!v8_array->HasRealIndexedProperty(i))
357 continue; 404 continue;
358 405
359 PP_Var child_var; 406 PP_Var child_var;
360 if (!GetOrCreateVar(child_v8, &child_var, &did_create, 407 if (!GetOrCreateVar(child_v8, &child_var, &did_create,
361 &visited_handles)) { 408 &visited_handles, &parent_handles, allow_cycles_)) {
362 // Silently ignore the case where we can't convert to a Var as we may 409 return false;
363 // be trying to convert a type that doesn't have a corresponding
364 // PP_Var type.
365 continue;
366 } 410 }
367 if (did_create && child_v8->IsObject()) 411 if (did_create && child_v8->IsObject())
368 stack.push(child_v8); 412 stack.push(child_v8);
369 413
370 array_var->Set(i, child_var); 414 array_var->Set(i, child_var);
371 } 415 }
372 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { 416 } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
373 DCHECK(current_v8->IsObject()); 417 DCHECK(current_v8->IsObject());
374 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); 418 v8::Handle<v8::Object> v8_object = current_v8->ToObject();
419 parent_handles.insert(HashedHandle(v8_object));
375 420
376 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); 421 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
377 if (!dict_var) { 422 if (!dict_var) {
378 NOTREACHED(); 423 NOTREACHED();
379 return false; 424 return false;
380 } 425 }
381 426
382 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); 427 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames());
383 for (uint32 i = 0; i < property_names->Length(); ++i) { 428 for (uint32 i = 0; i < property_names->Length(); ++i) {
384 v8::Handle<v8::Value> key(property_names->Get(i)); 429 v8::Handle<v8::Value> key(property_names->Get(i));
(...skipping 11 matching lines...) Expand all
396 441
397 v8::String::Utf8Value name_utf8(key->ToString()); 442 v8::String::Utf8Value name_utf8(key->ToString());
398 443
399 v8::TryCatch try_catch; 444 v8::TryCatch try_catch;
400 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); 445 v8::Handle<v8::Value> child_v8 = v8_object->Get(key);
401 if (try_catch.HasCaught()) 446 if (try_catch.HasCaught())
402 return false; 447 return false;
403 448
404 PP_Var child_var; 449 PP_Var child_var;
405 if (!GetOrCreateVar(child_v8, &child_var, &did_create, 450 if (!GetOrCreateVar(child_v8, &child_var, &did_create,
406 &visited_handles)) { 451 &visited_handles, &parent_handles, allow_cycles_)) {
407 continue; 452 return false;
408 } 453 }
409 if (did_create && child_v8->IsObject()) 454 if (did_create && child_v8->IsObject())
410 stack.push(child_v8); 455 stack.push(child_v8);
411 456
412 bool success = dict_var->SetWithStringKey( 457 bool success = dict_var->SetWithStringKey(
413 std::string(*name_utf8, name_utf8.length()), child_var); 458 std::string(*name_utf8, name_utf8.length()), child_var);
414 DCHECK(success); 459 DCHECK(success);
415 } 460 }
416 } 461 }
417 } 462 }
418 *result = root.Release(); 463 *result = root.Release();
419 return true; 464 return true;
420 } 465 }
421 466
422 } // namespace ppapi 467 } // namespace ppapi
423 } // namespace webkit 468 } // namespace webkit
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698