// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "libcef/common/values_impl.h" #include #include // CefBinaryValueImpl implementation. CefRefPtr CefBinaryValue::Create(const void* data, size_t data_size) { DCHECK(data); DCHECK_GT(data_size, (size_t)0); if (!data || data_size == 0) return NULL; return new CefBinaryValueImpl(static_cast(const_cast(data)), data_size, true); } // static CefRefPtr CefBinaryValueImpl::GetOrCreateRef( base::BinaryValue* value, void* parent_value, CefValueController* controller) { DCHECK(value); DCHECK(parent_value); DCHECK(controller); CefValueController::Object* object = controller->Get(value); if (object) return static_cast(object); return new CefBinaryValueImpl(value, parent_value, CefBinaryValueImpl::kReference, controller); } CefBinaryValueImpl::CefBinaryValueImpl(base::BinaryValue* value, bool will_delete, bool read_only) : CefValueBase( value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, read_only, NULL) { } base::BinaryValue* CefBinaryValueImpl::CopyValue() { CEF_VALUE_VERIFY_RETURN(false, NULL); return const_value().DeepCopy(); } base::BinaryValue* CefBinaryValueImpl::CopyOrDetachValue( CefValueController* new_controller) { base::BinaryValue* new_value; if (!will_delete()) { // Copy the value. new_value = CopyValue(); } else { // Take ownership of the value. new_value = Detach(new_controller); } DCHECK(new_value); return new_value; } bool CefBinaryValueImpl::IsValid() { return !detached(); } bool CefBinaryValueImpl::IsOwned() { return !will_delete(); } CefRefPtr CefBinaryValueImpl::Copy() { CEF_VALUE_VERIFY_RETURN(false, NULL); return new CefBinaryValueImpl(const_value().DeepCopy(), NULL, CefBinaryValueImpl::kOwnerWillDelete, NULL); } size_t CefBinaryValueImpl::GetSize() { CEF_VALUE_VERIFY_RETURN(false, 0); return const_value().GetSize(); } size_t CefBinaryValueImpl::GetData(void* buffer, size_t buffer_size, size_t data_offset) { DCHECK(buffer); DCHECK_GT(buffer_size, (size_t)0); if (!buffer || buffer_size == 0) return 0; CEF_VALUE_VERIFY_RETURN(false, 0); size_t size = const_value().GetSize(); DCHECK_LT(data_offset, size); if (data_offset >= size) return 0; size = std::min(buffer_size, size-data_offset); const char* data = const_value().GetBuffer(); memcpy(buffer, data+data_offset, size); return size; } CefBinaryValueImpl::CefBinaryValueImpl(base::BinaryValue* value, void* parent_value, ValueMode value_mode, CefValueController* controller) : CefValueBase( value, parent_value, value_mode, true, controller) { } CefBinaryValueImpl::CefBinaryValueImpl(char* data, size_t data_size, bool copy) : CefValueBase( copy ? base::BinaryValue::CreateWithCopiedBuffer(data, data_size) : new base::BinaryValue(scoped_ptr(data), data_size), NULL, kOwnerWillDelete, true, NULL) { } // CefDictionaryValueImpl implementation. // static CefRefPtr CefDictionaryValue::Create() { return new CefDictionaryValueImpl(new base::DictionaryValue(), NULL, CefDictionaryValueImpl::kOwnerWillDelete, false, NULL); } // static CefRefPtr CefDictionaryValueImpl::GetOrCreateRef( base::DictionaryValue* value, void* parent_value, bool read_only, CefValueController* controller) { CefValueController::Object* object = controller->Get(value); if (object) return static_cast(object); return new CefDictionaryValueImpl(value, parent_value, CefDictionaryValueImpl::kReference, read_only, controller); } CefDictionaryValueImpl::CefDictionaryValueImpl(base::DictionaryValue* value, bool will_delete, bool read_only) : CefValueBase( value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, read_only, NULL) { } base::DictionaryValue* CefDictionaryValueImpl::CopyValue() { CEF_VALUE_VERIFY_RETURN(false, NULL); return const_value().DeepCopy(); } base::DictionaryValue* CefDictionaryValueImpl::CopyOrDetachValue( CefValueController* new_controller) { base::DictionaryValue* new_value; if (!will_delete()) { // Copy the value. new_value = CopyValue(); } else { // Take ownership of the value. new_value = Detach(new_controller); } DCHECK(new_value); return new_value; } bool CefDictionaryValueImpl::IsValid() { return !detached(); } bool CefDictionaryValueImpl::IsOwned() { return !will_delete(); } bool CefDictionaryValueImpl::IsReadOnly() { return read_only(); } CefRefPtr CefDictionaryValueImpl::Copy( bool exclude_empty_children) { CEF_VALUE_VERIFY_RETURN(false, NULL); base::DictionaryValue* value; if (exclude_empty_children) { value = const_cast( const_value()).DeepCopyWithoutEmptyChildren(); } else { value = const_value().DeepCopy(); } return new CefDictionaryValueImpl(value, NULL, CefDictionaryValueImpl::kOwnerWillDelete, false, NULL); } size_t CefDictionaryValueImpl::GetSize() { CEF_VALUE_VERIFY_RETURN(false, 0); return const_value().size(); } bool CefDictionaryValueImpl::Clear() { CEF_VALUE_VERIFY_RETURN(true, false); // Detach any dependent values. controller()->RemoveDependencies(mutable_value()); mutable_value()->Clear(); return true; } bool CefDictionaryValueImpl::HasKey(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, 0); return const_value().HasKey(key); } bool CefDictionaryValueImpl::GetKeys(KeyList& keys) { CEF_VALUE_VERIFY_RETURN(false, 0); for (DictionaryValue::Iterator i(const_value()); !i.IsAtEnd(); i.Advance()) keys.push_back(i.key()); return true; } bool CefDictionaryValueImpl::Remove(const CefString& key) { CEF_VALUE_VERIFY_RETURN(true, false); return RemoveInternal(key); } CefValueType CefDictionaryValueImpl::GetType(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID); const base::Value* out_value = NULL; if (const_value().GetWithoutPathExpansion(key, &out_value)) { switch (out_value->GetType()) { case base::Value::TYPE_NULL: return VTYPE_NULL; case base::Value::TYPE_BOOLEAN: return VTYPE_BOOL; case base::Value::TYPE_INTEGER: return VTYPE_INT; case base::Value::TYPE_DOUBLE: return VTYPE_DOUBLE; case base::Value::TYPE_STRING: return VTYPE_STRING; case base::Value::TYPE_BINARY: return VTYPE_BINARY; case base::Value::TYPE_DICTIONARY: return VTYPE_DICTIONARY; case base::Value::TYPE_LIST: return VTYPE_LIST; } } return VTYPE_INVALID; } bool CefDictionaryValueImpl::GetBool(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, false); const base::Value* out_value = NULL; bool ret_value = false; if (const_value().GetWithoutPathExpansion(key, &out_value)) out_value->GetAsBoolean(&ret_value); return ret_value; } int CefDictionaryValueImpl::GetInt(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, 0); const base::Value* out_value = NULL; int ret_value = 0; if (const_value().GetWithoutPathExpansion(key, &out_value)) out_value->GetAsInteger(&ret_value); return ret_value; } double CefDictionaryValueImpl::GetDouble(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, 0); const base::Value* out_value = NULL; double ret_value = 0; if (const_value().GetWithoutPathExpansion(key, &out_value)) out_value->GetAsDouble(&ret_value); return ret_value; } CefString CefDictionaryValueImpl::GetString(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, CefString()); const base::Value* out_value = NULL; std::string ret_value; if (const_value().GetWithoutPathExpansion(key, &out_value)) out_value->GetAsString(&ret_value); return ret_value; } CefRefPtr CefDictionaryValueImpl::GetBinary( const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().GetWithoutPathExpansion(key, &out_value) && out_value->IsType(base::Value::TYPE_BINARY)) { base::BinaryValue* binary_value = static_cast(const_cast(out_value)); return CefBinaryValueImpl::GetOrCreateRef(binary_value, const_cast(&const_value()), controller()); } return NULL; } CefRefPtr CefDictionaryValueImpl::GetDictionary( const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().GetWithoutPathExpansion(key, &out_value) && out_value->IsType(base::Value::TYPE_DICTIONARY)) { base::DictionaryValue* dict_value = static_cast( const_cast(out_value)); return CefDictionaryValueImpl::GetOrCreateRef( dict_value, const_cast(&const_value()), read_only(), controller()); } return NULL; } CefRefPtr CefDictionaryValueImpl::GetList(const CefString& key) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().GetWithoutPathExpansion(key, &out_value) && out_value->IsType(base::Value::TYPE_LIST)) { base::ListValue* list_value = static_cast(const_cast(out_value)); return CefListValueImpl::GetOrCreateRef( list_value, const_cast(&const_value()), read_only(), controller()); } return NULL; } bool CefDictionaryValueImpl::SetNull(const CefString& key) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateNullValue()); return true; } bool CefDictionaryValueImpl::SetBool(const CefString& key, bool value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateBooleanValue(value)); return true; } bool CefDictionaryValueImpl::SetInt(const CefString& key, int value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateIntegerValue(value)); return true; } bool CefDictionaryValueImpl::SetDouble(const CefString& key, double value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateDoubleValue(value)); return true; } bool CefDictionaryValueImpl::SetString(const CefString& key, const CefString& value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateStringValue(value.ToString())); return true; } bool CefDictionaryValueImpl::SetBinary(const CefString& key, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); CefBinaryValueImpl* impl = static_cast(value.get()); DCHECK(impl); mutable_value()->SetWithoutPathExpansion(key, impl->CopyOrDetachValue(controller())); return true; } bool CefDictionaryValueImpl::SetDictionary( const CefString& key, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); CefDictionaryValueImpl* impl = static_cast(value.get()); DCHECK(impl); mutable_value()->SetWithoutPathExpansion(key, impl->CopyOrDetachValue(controller())); return true; } bool CefDictionaryValueImpl::SetList(const CefString& key, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); RemoveInternal(key); CefListValueImpl* impl = static_cast(value.get()); DCHECK(impl); mutable_value()->SetWithoutPathExpansion(key, impl->CopyOrDetachValue(controller())); return true; } bool CefDictionaryValueImpl::RemoveInternal(const CefString& key) { scoped_ptr out_value; if (!mutable_value()->RemoveWithoutPathExpansion(key, &out_value)) return false; // Remove the value. controller()->Remove(out_value.get(), true); // Only list and dictionary types may have dependencies. if (out_value->IsType(base::Value::TYPE_LIST) || out_value->IsType(base::Value::TYPE_DICTIONARY)) { controller()->RemoveDependencies(out_value.get()); } return true; } CefDictionaryValueImpl::CefDictionaryValueImpl( base::DictionaryValue* value, void* parent_value, ValueMode value_mode, bool read_only, CefValueController* controller) : CefValueBase( value, parent_value, value_mode, read_only, controller) { } // CefListValueImpl implementation. // static CefRefPtr CefListValue::Create() { return new CefListValueImpl(new base::ListValue(), NULL, CefListValueImpl::kOwnerWillDelete, false, NULL); } // static CefRefPtr CefListValueImpl::GetOrCreateRef( base::ListValue* value, void* parent_value, bool read_only, CefValueController* controller) { CefValueController::Object* object = controller->Get(value); if (object) return static_cast(object); return new CefListValueImpl(value, parent_value, CefListValueImpl::kReference, read_only, controller); } CefListValueImpl::CefListValueImpl(base::ListValue* value, bool will_delete, bool read_only) : CefValueBase( value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, read_only, NULL) { } base::ListValue* CefListValueImpl::CopyValue() { CEF_VALUE_VERIFY_RETURN(false, NULL); return const_value().DeepCopy(); } base::ListValue* CefListValueImpl::CopyOrDetachValue( CefValueController* new_controller) { base::ListValue* new_value; if (!will_delete()) { // Copy the value. new_value = CopyValue(); } else { // Take ownership of the value. new_value = Detach(new_controller); } DCHECK(new_value); return new_value; } bool CefListValueImpl::IsValid() { return !detached(); } bool CefListValueImpl::IsOwned() { return !will_delete(); } bool CefListValueImpl::IsReadOnly() { return read_only(); } CefRefPtr CefListValueImpl::Copy() { CEF_VALUE_VERIFY_RETURN(false, NULL); return new CefListValueImpl(const_value().DeepCopy(), NULL, CefListValueImpl::kOwnerWillDelete, false, NULL); } bool CefListValueImpl::SetSize(size_t size) { CEF_VALUE_VERIFY_RETURN(true, false); size_t current_size = const_value().GetSize(); if (size < current_size) { // Clean up any values above the requested size. for (size_t i = current_size-1; i >= size; --i) RemoveInternal(i); } else if (size > 0) { // Expand the list size. mutable_value()->Set(size-1, base::Value::CreateNullValue()); } return true; } size_t CefListValueImpl::GetSize() { CEF_VALUE_VERIFY_RETURN(false, 0); return const_value().GetSize(); } bool CefListValueImpl::Clear() { CEF_VALUE_VERIFY_RETURN(true, false); // Detach any dependent values. controller()->RemoveDependencies(mutable_value()); mutable_value()->Clear(); return true; } bool CefListValueImpl::Remove(int index) { CEF_VALUE_VERIFY_RETURN(true, false); return RemoveInternal(index); } CefValueType CefListValueImpl::GetType(int index) { CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID); const base::Value* out_value = NULL; if (const_value().Get(index, &out_value)) { switch (out_value->GetType()) { case base::Value::TYPE_NULL: return VTYPE_NULL; case base::Value::TYPE_BOOLEAN: return VTYPE_BOOL; case base::Value::TYPE_INTEGER: return VTYPE_INT; case base::Value::TYPE_DOUBLE: return VTYPE_DOUBLE; case base::Value::TYPE_STRING: return VTYPE_STRING; case base::Value::TYPE_BINARY: return VTYPE_BINARY; case base::Value::TYPE_DICTIONARY: return VTYPE_DICTIONARY; case base::Value::TYPE_LIST: return VTYPE_LIST; } } return VTYPE_INVALID; } bool CefListValueImpl::GetBool(int index) { CEF_VALUE_VERIFY_RETURN(false, false); const base::Value* out_value = NULL; bool ret_value = false; if (const_value().Get(index, &out_value)) out_value->GetAsBoolean(&ret_value); return ret_value; } int CefListValueImpl::GetInt(int index) { CEF_VALUE_VERIFY_RETURN(false, 0); const base::Value* out_value = NULL; int ret_value = 0; if (const_value().Get(index, &out_value)) out_value->GetAsInteger(&ret_value); return ret_value; } double CefListValueImpl::GetDouble(int index) { CEF_VALUE_VERIFY_RETURN(false, 0); const base::Value* out_value = NULL; double ret_value = 0; if (const_value().Get(index, &out_value)) out_value->GetAsDouble(&ret_value); return ret_value; } CefString CefListValueImpl::GetString(int index) { CEF_VALUE_VERIFY_RETURN(false, CefString()); const base::Value* out_value = NULL; std::string ret_value; if (const_value().Get(index, &out_value)) out_value->GetAsString(&ret_value); return ret_value; } CefRefPtr CefListValueImpl::GetBinary(int index) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().Get(index, &out_value) && out_value->IsType(base::Value::TYPE_BINARY)) { base::BinaryValue* binary_value = static_cast(const_cast(out_value)); return CefBinaryValueImpl::GetOrCreateRef(binary_value, const_cast(&const_value()), controller()); } return NULL; } CefRefPtr CefListValueImpl::GetDictionary(int index) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().Get(index, &out_value) && out_value->IsType(base::Value::TYPE_DICTIONARY)) { base::DictionaryValue* dict_value = static_cast( const_cast(out_value)); return CefDictionaryValueImpl::GetOrCreateRef( dict_value, const_cast(&const_value()), read_only(), controller()); } return NULL; } CefRefPtr CefListValueImpl::GetList(int index) { CEF_VALUE_VERIFY_RETURN(false, NULL); const base::Value* out_value = NULL; if (const_value().Get(index, &out_value) && out_value->IsType(base::Value::TYPE_LIST)) { base::ListValue* list_value = static_cast(const_cast(out_value)); return CefListValueImpl::GetOrCreateRef( list_value, const_cast(&const_value()), read_only(), controller()); } return NULL; } bool CefListValueImpl::SetNull(int index) { CEF_VALUE_VERIFY_RETURN(true, false); base::Value* new_value = base::Value::CreateNullValue(); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetBool(int index, bool value) { CEF_VALUE_VERIFY_RETURN(true, false); base::Value* new_value = base::Value::CreateBooleanValue(value); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetInt(int index, int value) { CEF_VALUE_VERIFY_RETURN(true, false); base::Value* new_value = base::Value::CreateIntegerValue(value); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetDouble(int index, double value) { CEF_VALUE_VERIFY_RETURN(true, false); base::Value* new_value = base::Value::CreateDoubleValue(value); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetString(int index, const CefString& value) { CEF_VALUE_VERIFY_RETURN(true, false); base::Value* new_value = base::Value::CreateStringValue(value.ToString()); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetBinary(int index, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); CefBinaryValueImpl* impl = static_cast(value.get()); DCHECK(impl); base::Value* new_value = impl->CopyOrDetachValue(controller()); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetDictionary(int index, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); CefDictionaryValueImpl* impl = static_cast(value.get()); DCHECK(impl); base::Value* new_value = impl->CopyOrDetachValue(controller()); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::SetList(int index, CefRefPtr value) { CEF_VALUE_VERIFY_RETURN(true, false); CefListValueImpl* impl = static_cast(value.get()); DCHECK(impl); base::Value* new_value = impl->CopyOrDetachValue(controller()); if (RemoveInternal(index)) mutable_value()->Insert(index, new_value); else mutable_value()->Set(index, new_value); return true; } bool CefListValueImpl::RemoveInternal(int index) { scoped_ptr out_value; if (!mutable_value()->Remove(index, &out_value)) return false; // Remove the value. controller()->Remove(out_value.get(), true); // Only list and dictionary types may have dependencies. if (out_value->IsType(base::Value::TYPE_LIST) || out_value->IsType(base::Value::TYPE_DICTIONARY)) { controller()->RemoveDependencies(out_value.get()); } return true; } CefListValueImpl::CefListValueImpl( base::ListValue* value, void* parent_value, ValueMode value_mode, bool read_only, CefValueController* controller) : CefValueBase( value, parent_value, value_mode, read_only, controller) { }