11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/enhanced_bookmarks/enhanced_bookmark_model.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <iomanip>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <sstream>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/base64.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/message_loop/message_loop_proxy.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/rand_util.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/bookmarks/browser/bookmark_model.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/bookmarks/browser/bookmark_node.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/enhanced_bookmarks/proto/metadata.pb.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/models/tree_node_iterator.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "url/gurl.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kBookmarkBarId = "f_bookmarks_bar";
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kIdKey = "stars.id";
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kImageDataKey = "stars.imageData";
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kNoteKey = "stars.note";
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kOldIdKey = "stars.oldId";
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kPageDataKey = "stars.pageData";
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kVersionKey = "stars.version";
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* kBookmarkPrefix = "ebc_";
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper method for working with bookmark metainfo.
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string DataForMetaInfoField(const BookmarkNode* node,
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 const std::string& field) {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string value;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!node->GetMetaInfo(field, &value))
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return std::string();
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!base::Base64Decode(value, &decoded))
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return std::string();
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return decoded;
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Helper method for working with ImageData_ImageInfo.
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool PopulateImageData(const image::collections::ImageData_ImageInfo& info,
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       GURL* out_url,
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int* width,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int* height) {
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!info.has_url() || !info.has_width() || !info.has_height())
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(info.url());
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!url.is_valid())
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *out_url = url;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *width = info.width();
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *height = info.height();
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Generate a random remote id, with a prefix that depends on whether the node
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// is a folder or a bookmark.
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string GenerateRemoteId() {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::stringstream random_id;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  random_id << kBookmarkPrefix;
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Generate 32 digit hex string random suffix.
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  random_id << std::hex << std::setfill('0') << std::setw(16);
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  random_id << base::RandUint64() << base::RandUint64();
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return random_id.str();
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace enhanced_bookmarks {
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEnhancedBookmarkModel::EnhancedBookmarkModel(BookmarkModel* bookmark_model,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             const std::string& version)
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : bookmark_model_(bookmark_model),
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      loaded_(false),
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_ptr_factory_(this),
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      version_(version) {
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->AddObserver(this);
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (bookmark_model_->loaded()) {
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    InitializeIdMap();
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    loaded_ = true;
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEnhancedBookmarkModel::~EnhancedBookmarkModel() {
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::Shutdown() {
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(EnhancedBookmarkModelObserver,
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    observers_,
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    EnhancedBookmarkModelShuttingDown());
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  weak_ptr_factory_.InvalidateWeakPtrs();
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->RemoveObserver(this);
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_ = NULL;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::AddObserver(
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EnhancedBookmarkModelObserver* observer) {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  observers_.AddObserver(observer);
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::RemoveObserver(
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EnhancedBookmarkModelObserver* observer) {
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  observers_.RemoveObserver(observer);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Moves |node| to |new_parent| and inserts it at the given |index|.
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::Move(const BookmarkNode* node,
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 const BookmarkNode* new_parent,
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 int index) {
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->Move(node, new_parent, index);
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Adds a new folder node at the specified position.
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst BookmarkNode* EnhancedBookmarkModel::AddFolder(
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* parent,
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int index,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::string16& title) {
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return bookmark_model_->AddFolder(parent, index, title);
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Adds a url at the specified position.
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst BookmarkNode* EnhancedBookmarkModel::AddURL(
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* parent,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int index,
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::string16& title,
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL& url,
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Time& creation_time) {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BookmarkNode::MetaInfoMap meta_info;
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  meta_info[kIdKey] = GenerateRemoteId();
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return bookmark_model_->AddURLWithCreationTimeAndMetaInfo(
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      parent, index, title, url, creation_time, &meta_info);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string EnhancedBookmarkModel::GetRemoteId(const BookmarkNode* node) {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (node == bookmark_model_->bookmark_bar_node())
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return kBookmarkBarId;
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string id;
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!node->GetMetaInfo(kIdKey, &id))
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return std::string();
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return id;
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst BookmarkNode* EnhancedBookmarkModel::BookmarkForRemoteId(
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& remote_id) {
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IdToNodeMap::iterator it = id_map_.find(remote_id);
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (it != id_map_.end())
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return it->second;
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return NULL;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::SetDescription(const BookmarkNode* node,
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           const std::string& description) {
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetMetaInfo(node, kNoteKey, description);
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string EnhancedBookmarkModel::GetDescription(const BookmarkNode* node) {
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // First, look for a custom note set by the user.
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string description;
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (node->GetMetaInfo(kNoteKey, &description) && !description.empty())
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return description;
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If none are present, return the snippet.
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return GetSnippet(node);
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool EnhancedBookmarkModel::SetOriginalImage(const BookmarkNode* node,
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             const GURL& url,
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             int width,
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             int height) {
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(node->is_url());
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(url.is_valid());
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded(DataForMetaInfoField(node, kImageDataKey));
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  image::collections::ImageData data;
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Try to populate the imageData with the existing data.
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decoded != "") {
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the parsing fails, something is wrong. Immediately fail.
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool result = data.ParseFromString(decoded);
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!result)
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<image::collections::ImageData_ImageInfo> info(
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new image::collections::ImageData_ImageInfo);
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info->set_url(url.spec());
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info->set_width(width);
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info->set_height(height);
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  data.set_allocated_original_info(info.release());
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string output;
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool result = data.SerializePartialToString(&output);
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result)
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string encoded;
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Base64Encode(output, &encoded);
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetMetaInfo(node, kImageDataKey, encoded);
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool EnhancedBookmarkModel::GetOriginalImage(const BookmarkNode* node,
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             GURL* url,
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             int* width,
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             int* height) {
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded(DataForMetaInfoField(node, kImageDataKey));
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decoded == "")
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  image::collections::ImageData data;
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool result = data.ParseFromString(decoded);
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result)
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!data.has_original_info())
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return PopulateImageData(data.original_info(), url, width, height);
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool EnhancedBookmarkModel::GetThumbnailImage(const BookmarkNode* node,
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              GURL* url,
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              int* width,
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              int* height) {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded(DataForMetaInfoField(node, kImageDataKey));
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decoded == "")
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  image::collections::ImageData data;
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool result = data.ParseFromString(decoded);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result)
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!data.has_thumbnail_info())
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return PopulateImageData(data.thumbnail_info(), url, width, height);
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string EnhancedBookmarkModel::GetSnippet(const BookmarkNode* node) {
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded(DataForMetaInfoField(node, kPageDataKey));
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decoded.empty())
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return decoded;
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  image::collections::PageData data;
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool result = data.ParseFromString(decoded);
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result)
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return std::string();
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return data.snippet();
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::SetVersionSuffix(
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& version_suffix) {
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  version_suffix_ = version_suffix;
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkModelChanged() {
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkModelLoaded(BookmarkModel* model,
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                bool ids_reassigned) {
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  InitializeIdMap();
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkModelLoaded());
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkNodeAdded(BookmarkModel* model,
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              const BookmarkNode* parent,
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              int index) {
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const BookmarkNode* node = parent->GetChild(index);
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AddToIdMap(node);
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScheduleResetDuplicateRemoteIds();
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkAdded(node));
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkNodeRemoved(
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BookmarkModel* model,
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* parent,
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int old_index,
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* node,
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::set<GURL>& removed_urls) {
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string remote_id = GetRemoteId(node);
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  id_map_.erase(remote_id);
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkRemoved(node));
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::OnWillChangeBookmarkMetaInfo(
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BookmarkModel* model,
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* node) {
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  prev_remote_id_ = GetRemoteId(node);
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkMetaInfoChanged(BookmarkModel* model,
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                    const BookmarkNode* node) {
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string remote_id = GetRemoteId(node);
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (remote_id != prev_remote_id_) {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    id_map_.erase(prev_remote_id_);
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!remote_id.empty()) {
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      AddToIdMap(node);
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ScheduleResetDuplicateRemoteIds();
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    FOR_EACH_OBSERVER(
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        EnhancedBookmarkModelObserver,
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        observers_,
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        EnhancedBookmarkRemoteIdChanged(node, prev_remote_id_, remote_id));
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::BookmarkAllUserNodesRemoved(
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BookmarkModel* model,
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::set<GURL>& removed_urls) {
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  id_map_.clear();
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Re-initialize so non-user nodes with remote ids are present in the map.
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  InitializeIdMap();
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(EnhancedBookmarkModelObserver,
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    observers_,
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    EnhancedBookmarkAllUserNodesRemoved());
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::InitializeIdMap() {
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ui::TreeNodeIterator<const BookmarkNode> iterator(
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bookmark_model_->root_node());
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (iterator.has_next()) {
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddToIdMap(iterator.Next());
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScheduleResetDuplicateRemoteIds();
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::AddToIdMap(const BookmarkNode* node) {
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string remote_id = GetRemoteId(node);
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (remote_id.empty())
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Try to insert the node.
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::pair<IdToNodeMap::iterator, bool> result =
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      id_map_.insert(make_pair(remote_id, node));
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result.second) {
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Some node already had the same remote id, so add both nodes to the
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // to-be-reset set.
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    nodes_to_reset_[result.first->second] = remote_id;
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    nodes_to_reset_[node] = remote_id;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::ScheduleResetDuplicateRemoteIds() {
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!nodes_to_reset_.empty()) {
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::MessageLoopProxy::current()->PostTask(
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&EnhancedBookmarkModel::ResetDuplicateRemoteIds,
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_ptr_factory_.GetWeakPtr()));
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::ResetDuplicateRemoteIds() {
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (NodeToIdMap::iterator it = nodes_to_reset_.begin();
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != nodes_to_reset_.end();
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BookmarkNode::MetaInfoMap meta_info;
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    meta_info[kIdKey] = "";
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    meta_info[kOldIdKey] = it->second;
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SetMultipleMetaInfo(it->first, meta_info);
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  nodes_to_reset_.clear();
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::SetMetaInfo(const BookmarkNode* node,
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        const std::string& field,
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        const std::string& value) {
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!bookmark_model_->is_permanent_node(node));
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BookmarkNode::MetaInfoMap meta_info;
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const BookmarkNode::MetaInfoMap* old_meta_info = node->GetMetaInfoMap();
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (old_meta_info)
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    meta_info.insert(old_meta_info->begin(), old_meta_info->end());
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't update anything if the value to set is already there.
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BookmarkNode::MetaInfoMap::iterator it = meta_info.find(field);
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (it != meta_info.end() && it->second == value)
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  meta_info[field] = value;
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  meta_info[kVersionKey] = GetVersionString();
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->SetNodeMetaInfoMap(node, meta_info);
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string EnhancedBookmarkModel::GetVersionString() {
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (version_suffix_.empty())
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return version_;
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return version_ + '/' + version_suffix_;
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnhancedBookmarkModel::SetMultipleMetaInfo(
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode* node,
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BookmarkNode::MetaInfoMap meta_info) {
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!bookmark_model_->is_permanent_node(node));
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't update anything if every value is already set correctly.
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (node->GetMetaInfoMap()) {
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool changed = false;
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const BookmarkNode::MetaInfoMap* old_meta_info = node->GetMetaInfoMap();
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (BookmarkNode::MetaInfoMap::iterator it = meta_info.begin();
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         it != meta_info.end();
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         ++it) {
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BookmarkNode::MetaInfoMap::const_iterator old_field =
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          old_meta_info->find(it->first);
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (old_field == old_meta_info->end() ||
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          old_field->second != it->second) {
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        changed = true;
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!changed)
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Fill in the values that aren't changing
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    meta_info.insert(old_meta_info->begin(), old_meta_info->end());
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  meta_info[kVersionKey] = GetVersionString();
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->SetNodeMetaInfoMap(node, meta_info);
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool EnhancedBookmarkModel::SetAllImages(const BookmarkNode* node,
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         const GURL& image_url,
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         int image_width,
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         int image_height,
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         const GURL& thumbnail_url,
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         int thumbnail_width,
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         int thumbnail_height) {
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(node->is_url());
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(image_url.is_valid() || image_url.is_empty());
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(thumbnail_url.is_valid() || thumbnail_url.is_empty());
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string decoded(DataForMetaInfoField(node, kImageDataKey));
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  image::collections::ImageData data;
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Try to populate the imageData with the existing data.
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decoded != "") {
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the parsing fails, something is wrong. Immediately fail.
4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool result = data.ParseFromString(decoded);
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!result)
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (image_url.is_empty()) {
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data.release_original_info();
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Regardless of whether an image info exists, we make a new one.
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Intentially make a raw pointer.
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    image::collections::ImageData_ImageInfo* info =
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new image::collections::ImageData_ImageInfo;
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_url(image_url.spec());
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_width(image_width);
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_height(image_height);
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // This method consumes the raw pointer.
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data.set_allocated_original_info(info);
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (thumbnail_url.is_empty()) {
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data.release_thumbnail_info();
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Regardless of whether an image info exists, we make a new one.
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Intentially make a raw pointer.
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    image::collections::ImageData_ImageInfo* info =
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new image::collections::ImageData_ImageInfo;
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_url(thumbnail_url.spec());
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_width(thumbnail_width);
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info->set_height(thumbnail_height);
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // This method consumes the raw pointer.
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data.set_allocated_thumbnail_info(info);
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string output;
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool result = data.SerializePartialToString(&output);
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!result)
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string encoded;
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Base64Encode(output, &encoded);
4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bookmark_model_->SetNodeMetaInfo(node, kImageDataKey, encoded);
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace enhanced_bookmarks
496