diff options
Diffstat (limited to 'chrome/browser/bookmark_codec.cc')
-rw-r--r-- | chrome/browser/bookmark_codec.cc | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/chrome/browser/bookmark_codec.cc b/chrome/browser/bookmark_codec.cc new file mode 100644 index 0000000..37f0ed0 --- /dev/null +++ b/chrome/browser/bookmark_codec.cc @@ -0,0 +1,197 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/bookmark_codec.h" + +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/bookmark_bar_model.h" +#include "googleurl/src/gurl.h" + +// Key names. +static const wchar_t* kRootsKey = L"roots"; +static const wchar_t* kRootFolderNameKey = L"root"; +static const wchar_t* kOtherBookmarFolderNameKey = L"other"; +static const wchar_t* kVersionKey = L"version"; +static const wchar_t* kTypeKey = L"type"; +static const wchar_t* kNameKey = L"name"; +static const wchar_t* kDateAddedKey = L"date_added"; +static const wchar_t* kURLKey = L"url"; +static const wchar_t* kDateModifiedKey = L"date_modified"; +static const wchar_t* kChildrenKey = L"children"; + +// Possible values for kTypeKey. +static const wchar_t* kTypeURL = L"url"; +static const wchar_t* kTypeFolder = L"folder"; + +// Current version of the file. +static const int kCurrentVersion = 1; + +Value* BookmarkCodec::Encode(BookmarkBarModel* model) { + DictionaryValue* roots = new DictionaryValue(); + roots->Set(kRootFolderNameKey, EncodeNode(model->GetBookmarkBarNode())); + roots->Set(kOtherBookmarFolderNameKey, EncodeNode(model->other_node())); + + DictionaryValue* main = new DictionaryValue(); + main->SetInteger(kVersionKey, kCurrentVersion); + main->Set(kRootsKey, roots); + return main; +} + +bool BookmarkCodec::Decode(BookmarkBarModel* model, const Value& value) { + if (value.GetType() != Value::TYPE_DICTIONARY) + return false; // Unexpected type. + + const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); + + int version; + if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) + return false; // Unknown version. + + Value* roots; + if (!d_value.Get(kRootsKey, &roots)) + return false; // No roots. + + if (roots->GetType() != Value::TYPE_DICTIONARY) + return false; // Invalid type for roots. + + DictionaryValue* roots_d_value = static_cast<DictionaryValue*>(roots); + Value* root_folder_value; + Value* other_folder_value; + if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || + root_folder_value->GetType() != Value::TYPE_DICTIONARY || + !roots_d_value->Get(kOtherBookmarFolderNameKey, &other_folder_value) || + other_folder_value->GetType() != Value::TYPE_DICTIONARY) + return false; // Invalid type for root folder and/or other folder. + + DecodeNode(model, *static_cast<DictionaryValue*>(root_folder_value), + model->GetBookmarkBarNode()); + DecodeNode(model, *static_cast<DictionaryValue*>(other_folder_value), + model->other_node()); + // Need to reset these as Decode sets the type to FOLDER. + model->GetBookmarkBarNode()->type_ = history::StarredEntry::BOOKMARK_BAR; + model->other_node()->type_ = history::StarredEntry::OTHER; + return true; +} + +Value* BookmarkCodec::EncodeNode(BookmarkBarNode* node) { + DictionaryValue* value = new DictionaryValue(); + value->SetString(kNameKey, node->GetTitle()); + value->SetString(kDateAddedKey, + Int64ToWString(node->date_added().ToInternalValue())); + if (node->GetType() == history::StarredEntry::URL) { + value->SetString(kTypeKey, kTypeURL); + value->SetString(kURLKey, + UTF8ToWide(node->GetURL().possibly_invalid_spec())); + } else { + value->SetString(kTypeKey, kTypeFolder); + value->SetString(kDateModifiedKey, + Int64ToWString(node->date_group_modified(). + ToInternalValue())); + + ListValue* child_values = new ListValue(); + value->Set(kChildrenKey, child_values); + for (int i = 0; i < node->GetChildCount(); ++i) + child_values->Append(EncodeNode(node->GetChild(i))); + } + return value; +} + +bool BookmarkCodec::DecodeChildren(BookmarkBarModel* model, + const ListValue& child_value_list, + BookmarkBarNode* parent) { + for (size_t i = 0; i < child_value_list.GetSize(); ++i) { + Value* child_value; + if (!child_value_list.Get(i, &child_value)) + return false; + + if (child_value->GetType() != Value::TYPE_DICTIONARY) + return false; + + BookmarkBarNode* child = new BookmarkBarNode(model); + parent->Add(static_cast<int>(i), child); + if (!DecodeNode(model, *static_cast<DictionaryValue*>(child_value), child)) + return false; + } + return true; +} + +bool BookmarkCodec::DecodeNode(BookmarkBarModel* model, + const DictionaryValue& value, + BookmarkBarNode* node) { + std::wstring title; + if (!value.GetString(kNameKey, &title)) + return false; + node->SetTitle(title); + + std::wstring date_added_string; + if (!value.GetString(kDateAddedKey, &date_added_string)) + return false; + node->date_added_ = + Time::FromInternalValue(StringToInt64(date_added_string)); + + std::wstring type_string; + if (!value.GetString(kTypeKey, &type_string)) + return false; + + if (type_string != kTypeURL && type_string != kTypeFolder) + return false; // Unknown type. + + if (type_string == kTypeURL) { + std::wstring url_string; + if (!value.GetString(kURLKey, &url_string)) + return false; + node->SetURL(GURL(url_string)); + node->type_ = history::StarredEntry::URL; + } else { + node->type_ = history::StarredEntry::USER_GROUP; + + std::wstring last_modified_date; + if (!value.GetString(kDateModifiedKey, &last_modified_date)) + return false; + node->date_group_modified_ = + Time::FromInternalValue(StringToInt64(last_modified_date)); + + Value* child_values; + if (!value.Get(kChildrenKey, &child_values)) + return false; + + if (child_values->GetType() != Value::TYPE_LIST) + return false; + + if (!DecodeChildren(model, *static_cast<ListValue*>(child_values), node)) { + // There was an error in building the children. Delete all the children. + while (node->GetChildCount()) + delete node->Remove(node->GetChildCount() - 1); + return false; + } + } + + return true; +} |