OLD | NEW |
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 "content/renderer/pepper/v8_var_converter.h" | 5 #include "content/renderer/pepper/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 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 bool operator<(const HashedHandle& h) const { return hash() < h.hash(); } | 47 bool operator<(const HashedHandle& h) const { return hash() < h.hash(); } |
48 v8::Handle<v8::Object> handle; | 48 v8::Handle<v8::Object> handle; |
49 }; | 49 }; |
50 | 50 |
51 } // namespace | 51 } // namespace |
52 | 52 |
53 namespace BASE_HASH_NAMESPACE { | 53 namespace BASE_HASH_NAMESPACE { |
54 #if defined(COMPILER_GCC) | 54 #if defined(COMPILER_GCC) |
55 template <> | 55 template <> |
56 struct hash<HashedHandle> { | 56 struct hash<HashedHandle> { |
57 size_t operator()(const HashedHandle& handle) const { | 57 size_t operator()(const HashedHandle& handle) const { return handle.hash(); } |
58 return handle.hash(); | |
59 } | |
60 }; | 58 }; |
61 #elif defined(COMPILER_MSVC) | 59 #elif defined(COMPILER_MSVC) |
62 inline size_t hash_value(const HashedHandle& handle) { | 60 inline size_t hash_value(const HashedHandle& handle) { return handle.hash(); } |
63 return handle.hash(); | |
64 } | |
65 #endif | 61 #endif |
66 } // namespace BASE_HASH_NAMESPACE | 62 } // namespace BASE_HASH_NAMESPACE |
67 | 63 |
68 namespace content { | 64 namespace content { |
69 | 65 |
70 namespace { | 66 namespace { |
71 | 67 |
72 // 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. |
73 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; | 69 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; |
74 typedef base::hash_set<int64_t> ParentVarSet; | 70 typedef base::hash_set<int64_t> ParentVarSet; |
(...skipping 28 matching lines...) Expand all Loading... |
103 } | 99 } |
104 | 100 |
105 switch (var.type) { | 101 switch (var.type) { |
106 case PP_VARTYPE_UNDEFINED: | 102 case PP_VARTYPE_UNDEFINED: |
107 *result = v8::Undefined(isolate); | 103 *result = v8::Undefined(isolate); |
108 break; | 104 break; |
109 case PP_VARTYPE_NULL: | 105 case PP_VARTYPE_NULL: |
110 *result = v8::Null(isolate); | 106 *result = v8::Null(isolate); |
111 break; | 107 break; |
112 case PP_VARTYPE_BOOL: | 108 case PP_VARTYPE_BOOL: |
113 *result = (var.value.as_bool == PP_TRUE) | 109 *result = (var.value.as_bool == PP_TRUE) ? v8::True(isolate) |
114 ? v8::True(isolate) | 110 : v8::False(isolate); |
115 : v8::False(isolate); | |
116 break; | 111 break; |
117 case PP_VARTYPE_INT32: | 112 case PP_VARTYPE_INT32: |
118 *result = v8::Integer::New(isolate, var.value.as_int); | 113 *result = v8::Integer::New(isolate, var.value.as_int); |
119 break; | 114 break; |
120 case PP_VARTYPE_DOUBLE: | 115 case PP_VARTYPE_DOUBLE: |
121 *result = v8::Number::New(isolate, var.value.as_double); | 116 *result = v8::Number::New(isolate, var.value.as_double); |
122 break; | 117 break; |
123 case PP_VARTYPE_STRING: { | 118 case PP_VARTYPE_STRING: { |
124 StringVar* string = StringVar::FromPPVar(var); | 119 StringVar* string = StringVar::FromPPVar(var); |
125 if (!string) { | 120 if (!string) { |
126 NOTREACHED(); | 121 NOTREACHED(); |
127 result->Clear(); | 122 result->Clear(); |
128 return false; | 123 return false; |
129 } | 124 } |
130 const std::string& value = string->value(); | 125 const std::string& value = string->value(); |
131 // Create a string primitive rather than a string object. This is lossy | 126 // Create a string primitive rather than a string object. This is lossy |
132 // in the sense that string primitives in JavaScript can't be referenced | 127 // in the sense that string primitives in JavaScript can't be referenced |
133 // in the same way that string vars can in pepper. But that information | 128 // in the same way that string vars can in pepper. But that information |
134 // isn't very useful and primitive strings are a more expected form in JS. | 129 // isn't very useful and primitive strings are a more expected form in JS. |
135 *result = v8::String::NewFromUtf8(isolate, | 130 *result = v8::String::NewFromUtf8( |
136 value.c_str(), | 131 isolate, value.c_str(), v8::String::kNormalString, value.size()); |
137 v8::String::kNormalString, | |
138 value.size()); | |
139 break; | 132 break; |
140 } | 133 } |
141 case PP_VARTYPE_ARRAY_BUFFER: { | 134 case PP_VARTYPE_ARRAY_BUFFER: { |
142 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); | 135 ArrayBufferVar* buffer = ArrayBufferVar::FromPPVar(var); |
143 if (!buffer) { | 136 if (!buffer) { |
144 NOTREACHED(); | 137 NOTREACHED(); |
145 result->Clear(); | 138 result->Clear(); |
146 return false; | 139 return false; |
147 } | 140 } |
148 HostArrayBufferVar* host_buffer = | 141 HostArrayBufferVar* host_buffer = |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 CHECK(!val.IsEmpty()); | 182 CHECK(!val.IsEmpty()); |
190 *did_create = false; | 183 *did_create = false; |
191 | 184 |
192 // Even though every v8 string primitive encountered will be a unique object, | 185 // Even though every v8 string primitive encountered will be a unique object, |
193 // we still add them to |visited_handles| so that the corresponding string | 186 // we still add them to |visited_handles| so that the corresponding string |
194 // PP_Var created will be properly refcounted. | 187 // PP_Var created will be properly refcounted. |
195 if (val->IsObject() || val->IsString()) { | 188 if (val->IsObject() || val->IsString()) { |
196 if (parent_handles->count(HashedHandle(val->ToObject())) != 0) | 189 if (parent_handles->count(HashedHandle(val->ToObject())) != 0) |
197 return false; | 190 return false; |
198 | 191 |
199 HandleVarMap::const_iterator it = visited_handles->find( | 192 HandleVarMap::const_iterator it = |
200 HashedHandle(val->ToObject())); | 193 visited_handles->find(HashedHandle(val->ToObject())); |
201 if (it != visited_handles->end()) { | 194 if (it != visited_handles->end()) { |
202 *result = it->second.get(); | 195 *result = it->second.get(); |
203 return true; | 196 return true; |
204 } | 197 } |
205 } | 198 } |
206 | 199 |
207 if (val->IsUndefined()) { | 200 if (val->IsUndefined()) { |
208 *result = PP_MakeUndefined(); | 201 *result = PP_MakeUndefined(); |
209 } else if (val->IsNull()) { | 202 } else if (val->IsNull()) { |
210 *result = PP_MakeNull(); | 203 *result = PP_MakeNull(); |
211 } else if (val->IsBoolean() || val->IsBooleanObject()) { | 204 } else if (val->IsBoolean() || val->IsBooleanObject()) { |
212 *result = PP_MakeBool(PP_FromBool(val->ToBoolean()->Value())); | 205 *result = PP_MakeBool(PP_FromBool(val->ToBoolean()->Value())); |
213 } else if (val->IsInt32()) { | 206 } else if (val->IsInt32()) { |
214 *result = PP_MakeInt32(val->ToInt32()->Value()); | 207 *result = PP_MakeInt32(val->ToInt32()->Value()); |
215 } else if (val->IsNumber() || val->IsNumberObject()) { | 208 } else if (val->IsNumber() || val->IsNumberObject()) { |
216 *result = PP_MakeDouble(val->ToNumber()->Value()); | 209 *result = PP_MakeDouble(val->ToNumber()->Value()); |
217 } else if (val->IsString() || val->IsStringObject()) { | 210 } else if (val->IsString() || val->IsStringObject()) { |
218 v8::String::Utf8Value utf8(val->ToString()); | 211 v8::String::Utf8Value utf8(val->ToString()); |
219 *result = StringVar::StringToPPVar(std::string(*utf8, utf8.length())); | 212 *result = StringVar::StringToPPVar(std::string(*utf8, utf8.length())); |
220 } else if (val->IsArray()) { | 213 } else if (val->IsArray()) { |
221 *result = (new ArrayVar())->GetPPVar(); | 214 *result = (new ArrayVar())->GetPPVar(); |
222 } else if (val->IsObject()) { | 215 } else if (val->IsObject()) { |
223 scoped_ptr<blink::WebArrayBuffer> web_array_buffer( | 216 scoped_ptr<blink::WebArrayBuffer> web_array_buffer( |
224 blink::WebArrayBufferConverter::createFromV8Value(val)); | 217 blink::WebArrayBufferConverter::createFromV8Value(val)); |
225 if (web_array_buffer.get()) { | 218 if (web_array_buffer.get()) { |
226 scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar( | 219 scoped_refptr<HostArrayBufferVar> buffer_var( |
227 *web_array_buffer)); | 220 new HostArrayBufferVar(*web_array_buffer)); |
228 *result = buffer_var->GetPPVar(); | 221 *result = buffer_var->GetPPVar(); |
229 } else { | 222 } else { |
230 bool was_resource; | 223 bool was_resource; |
231 if (!resource_converter->FromV8Value(val->ToObject(), context, result, | 224 if (!resource_converter->FromV8Value( |
232 &was_resource)) | 225 val->ToObject(), context, result, &was_resource)) |
233 return false; | 226 return false; |
234 if (!was_resource) { | 227 if (!was_resource) { |
235 *result = (new DictionaryVar())->GetPPVar(); | 228 *result = (new DictionaryVar())->GetPPVar(); |
236 } | 229 } |
237 } | 230 } |
238 } else { | 231 } else { |
239 // Silently ignore the case where we can't convert to a Var as we may | 232 // Silently ignore the case where we can't convert to a Var as we may |
240 // be trying to convert a type that doesn't have a corresponding | 233 // be trying to convert a type that doesn't have a corresponding |
241 // PP_Var type. | 234 // PP_Var type. |
242 return true; | 235 return true; |
243 } | 236 } |
244 | 237 |
245 *did_create = true; | 238 *did_create = true; |
246 if (val->IsObject() || val->IsString()) { | 239 if (val->IsObject() || val->IsString()) { |
247 visited_handles->insert(make_pair( | 240 visited_handles->insert( |
248 HashedHandle(val->ToObject()), | 241 make_pair(HashedHandle(val->ToObject()), |
249 ScopedPPVar(ScopedPPVar::PassRef(), *result))); | 242 ScopedPPVar(ScopedPPVar::PassRef(), *result))); |
250 } | 243 } |
251 return true; | 244 return true; |
252 } | 245 } |
253 | 246 |
254 bool CanHaveChildren(PP_Var var) { | 247 bool CanHaveChildren(PP_Var var) { |
255 return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY; | 248 return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY; |
256 } | 249 } |
257 | 250 |
258 } // namespace | 251 } // namespace |
259 | 252 |
260 V8VarConverter::V8VarConverter(PP_Instance instance) | 253 V8VarConverter::V8VarConverter(PP_Instance instance) |
261 : message_loop_proxy_(base::MessageLoopProxy::current()) { | 254 : message_loop_proxy_(base::MessageLoopProxy::current()) { |
262 resource_converter_.reset(new ResourceConverterImpl( | 255 resource_converter_.reset(new ResourceConverterImpl( |
263 instance, RendererPpapiHost::GetForPPInstance(instance))); | 256 instance, RendererPpapiHost::GetForPPInstance(instance))); |
264 } | 257 } |
265 | 258 |
266 V8VarConverter::V8VarConverter( | 259 V8VarConverter::V8VarConverter(PP_Instance instance, |
267 PP_Instance instance, | 260 scoped_ptr<ResourceConverter> resource_converter) |
268 scoped_ptr<ResourceConverter> resource_converter) | |
269 : message_loop_proxy_(base::MessageLoopProxy::current()), | 261 : message_loop_proxy_(base::MessageLoopProxy::current()), |
270 resource_converter_(resource_converter.release()) { | 262 resource_converter_(resource_converter.release()) {} |
271 } | |
272 | 263 |
273 V8VarConverter::~V8VarConverter() { | 264 V8VarConverter::~V8VarConverter() {} |
274 } | |
275 | 265 |
276 // To/FromV8Value use a stack-based DFS search to traverse V8/Var graph. Each | 266 // To/FromV8Value use a stack-based DFS search to traverse V8/Var graph. Each |
277 // iteration, the top node on the stack examined. If the node has not been | 267 // iteration, the top node on the stack examined. If the node has not been |
278 // visited yet (i.e. sentinel == false) then it is added to the list of parents | 268 // visited yet (i.e. sentinel == false) then it is added to the list of parents |
279 // which contains all of the nodes on the path from the start node to the | 269 // which contains all of the nodes on the path from the start node to the |
280 // current node. Each of the current nodes children are examined. If they appear | 270 // current node. Each of the current nodes children are examined. If they appear |
281 // in the list of parents it means we have a cycle and we return NULL. | 271 // in the list of parents it means we have a cycle and we return NULL. |
282 // Otherwise, if they can have children, we add them to the stack. If the | 272 // Otherwise, if they can have children, we add them to the stack. If the |
283 // node at the top of the stack has already been visited, then we pop it off the | 273 // node at the top of the stack has already been visited, then we pop it off the |
284 // stack and erase it from the list of parents. | 274 // stack and erase it from the list of parents. |
(...skipping 20 matching lines...) Expand all Loading... |
305 if (stack.top().sentinel) { | 295 if (stack.top().sentinel) { |
306 stack.pop(); | 296 stack.pop(); |
307 if (CanHaveChildren(current_var)) | 297 if (CanHaveChildren(current_var)) |
308 parent_ids.erase(current_var.value.as_id); | 298 parent_ids.erase(current_var.value.as_id); |
309 continue; | 299 continue; |
310 } else { | 300 } else { |
311 stack.top().sentinel = true; | 301 stack.top().sentinel = true; |
312 } | 302 } |
313 | 303 |
314 bool did_create = false; | 304 bool did_create = false; |
315 if (!GetOrCreateV8Value(context, current_var, ¤t_v8, &did_create, | 305 if (!GetOrCreateV8Value(context, |
316 &visited_ids, &parent_ids, | 306 current_var, |
| 307 ¤t_v8, |
| 308 &did_create, |
| 309 &visited_ids, |
| 310 &parent_ids, |
317 resource_converter_.get())) { | 311 resource_converter_.get())) { |
318 return false; | 312 return false; |
319 } | 313 } |
320 | 314 |
321 if (is_root) { | 315 if (is_root) { |
322 is_root = false; | 316 is_root = false; |
323 root = current_v8; | 317 root = current_v8; |
324 } | 318 } |
325 | 319 |
326 // Add child nodes to the stack. | 320 // Add child nodes to the stack. |
327 if (current_var.type == PP_VARTYPE_ARRAY) { | 321 if (current_var.type == PP_VARTYPE_ARRAY) { |
328 parent_ids.insert(current_var.value.as_id); | 322 parent_ids.insert(current_var.value.as_id); |
329 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 323 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
330 if (!array_var) { | 324 if (!array_var) { |
331 NOTREACHED(); | 325 NOTREACHED(); |
332 return false; | 326 return false; |
333 } | 327 } |
334 DCHECK(current_v8->IsArray()); | 328 DCHECK(current_v8->IsArray()); |
335 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); | 329 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); |
336 | 330 |
337 for (size_t i = 0; i < array_var->elements().size(); ++i) { | 331 for (size_t i = 0; i < array_var->elements().size(); ++i) { |
338 const PP_Var& child_var = array_var->elements()[i].get(); | 332 const PP_Var& child_var = array_var->elements()[i].get(); |
339 v8::Handle<v8::Value> child_v8; | 333 v8::Handle<v8::Value> child_v8; |
340 if (!GetOrCreateV8Value(context, child_var, &child_v8, &did_create, | 334 if (!GetOrCreateV8Value(context, |
341 &visited_ids, &parent_ids, | 335 child_var, |
| 336 &child_v8, |
| 337 &did_create, |
| 338 &visited_ids, |
| 339 &parent_ids, |
342 resource_converter_.get())) { | 340 resource_converter_.get())) { |
343 return false; | 341 return false; |
344 } | 342 } |
345 if (did_create && CanHaveChildren(child_var)) | 343 if (did_create && CanHaveChildren(child_var)) |
346 stack.push(child_var); | 344 stack.push(child_var); |
347 v8::TryCatch try_catch; | 345 v8::TryCatch try_catch; |
348 v8_array->Set(static_cast<uint32>(i), child_v8); | 346 v8_array->Set(static_cast<uint32>(i), child_v8); |
349 if (try_catch.HasCaught()) { | 347 if (try_catch.HasCaught()) { |
350 LOG(ERROR) << "Setter for index " << i << " threw an exception."; | 348 LOG(ERROR) << "Setter for index " << i << " threw an exception."; |
351 return false; | 349 return false; |
352 } | 350 } |
353 } | 351 } |
354 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 352 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
355 parent_ids.insert(current_var.value.as_id); | 353 parent_ids.insert(current_var.value.as_id); |
356 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 354 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
357 if (!dict_var) { | 355 if (!dict_var) { |
358 NOTREACHED(); | 356 NOTREACHED(); |
359 return false; | 357 return false; |
360 } | 358 } |
361 DCHECK(current_v8->IsObject()); | 359 DCHECK(current_v8->IsObject()); |
362 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); | 360 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); |
363 | 361 |
364 for (DictionaryVar::KeyValueMap::const_iterator iter = | 362 for (DictionaryVar::KeyValueMap::const_iterator iter = |
365 dict_var->key_value_map().begin(); | 363 dict_var->key_value_map().begin(); |
366 iter != dict_var->key_value_map().end(); | 364 iter != dict_var->key_value_map().end(); |
367 ++iter) { | 365 ++iter) { |
368 const std::string& key = iter->first; | 366 const std::string& key = iter->first; |
369 const PP_Var& child_var = iter->second.get(); | 367 const PP_Var& child_var = iter->second.get(); |
370 v8::Handle<v8::Value> child_v8; | 368 v8::Handle<v8::Value> child_v8; |
371 if (!GetOrCreateV8Value(context, child_var, &child_v8, &did_create, | 369 if (!GetOrCreateV8Value(context, |
372 &visited_ids, &parent_ids, | 370 child_var, |
| 371 &child_v8, |
| 372 &did_create, |
| 373 &visited_ids, |
| 374 &parent_ids, |
373 resource_converter_.get())) { | 375 resource_converter_.get())) { |
374 return false; | 376 return false; |
375 } | 377 } |
376 if (did_create && CanHaveChildren(child_var)) | 378 if (did_create && CanHaveChildren(child_var)) |
377 stack.push(child_var); | 379 stack.push(child_var); |
378 v8::TryCatch try_catch; | 380 v8::TryCatch try_catch; |
379 v8_object->Set(v8::String::NewFromUtf8(isolate, | 381 v8_object->Set( |
380 key.c_str(), | 382 v8::String::NewFromUtf8( |
381 v8::String::kNormalString, | 383 isolate, key.c_str(), v8::String::kNormalString, key.length()), |
382 key.length()), | 384 child_v8); |
383 child_v8); | |
384 if (try_catch.HasCaught()) { | 385 if (try_catch.HasCaught()) { |
385 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " | 386 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " |
386 << "exception."; | 387 << "exception."; |
387 return false; | 388 return false; |
388 } | 389 } |
389 } | 390 } |
390 } | 391 } |
391 } | 392 } |
392 | 393 |
393 *result = handle_scope.Escape(root); | 394 *result = handle_scope.Escape(root); |
394 return true; | 395 return true; |
395 } | 396 } |
396 | 397 |
(...skipping 19 matching lines...) Expand all Loading... |
416 if (stack.top().sentinel) { | 417 if (stack.top().sentinel) { |
417 stack.pop(); | 418 stack.pop(); |
418 if (current_v8->IsObject()) | 419 if (current_v8->IsObject()) |
419 parent_handles.erase(HashedHandle(current_v8->ToObject())); | 420 parent_handles.erase(HashedHandle(current_v8->ToObject())); |
420 continue; | 421 continue; |
421 } else { | 422 } else { |
422 stack.top().sentinel = true; | 423 stack.top().sentinel = true; |
423 } | 424 } |
424 | 425 |
425 bool did_create = false; | 426 bool did_create = false; |
426 if (!GetOrCreateVar(current_v8, context, ¤t_var, &did_create, | 427 if (!GetOrCreateVar(current_v8, |
427 &visited_handles, &parent_handles, | 428 context, |
| 429 ¤t_var, |
| 430 &did_create, |
| 431 &visited_handles, |
| 432 &parent_handles, |
428 resource_converter_.get())) { | 433 resource_converter_.get())) { |
429 message_loop_proxy_->PostTask(FROM_HERE, | 434 message_loop_proxy_->PostTask( |
| 435 FROM_HERE, |
430 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 436 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
431 return; | 437 return; |
432 } | 438 } |
433 | 439 |
434 if (is_root) { | 440 if (is_root) { |
435 is_root = false; | 441 is_root = false; |
436 root = current_var; | 442 root = current_var; |
437 } | 443 } |
438 | 444 |
439 // Add child nodes to the stack. | 445 // Add child nodes to the stack. |
440 if (current_var.type == PP_VARTYPE_ARRAY) { | 446 if (current_var.type == PP_VARTYPE_ARRAY) { |
441 DCHECK(current_v8->IsArray()); | 447 DCHECK(current_v8->IsArray()); |
442 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); | 448 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); |
443 parent_handles.insert(HashedHandle(v8_array)); | 449 parent_handles.insert(HashedHandle(v8_array)); |
444 | 450 |
445 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 451 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
446 if (!array_var) { | 452 if (!array_var) { |
447 NOTREACHED(); | 453 NOTREACHED(); |
448 message_loop_proxy_->PostTask(FROM_HERE, | 454 message_loop_proxy_->PostTask( |
| 455 FROM_HERE, |
449 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 456 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
450 return; | 457 return; |
451 } | 458 } |
452 | 459 |
453 for (uint32 i = 0; i < v8_array->Length(); ++i) { | 460 for (uint32 i = 0; i < v8_array->Length(); ++i) { |
454 v8::TryCatch try_catch; | 461 v8::TryCatch try_catch; |
455 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); | 462 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); |
456 if (try_catch.HasCaught()) { | 463 if (try_catch.HasCaught()) { |
457 message_loop_proxy_->PostTask(FROM_HERE, | 464 message_loop_proxy_->PostTask( |
| 465 FROM_HERE, |
458 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 466 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
459 return; | 467 return; |
460 } | 468 } |
461 | 469 |
462 if (!v8_array->HasRealIndexedProperty(i)) | 470 if (!v8_array->HasRealIndexedProperty(i)) |
463 continue; | 471 continue; |
464 | 472 |
465 PP_Var child_var; | 473 PP_Var child_var; |
466 if (!GetOrCreateVar(child_v8, context, &child_var, &did_create, | 474 if (!GetOrCreateVar(child_v8, |
467 &visited_handles, &parent_handles, | 475 context, |
| 476 &child_var, |
| 477 &did_create, |
| 478 &visited_handles, |
| 479 &parent_handles, |
468 resource_converter_.get())) { | 480 resource_converter_.get())) { |
469 message_loop_proxy_->PostTask(FROM_HERE, | 481 message_loop_proxy_->PostTask( |
| 482 FROM_HERE, |
470 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 483 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
471 return; | 484 return; |
472 } | 485 } |
473 if (did_create && child_v8->IsObject()) | 486 if (did_create && child_v8->IsObject()) |
474 stack.push(child_v8); | 487 stack.push(child_v8); |
475 | 488 |
476 array_var->Set(i, child_var); | 489 array_var->Set(i, child_var); |
477 } | 490 } |
478 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 491 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
479 DCHECK(current_v8->IsObject()); | 492 DCHECK(current_v8->IsObject()); |
480 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); | 493 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); |
481 parent_handles.insert(HashedHandle(v8_object)); | 494 parent_handles.insert(HashedHandle(v8_object)); |
482 | 495 |
483 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 496 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
484 if (!dict_var) { | 497 if (!dict_var) { |
485 NOTREACHED(); | 498 NOTREACHED(); |
486 message_loop_proxy_->PostTask(FROM_HERE, | 499 message_loop_proxy_->PostTask( |
| 500 FROM_HERE, |
487 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 501 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
488 return; | 502 return; |
489 } | 503 } |
490 | 504 |
491 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); | 505 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); |
492 for (uint32 i = 0; i < property_names->Length(); ++i) { | 506 for (uint32 i = 0; i < property_names->Length(); ++i) { |
493 v8::Handle<v8::Value> key(property_names->Get(i)); | 507 v8::Handle<v8::Value> key(property_names->Get(i)); |
494 | 508 |
495 // Extend this test to cover more types as necessary and if sensible. | 509 // Extend this test to cover more types as necessary and if sensible. |
496 if (!key->IsString() && !key->IsNumber()) { | 510 if (!key->IsString() && !key->IsNumber()) { |
497 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " | 511 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) |
| 512 << "\" " |
498 "is neither a string nor a number"; | 513 "is neither a string nor a number"; |
499 message_loop_proxy_->PostTask(FROM_HERE, | 514 message_loop_proxy_->PostTask( |
| 515 FROM_HERE, |
500 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 516 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
501 return; | 517 return; |
502 } | 518 } |
503 | 519 |
504 // Skip all callbacks: crbug.com/139933 | 520 // Skip all callbacks: crbug.com/139933 |
505 if (v8_object->HasRealNamedCallbackProperty(key->ToString())) | 521 if (v8_object->HasRealNamedCallbackProperty(key->ToString())) |
506 continue; | 522 continue; |
507 | 523 |
508 v8::String::Utf8Value name_utf8(key->ToString()); | 524 v8::String::Utf8Value name_utf8(key->ToString()); |
509 | 525 |
510 v8::TryCatch try_catch; | 526 v8::TryCatch try_catch; |
511 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); | 527 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); |
512 if (try_catch.HasCaught()) { | 528 if (try_catch.HasCaught()) { |
513 message_loop_proxy_->PostTask(FROM_HERE, | 529 message_loop_proxy_->PostTask( |
| 530 FROM_HERE, |
514 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 531 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
515 return; | 532 return; |
516 } | 533 } |
517 | 534 |
518 PP_Var child_var; | 535 PP_Var child_var; |
519 if (!GetOrCreateVar(child_v8, context, &child_var, &did_create, | 536 if (!GetOrCreateVar(child_v8, |
520 &visited_handles, &parent_handles, | 537 context, |
| 538 &child_var, |
| 539 &did_create, |
| 540 &visited_handles, |
| 541 &parent_handles, |
521 resource_converter_.get())) { | 542 resource_converter_.get())) { |
522 message_loop_proxy_->PostTask(FROM_HERE, | 543 message_loop_proxy_->PostTask( |
| 544 FROM_HERE, |
523 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | 545 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); |
524 return; | 546 return; |
525 } | 547 } |
526 if (did_create && child_v8->IsObject()) | 548 if (did_create && child_v8->IsObject()) |
527 stack.push(child_v8); | 549 stack.push(child_v8); |
528 | 550 |
529 bool success = dict_var->SetWithStringKey( | 551 bool success = dict_var->SetWithStringKey( |
530 std::string(*name_utf8, name_utf8.length()), child_var); | 552 std::string(*name_utf8, name_utf8.length()), child_var); |
531 DCHECK(success); | 553 DCHECK(success); |
532 } | 554 } |
533 } | 555 } |
534 } | 556 } |
535 resource_converter_->Flush(base::Bind(callback, root)); | 557 resource_converter_->Flush(base::Bind(callback, root)); |
536 } | 558 } |
537 | 559 |
538 } // namespace content | 560 } // namespace content |
OLD | NEW |