| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/child/v8_value_converter_impl.h" | 5 #include "content/child/v8_value_converter_impl.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.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 "base/values.h" | 14 #include "base/values.h" |
| 15 #include "third_party/WebKit/public/web/WebArrayBuffer.h" | 15 #include "third_party/WebKit/public/web/WebArrayBuffer.h" |
| 16 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h" | 16 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h" |
| 17 #include "third_party/WebKit/public/web/WebArrayBufferView.h" | 17 #include "third_party/WebKit/public/web/WebArrayBufferView.h" |
| 18 #include "v8/include/v8.h" | 18 #include "v8/include/v8.h" |
| 19 | 19 |
| 20 namespace content { | 20 namespace content { |
| 21 | 21 |
| 22 // Default implementation of V8ValueConverter::Strategy | 22 // Default implementation of V8ValueConverter::Strategy |
| 23 | 23 |
| 24 bool V8ValueConverter::Strategy::FromV8Object( | 24 bool V8ValueConverter::Strategy::FromV8Object( |
| 25 v8::Handle<v8::Object> value, | 25 v8::Local<v8::Object> value, |
| 26 base::Value** out, | 26 base::Value** out, |
| 27 v8::Isolate* isolate, | 27 v8::Isolate* isolate, |
| 28 const FromV8ValueCallback& callback) const { | 28 const FromV8ValueCallback& callback) const { |
| 29 return false; | 29 return false; |
| 30 } | 30 } |
| 31 | 31 |
| 32 bool V8ValueConverter::Strategy::FromV8Array( | 32 bool V8ValueConverter::Strategy::FromV8Array( |
| 33 v8::Handle<v8::Array> value, | 33 v8::Local<v8::Array> value, |
| 34 base::Value** out, | 34 base::Value** out, |
| 35 v8::Isolate* isolate, | 35 v8::Isolate* isolate, |
| 36 const FromV8ValueCallback& callback) const { | 36 const FromV8ValueCallback& callback) const { |
| 37 return false; | 37 return false; |
| 38 } | 38 } |
| 39 | 39 |
| 40 bool V8ValueConverter::Strategy::FromV8ArrayBuffer(v8::Handle<v8::Object> value, | 40 bool V8ValueConverter::Strategy::FromV8ArrayBuffer(v8::Local<v8::Object> value, |
| 41 base::Value** out, | 41 base::Value** out, |
| 42 v8::Isolate* isolate) const { | 42 v8::Isolate* isolate) const { |
| 43 return false; | 43 return false; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool V8ValueConverter::Strategy::FromV8Number(v8::Handle<v8::Number> value, | 46 bool V8ValueConverter::Strategy::FromV8Number(v8::Local<v8::Number> value, |
| 47 base::Value** out) const { | 47 base::Value** out) const { |
| 48 return false; | 48 return false; |
| 49 } | 49 } |
| 50 | 50 |
| 51 bool V8ValueConverter::Strategy::FromV8Undefined(base::Value** out) const { | 51 bool V8ValueConverter::Strategy::FromV8Undefined(base::Value** out) const { |
| 52 return false; | 52 return false; |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 81 : max_recursion_depth_(kMaxRecursionDepth), | 81 : max_recursion_depth_(kMaxRecursionDepth), |
| 82 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {} | 82 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {} |
| 83 | 83 |
| 84 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and | 84 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and |
| 85 // return true. | 85 // return true. |
| 86 // | 86 // |
| 87 // Otherwise do nothing and return false. Here "A is unique" means that no | 87 // Otherwise do nothing and return false. Here "A is unique" means that no |
| 88 // other handle B in the map points to the same object as A. Note that A can | 88 // other handle B in the map points to the same object as A. Note that A can |
| 89 // be unique even if there already is another handle with the same identity | 89 // be unique even if there already is another handle with the same identity |
| 90 // hash (key) in the map, because two objects can have the same hash. | 90 // hash (key) in the map, because two objects can have the same hash. |
| 91 bool UpdateAndCheckUniqueness(v8::Handle<v8::Object> handle) { | 91 bool UpdateAndCheckUniqueness(v8::Local<v8::Object> handle) { |
| 92 typedef HashToHandleMap::const_iterator Iterator; | 92 typedef HashToHandleMap::const_iterator Iterator; |
| 93 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); | 93 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); |
| 94 // We only compare using == with handles to objects with the same identity | 94 // We only compare using == with handles to objects with the same identity |
| 95 // hash. Different hash obviously means different objects, but two objects | 95 // hash. Different hash obviously means different objects, but two objects |
| 96 // in a couple of thousands could have the same identity hash. | 96 // in a couple of thousands could have the same identity hash. |
| 97 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); | 97 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); |
| 98 for (Iterator it = range.first; it != range.second; ++it) { | 98 for (Iterator it = range.first; it != range.second; ++it) { |
| 99 // Operator == for handles actually compares the underlying objects. | 99 // Operator == for handles actually compares the underlying objects. |
| 100 if (it->second == handle) | 100 if (it->second == handle) |
| 101 return false; | 101 return false; |
| 102 } | 102 } |
| 103 unique_map_.insert(std::make_pair(hash, handle)); | 103 unique_map_.insert(std::make_pair(hash, handle)); |
| 104 return true; | 104 return true; |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool HasReachedMaxRecursionDepth() { | 107 bool HasReachedMaxRecursionDepth() { |
| 108 return max_recursion_depth_ < 0; | 108 return max_recursion_depth_ < 0; |
| 109 } | 109 } |
| 110 | 110 |
| 111 private: | 111 private: |
| 112 typedef std::multimap<int, v8::Handle<v8::Object> > HashToHandleMap; | 112 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap; |
| 113 HashToHandleMap unique_map_; | 113 HashToHandleMap unique_map_; |
| 114 | 114 |
| 115 int max_recursion_depth_; | 115 int max_recursion_depth_; |
| 116 | 116 |
| 117 bool avoid_identity_hash_for_testing_; | 117 bool avoid_identity_hash_for_testing_; |
| 118 }; | 118 }; |
| 119 | 119 |
| 120 V8ValueConverter* V8ValueConverter::create() { | 120 V8ValueConverter* V8ValueConverter::create() { |
| 121 return new V8ValueConverterImpl(); | 121 return new V8ValueConverterImpl(); |
| 122 } | 122 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 142 } | 142 } |
| 143 | 143 |
| 144 void V8ValueConverterImpl::SetStripNullFromObjects(bool val) { | 144 void V8ValueConverterImpl::SetStripNullFromObjects(bool val) { |
| 145 strip_null_from_objects_ = val; | 145 strip_null_from_objects_ = val; |
| 146 } | 146 } |
| 147 | 147 |
| 148 void V8ValueConverterImpl::SetStrategy(Strategy* strategy) { | 148 void V8ValueConverterImpl::SetStrategy(Strategy* strategy) { |
| 149 strategy_ = strategy; | 149 strategy_ = strategy; |
| 150 } | 150 } |
| 151 | 151 |
| 152 v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Value( | 152 v8::Local<v8::Value> V8ValueConverterImpl::ToV8Value( |
| 153 const base::Value* value, v8::Handle<v8::Context> context) const { | 153 const base::Value* value, v8::Local<v8::Context> context) const { |
| 154 v8::Context::Scope context_scope(context); | 154 v8::Context::Scope context_scope(context); |
| 155 v8::EscapableHandleScope handle_scope(context->GetIsolate()); | 155 v8::EscapableHandleScope handle_scope(context->GetIsolate()); |
| 156 return handle_scope.Escape( | 156 return handle_scope.Escape( |
| 157 ToV8ValueImpl(context->GetIsolate(), context->Global(), value)); | 157 ToV8ValueImpl(context->GetIsolate(), context->Global(), value)); |
| 158 } | 158 } |
| 159 | 159 |
| 160 base::Value* V8ValueConverterImpl::FromV8Value( | 160 base::Value* V8ValueConverterImpl::FromV8Value( |
| 161 v8::Handle<v8::Value> val, | 161 v8::Local<v8::Value> val, |
| 162 v8::Handle<v8::Context> context) const { | 162 v8::Local<v8::Context> context) const { |
| 163 v8::Context::Scope context_scope(context); | 163 v8::Context::Scope context_scope(context); |
| 164 v8::HandleScope handle_scope(context->GetIsolate()); | 164 v8::HandleScope handle_scope(context->GetIsolate()); |
| 165 FromV8ValueState state(avoid_identity_hash_for_testing_); | 165 FromV8ValueState state(avoid_identity_hash_for_testing_); |
| 166 return FromV8ValueImpl(&state, val, context->GetIsolate()); | 166 return FromV8ValueImpl(&state, val, context->GetIsolate()); |
| 167 } | 167 } |
| 168 | 168 |
| 169 v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl( | 169 v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl( |
| 170 v8::Isolate* isolate, | 170 v8::Isolate* isolate, |
| 171 v8::Handle<v8::Object> creation_context, | 171 v8::Local<v8::Object> creation_context, |
| 172 const base::Value* value) const { | 172 const base::Value* value) const { |
| 173 CHECK(value); | 173 CHECK(value); |
| 174 switch (value->GetType()) { | 174 switch (value->GetType()) { |
| 175 case base::Value::TYPE_NULL: | 175 case base::Value::TYPE_NULL: |
| 176 return v8::Null(isolate); | 176 return v8::Null(isolate); |
| 177 | 177 |
| 178 case base::Value::TYPE_BOOLEAN: { | 178 case base::Value::TYPE_BOOLEAN: { |
| 179 bool val = false; | 179 bool val = false; |
| 180 CHECK(value->GetAsBoolean(&val)); | 180 CHECK(value->GetAsBoolean(&val)); |
| 181 return v8::Boolean::New(isolate, val); | 181 return v8::Boolean::New(isolate, val); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 return ToArrayBuffer(isolate, | 214 return ToArrayBuffer(isolate, |
| 215 creation_context, | 215 creation_context, |
| 216 static_cast<const base::BinaryValue*>(value)); | 216 static_cast<const base::BinaryValue*>(value)); |
| 217 | 217 |
| 218 default: | 218 default: |
| 219 LOG(ERROR) << "Unexpected value type: " << value->GetType(); | 219 LOG(ERROR) << "Unexpected value type: " << value->GetType(); |
| 220 return v8::Null(isolate); | 220 return v8::Null(isolate); |
| 221 } | 221 } |
| 222 } | 222 } |
| 223 | 223 |
| 224 v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Array( | 224 v8::Local<v8::Value> V8ValueConverterImpl::ToV8Array( |
| 225 v8::Isolate* isolate, | 225 v8::Isolate* isolate, |
| 226 v8::Handle<v8::Object> creation_context, | 226 v8::Local<v8::Object> creation_context, |
| 227 const base::ListValue* val) const { | 227 const base::ListValue* val) const { |
| 228 v8::Handle<v8::Array> result(v8::Array::New(isolate, val->GetSize())); | 228 v8::Local<v8::Array> result(v8::Array::New(isolate, val->GetSize())); |
| 229 | 229 |
| 230 for (size_t i = 0; i < val->GetSize(); ++i) { | 230 for (size_t i = 0; i < val->GetSize(); ++i) { |
| 231 const base::Value* child = NULL; | 231 const base::Value* child = NULL; |
| 232 CHECK(val->Get(i, &child)); | 232 CHECK(val->Get(i, &child)); |
| 233 | 233 |
| 234 v8::Handle<v8::Value> child_v8 = | 234 v8::Local<v8::Value> child_v8 = |
| 235 ToV8ValueImpl(isolate, creation_context, child); | 235 ToV8ValueImpl(isolate, creation_context, child); |
| 236 CHECK(!child_v8.IsEmpty()); | 236 CHECK(!child_v8.IsEmpty()); |
| 237 | 237 |
| 238 v8::TryCatch try_catch; | 238 v8::TryCatch try_catch; |
| 239 result->Set(static_cast<uint32>(i), child_v8); | 239 result->Set(static_cast<uint32>(i), child_v8); |
| 240 if (try_catch.HasCaught()) | 240 if (try_catch.HasCaught()) |
| 241 LOG(ERROR) << "Setter for index " << i << " threw an exception."; | 241 LOG(ERROR) << "Setter for index " << i << " threw an exception."; |
| 242 } | 242 } |
| 243 | 243 |
| 244 return result; | 244 return result; |
| 245 } | 245 } |
| 246 | 246 |
| 247 v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Object( | 247 v8::Local<v8::Value> V8ValueConverterImpl::ToV8Object( |
| 248 v8::Isolate* isolate, | 248 v8::Isolate* isolate, |
| 249 v8::Handle<v8::Object> creation_context, | 249 v8::Local<v8::Object> creation_context, |
| 250 const base::DictionaryValue* val) const { | 250 const base::DictionaryValue* val) const { |
| 251 v8::Handle<v8::Object> result(v8::Object::New(isolate)); | 251 v8::Local<v8::Object> result(v8::Object::New(isolate)); |
| 252 | 252 |
| 253 for (base::DictionaryValue::Iterator iter(*val); | 253 for (base::DictionaryValue::Iterator iter(*val); |
| 254 !iter.IsAtEnd(); iter.Advance()) { | 254 !iter.IsAtEnd(); iter.Advance()) { |
| 255 const std::string& key = iter.key(); | 255 const std::string& key = iter.key(); |
| 256 v8::Handle<v8::Value> child_v8 = | 256 v8::Local<v8::Value> child_v8 = |
| 257 ToV8ValueImpl(isolate, creation_context, &iter.value()); | 257 ToV8ValueImpl(isolate, creation_context, &iter.value()); |
| 258 CHECK(!child_v8.IsEmpty()); | 258 CHECK(!child_v8.IsEmpty()); |
| 259 | 259 |
| 260 v8::TryCatch try_catch; | 260 v8::TryCatch try_catch; |
| 261 result->Set( | 261 result->Set( |
| 262 v8::String::NewFromUtf8( | 262 v8::String::NewFromUtf8( |
| 263 isolate, key.c_str(), v8::String::kNormalString, key.length()), | 263 isolate, key.c_str(), v8::String::kNormalString, key.length()), |
| 264 child_v8); | 264 child_v8); |
| 265 if (try_catch.HasCaught()) { | 265 if (try_catch.HasCaught()) { |
| 266 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " | 266 LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " |
| 267 << "exception."; | 267 << "exception."; |
| 268 } | 268 } |
| 269 } | 269 } |
| 270 | 270 |
| 271 return result; | 271 return result; |
| 272 } | 272 } |
| 273 | 273 |
| 274 v8::Handle<v8::Value> V8ValueConverterImpl::ToArrayBuffer( | 274 v8::Local<v8::Value> V8ValueConverterImpl::ToArrayBuffer( |
| 275 v8::Isolate* isolate, | 275 v8::Isolate* isolate, |
| 276 v8::Handle<v8::Object> creation_context, | 276 v8::Local<v8::Object> creation_context, |
| 277 const base::BinaryValue* value) const { | 277 const base::BinaryValue* value) const { |
| 278 blink::WebArrayBuffer buffer = | 278 blink::WebArrayBuffer buffer = |
| 279 blink::WebArrayBuffer::create(value->GetSize(), 1); | 279 blink::WebArrayBuffer::create(value->GetSize(), 1); |
| 280 memcpy(buffer.data(), value->GetBuffer(), value->GetSize()); | 280 memcpy(buffer.data(), value->GetBuffer(), value->GetSize()); |
| 281 return blink::WebArrayBufferConverter::toV8Value( | 281 return blink::WebArrayBufferConverter::toV8Value( |
| 282 &buffer, creation_context, isolate); | 282 &buffer, creation_context, isolate); |
| 283 } | 283 } |
| 284 | 284 |
| 285 base::Value* V8ValueConverterImpl::FromV8ValueImpl( | 285 base::Value* V8ValueConverterImpl::FromV8ValueImpl( |
| 286 FromV8ValueState* state, | 286 FromV8ValueState* state, |
| 287 v8::Handle<v8::Value> val, | 287 v8::Local<v8::Value> val, |
| 288 v8::Isolate* isolate) const { | 288 v8::Isolate* isolate) const { |
| 289 CHECK(!val.IsEmpty()); | 289 CHECK(!val.IsEmpty()); |
| 290 | 290 |
| 291 FromV8ValueState::Level state_level(state); | 291 FromV8ValueState::Level state_level(state); |
| 292 if (state->HasReachedMaxRecursionDepth()) | 292 if (state->HasReachedMaxRecursionDepth()) |
| 293 return NULL; | 293 return NULL; |
| 294 | 294 |
| 295 if (val->IsNull()) | 295 if (val->IsNull()) |
| 296 return base::Value::CreateNullValue(); | 296 return base::Value::CreateNullValue(); |
| 297 | 297 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 return FromV8ArrayBuffer(val.As<v8::Object>(), isolate); | 360 return FromV8ArrayBuffer(val.As<v8::Object>(), isolate); |
| 361 | 361 |
| 362 if (val->IsObject()) | 362 if (val->IsObject()) |
| 363 return FromV8Object(val.As<v8::Object>(), state, isolate); | 363 return FromV8Object(val.As<v8::Object>(), state, isolate); |
| 364 | 364 |
| 365 LOG(ERROR) << "Unexpected v8 value type encountered."; | 365 LOG(ERROR) << "Unexpected v8 value type encountered."; |
| 366 return NULL; | 366 return NULL; |
| 367 } | 367 } |
| 368 | 368 |
| 369 base::Value* V8ValueConverterImpl::FromV8Array( | 369 base::Value* V8ValueConverterImpl::FromV8Array( |
| 370 v8::Handle<v8::Array> val, | 370 v8::Local<v8::Array> val, |
| 371 FromV8ValueState* state, | 371 FromV8ValueState* state, |
| 372 v8::Isolate* isolate) const { | 372 v8::Isolate* isolate) const { |
| 373 if (!state->UpdateAndCheckUniqueness(val)) | 373 if (!state->UpdateAndCheckUniqueness(val)) |
| 374 return base::Value::CreateNullValue(); | 374 return base::Value::CreateNullValue(); |
| 375 | 375 |
| 376 scoped_ptr<v8::Context::Scope> scope; | 376 scoped_ptr<v8::Context::Scope> scope; |
| 377 // If val was created in a different context than our current one, change to | 377 // If val was created in a different context than our current one, change to |
| 378 // that context, but change back after val is converted. | 378 // that context, but change back after val is converted. |
| 379 if (!val->CreationContext().IsEmpty() && | 379 if (!val->CreationContext().IsEmpty() && |
| 380 val->CreationContext() != isolate->GetCurrentContext()) | 380 val->CreationContext() != isolate->GetCurrentContext()) |
| 381 scope.reset(new v8::Context::Scope(val->CreationContext())); | 381 scope.reset(new v8::Context::Scope(val->CreationContext())); |
| 382 | 382 |
| 383 if (strategy_) { | 383 if (strategy_) { |
| 384 // These base::Unretained's are safe, because Strategy::FromV8Value should | 384 // These base::Unretained's are safe, because Strategy::FromV8Value should |
| 385 // be synchronous, so this object can't be out of scope. | 385 // be synchronous, so this object can't be out of scope. |
| 386 V8ValueConverter::Strategy::FromV8ValueCallback callback = | 386 V8ValueConverter::Strategy::FromV8ValueCallback callback = |
| 387 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl, | 387 base::Bind(&V8ValueConverterImpl::FromV8ValueImpl, |
| 388 base::Unretained(this), | 388 base::Unretained(this), |
| 389 base::Unretained(state)); | 389 base::Unretained(state)); |
| 390 base::Value* out = NULL; | 390 base::Value* out = NULL; |
| 391 if (strategy_->FromV8Array(val, &out, isolate, callback)) | 391 if (strategy_->FromV8Array(val, &out, isolate, callback)) |
| 392 return out; | 392 return out; |
| 393 } | 393 } |
| 394 | 394 |
| 395 base::ListValue* result = new base::ListValue(); | 395 base::ListValue* result = new base::ListValue(); |
| 396 | 396 |
| 397 // Only fields with integer keys are carried over to the ListValue. | 397 // Only fields with integer keys are carried over to the ListValue. |
| 398 for (uint32 i = 0; i < val->Length(); ++i) { | 398 for (uint32 i = 0; i < val->Length(); ++i) { |
| 399 v8::TryCatch try_catch; | 399 v8::TryCatch try_catch; |
| 400 v8::Handle<v8::Value> child_v8 = val->Get(i); | 400 v8::Local<v8::Value> child_v8 = val->Get(i); |
| 401 if (try_catch.HasCaught()) { | 401 if (try_catch.HasCaught()) { |
| 402 LOG(ERROR) << "Getter for index " << i << " threw an exception."; | 402 LOG(ERROR) << "Getter for index " << i << " threw an exception."; |
| 403 child_v8 = v8::Null(isolate); | 403 child_v8 = v8::Null(isolate); |
| 404 } | 404 } |
| 405 | 405 |
| 406 if (!val->HasRealIndexedProperty(i)) { | 406 if (!val->HasRealIndexedProperty(i)) { |
| 407 result->Append(base::Value::CreateNullValue()); | 407 result->Append(base::Value::CreateNullValue()); |
| 408 continue; | 408 continue; |
| 409 } | 409 } |
| 410 | 410 |
| 411 base::Value* child = FromV8ValueImpl(state, child_v8, isolate); | 411 base::Value* child = FromV8ValueImpl(state, child_v8, isolate); |
| 412 if (child) | 412 if (child) |
| 413 result->Append(child); | 413 result->Append(child); |
| 414 else | 414 else |
| 415 // JSON.stringify puts null in places where values don't serialize, for | 415 // JSON.stringify puts null in places where values don't serialize, for |
| 416 // example undefined and functions. Emulate that behavior. | 416 // example undefined and functions. Emulate that behavior. |
| 417 result->Append(base::Value::CreateNullValue()); | 417 result->Append(base::Value::CreateNullValue()); |
| 418 } | 418 } |
| 419 return result; | 419 return result; |
| 420 } | 420 } |
| 421 | 421 |
| 422 base::Value* V8ValueConverterImpl::FromV8ArrayBuffer( | 422 base::Value* V8ValueConverterImpl::FromV8ArrayBuffer( |
| 423 v8::Handle<v8::Object> val, | 423 v8::Local<v8::Object> val, |
| 424 v8::Isolate* isolate) const { | 424 v8::Isolate* isolate) const { |
| 425 if (strategy_) { | 425 if (strategy_) { |
| 426 base::Value* out = NULL; | 426 base::Value* out = NULL; |
| 427 if (strategy_->FromV8ArrayBuffer(val, &out, isolate)) | 427 if (strategy_->FromV8ArrayBuffer(val, &out, isolate)) |
| 428 return out; | 428 return out; |
| 429 } | 429 } |
| 430 | 430 |
| 431 char* data = NULL; | 431 char* data = NULL; |
| 432 size_t length = 0; | 432 size_t length = 0; |
| 433 | 433 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 if (data) | 448 if (data) |
| 449 return base::BinaryValue::CreateWithCopiedBuffer(data, length); | 449 return base::BinaryValue::CreateWithCopiedBuffer(data, length); |
| 450 else | 450 else |
| 451 return NULL; | 451 return NULL; |
| 452 } | 452 } |
| 453 | 453 |
| 454 base::Value* V8ValueConverterImpl::FromV8Object( | 454 base::Value* V8ValueConverterImpl::FromV8Object( |
| 455 v8::Handle<v8::Object> val, | 455 v8::Local<v8::Object> val, |
| 456 FromV8ValueState* state, | 456 FromV8ValueState* state, |
| 457 v8::Isolate* isolate) const { | 457 v8::Isolate* isolate) const { |
| 458 if (!state->UpdateAndCheckUniqueness(val)) | 458 if (!state->UpdateAndCheckUniqueness(val)) |
| 459 return base::Value::CreateNullValue(); | 459 return base::Value::CreateNullValue(); |
| 460 | 460 |
| 461 scoped_ptr<v8::Context::Scope> scope; | 461 scoped_ptr<v8::Context::Scope> scope; |
| 462 // If val was created in a different context than our current one, change to | 462 // If val was created in a different context than our current one, change to |
| 463 // that context, but change back after val is converted. | 463 // that context, but change back after val is converted. |
| 464 if (!val->CreationContext().IsEmpty() && | 464 if (!val->CreationContext().IsEmpty() && |
| 465 val->CreationContext() != isolate->GetCurrentContext()) | 465 val->CreationContext() != isolate->GetCurrentContext()) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 487 // | 487 // |
| 488 // NOTE: check this after |strategy_| so that callers have a chance to | 488 // NOTE: check this after |strategy_| so that callers have a chance to |
| 489 // do something else, such as convert to the node's name rather than NULL. | 489 // do something else, such as convert to the node's name rather than NULL. |
| 490 // | 490 // |
| 491 // ANOTHER NOTE: returning an empty dictionary here to minimise surprise. | 491 // ANOTHER NOTE: returning an empty dictionary here to minimise surprise. |
| 492 // See also http://crbug.com/330559. | 492 // See also http://crbug.com/330559. |
| 493 if (val->InternalFieldCount()) | 493 if (val->InternalFieldCount()) |
| 494 return new base::DictionaryValue(); | 494 return new base::DictionaryValue(); |
| 495 | 495 |
| 496 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | 496 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
| 497 v8::Handle<v8::Array> property_names(val->GetOwnPropertyNames()); | 497 v8::Local<v8::Array> property_names(val->GetOwnPropertyNames()); |
| 498 | 498 |
| 499 for (uint32 i = 0; i < property_names->Length(); ++i) { | 499 for (uint32 i = 0; i < property_names->Length(); ++i) { |
| 500 v8::Handle<v8::Value> key(property_names->Get(i)); | 500 v8::Local<v8::Value> key(property_names->Get(i)); |
| 501 | 501 |
| 502 // Extend this test to cover more types as necessary and if sensible. | 502 // Extend this test to cover more types as necessary and if sensible. |
| 503 if (!key->IsString() && | 503 if (!key->IsString() && |
| 504 !key->IsNumber()) { | 504 !key->IsNumber()) { |
| 505 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " | 505 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " |
| 506 "is neither a string nor a number"; | 506 "is neither a string nor a number"; |
| 507 continue; | 507 continue; |
| 508 } | 508 } |
| 509 | 509 |
| 510 v8::String::Utf8Value name_utf8(key); | 510 v8::String::Utf8Value name_utf8(key); |
| 511 | 511 |
| 512 v8::TryCatch try_catch; | 512 v8::TryCatch try_catch; |
| 513 v8::Handle<v8::Value> child_v8 = val->Get(key); | 513 v8::Local<v8::Value> child_v8 = val->Get(key); |
| 514 | 514 |
| 515 if (try_catch.HasCaught()) { | 515 if (try_catch.HasCaught()) { |
| 516 LOG(WARNING) << "Getter for property " << *name_utf8 | 516 LOG(WARNING) << "Getter for property " << *name_utf8 |
| 517 << " threw an exception."; | 517 << " threw an exception."; |
| 518 child_v8 = v8::Null(isolate); | 518 child_v8 = v8::Null(isolate); |
| 519 } | 519 } |
| 520 | 520 |
| 521 scoped_ptr<base::Value> child(FromV8ValueImpl(state, child_v8, isolate)); | 521 scoped_ptr<base::Value> child(FromV8ValueImpl(state, child_v8, isolate)); |
| 522 if (!child) | 522 if (!child) |
| 523 // JSON.stringify skips properties whose values don't serialize, for | 523 // JSON.stringify skips properties whose values don't serialize, for |
| (...skipping 24 matching lines...) Expand all Loading... |
| 548 continue; | 548 continue; |
| 549 | 549 |
| 550 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), | 550 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), |
| 551 child.release()); | 551 child.release()); |
| 552 } | 552 } |
| 553 | 553 |
| 554 return result.release(); | 554 return result.release(); |
| 555 } | 555 } |
| 556 | 556 |
| 557 } // namespace content | 557 } // namespace content |
| OLD | NEW |