blob: cfcc9be5efb2bd2c59f596e159e7e63225e7194b [file] [log] [blame]
[email protected]e244e1a2014-06-20 09:47:371// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/enhanced_bookmarks/metadata_accessor.h"
6
7#include <iomanip>
8
9#include "base/base64.h"
10#include "base/rand_util.h"
11#include "components/bookmarks/browser/bookmark_model.h"
12#include "components/enhanced_bookmarks/proto/metadata.pb.h"
13#include "ui/base/models/tree_node_iterator.h"
14
15using namespace image::collections;
16
17namespace {
18
19// Helper method for working with bookmark metainfo.
20std::string DataForMetaInfoField(const BookmarkNode* node,
21 const std::string& field) {
22 const BookmarkNode::MetaInfoMap* map = node->GetMetaInfoMap();
23 if (!map)
24 return "";
25
26 BookmarkNode::MetaInfoMap::const_iterator it = map->find(field);
27 if (it == map->end())
28 return "";
29
30 std::string decoded;
31 bool result = base::Base64Decode((*it).second, &decoded);
32 if (!result)
33 return "";
34
35 return decoded;
36}
37
38// Sets a new remote id on a bookmark.
39std::string SetRemoteIdOnBookmark(BookmarkModel* bookmark_model,
40 const BookmarkNode* node) {
41 // Generate 16 digit hex string random id.
42 std::stringstream random_id;
43 random_id << std::hex << std::setfill('0') << std::setw(16);
44 random_id << base::RandUint64() << base::RandUint64();
45 std::string random_id_str = random_id.str();
46 bookmark_model->SetNodeMetaInfo(
47 node, enhanced_bookmarks::kIdDataKey, random_id_str);
48 return random_id_str;
49}
50
51// Helper method for working with ImageData_ImageInfo.
52bool PopulateImageData(const ImageData_ImageInfo& info,
53 GURL* out_url,
54 int* width,
55 int* height) {
56 if (!info.has_url() || !info.has_width() || !info.has_height())
57 return false;
58
59 GURL url(info.url());
60 if (!url.is_valid())
61 return false;
62
63 *out_url = url;
64 *width = info.width();
65 *height = info.height();
66 return true;
67}
68
69} // namespace
70
71namespace enhanced_bookmarks {
72
73const char* kPageDataKey = "stars.pageData";
74const char* kImageDataKey = "stars.imageData";
75const char* kIdDataKey = "stars.id";
76const char* kNoteKey = "stars.note";
77
78std::string RemoteIdFromBookmark(BookmarkModel* bookmark_model,
79 const BookmarkNode* node) {
80 const BookmarkNode::MetaInfoMap* map = node->GetMetaInfoMap();
81 if (!map)
82 return SetRemoteIdOnBookmark(bookmark_model, node);
83
84 BookmarkNode::MetaInfoMap::const_iterator it = map->find(kIdDataKey);
85 if (it == map->end())
86 return SetRemoteIdOnBookmark(bookmark_model, node);
87
88 DCHECK(it->second.length());
89 return it->second;
90}
91
92void SetDescriptionForBookmark(BookmarkModel* bookmark_model,
93 const BookmarkNode* node,
94 const std::string& description) {
95 bookmark_model->SetNodeMetaInfo(node, kNoteKey, description);
96}
97
98std::string DescriptionFromBookmark(const BookmarkNode* node) {
99 const BookmarkNode::MetaInfoMap* map = node->GetMetaInfoMap();
100 if (!map)
101 return "";
102
103 // First, look for a custom note set by the user.
104 BookmarkNode::MetaInfoMap::const_iterator it = map->find(kNoteKey);
105 if (it != map->end() && it->second != "")
106 return it->second;
107
108 // If none are present, return the snippet.
109 return SnippetFromBookmark(node);
110}
111
112bool SetOriginalImageForBookmark(BookmarkModel* bookmark_model,
113 const BookmarkNode* node,
114 const GURL& url,
115 int width,
116 int height) {
117 DCHECK(url.is_valid());
118
119 std::string decoded(DataForMetaInfoField(node, kImageDataKey));
120 ImageData data;
121
122 // Try to populate the imageData with the existing data.
123 if (decoded != "") {
124 // If the parsing fails, something is wrong. Immediately fail.
125 bool result = data.ParseFromString(decoded);
126 if (!result)
127 return false;
128 }
129
130 scoped_ptr<ImageData_ImageInfo> info(new ImageData_ImageInfo);
131 info->set_url(url.spec());
132 info->set_width(width);
133 info->set_height(height);
134 data.set_allocated_original_info(info.release());
135
136 std::string output;
137 bool result = data.SerializePartialToString(&output);
138 if (!result)
139 return false;
140
141 std::string encoded;
142 base::Base64Encode(output, &encoded);
143 bookmark_model->SetNodeMetaInfo(node, kImageDataKey, encoded);
144 // Ensure that the bookmark has a stars.id, to trigger the server processing.
145 RemoteIdFromBookmark(bookmark_model, node);
146 return true;
147}
148
149bool OriginalImageFromBookmark(const BookmarkNode* node,
150 GURL* url,
151 int* width,
152 int* height) {
153 std::string decoded(DataForMetaInfoField(node, kImageDataKey));
154 if (decoded == "")
155 return false;
156
157 ImageData data;
158 bool result = data.ParseFromString(decoded);
159 if (!result)
160 return false;
161
162 if (!data.has_original_info())
163 return false;
164
165 return PopulateImageData(data.original_info(), url, width, height);
166}
167
168bool ThumbnailImageFromBookmark(const BookmarkNode* node,
169 GURL* url,
170 int* width,
171 int* height) {
172 std::string decoded(DataForMetaInfoField(node, kImageDataKey));
173 if (decoded == "")
174 return false;
175
176 ImageData data;
177 bool result = data.ParseFromString(decoded);
178 if (!result)
179 return false;
180
181 if (!data.has_thumbnail_info())
182 return false;
183
184 return PopulateImageData(data.thumbnail_info(), url, width, height);
185}
186
187std::string SnippetFromBookmark(const BookmarkNode* node) {
188 std::string decoded(DataForMetaInfoField(node, kPageDataKey));
189 if (decoded == "")
190 return decoded;
191
192 PageData data;
193 bool result = data.ParseFromString(decoded);
194 if (!result)
195 return "";
196
197 return data.snippet();
198}
199
200bool SetAllImagesForBookmark(BookmarkModel* bookmark_model,
201 const BookmarkNode* node,
202 const GURL& image_url,
203 int image_width,
204 int image_height,
205 const GURL& thumbnail_url,
206 int thumbnail_width,
207 int thumbnail_height) {
208 DCHECK(image_url.is_valid() || image_url.is_empty());
209 DCHECK(thumbnail_url.is_valid() || thumbnail_url.is_empty());
210 std::string decoded(DataForMetaInfoField(node, kImageDataKey));
211 ImageData data;
212
213 // Try to populate the imageData with the existing data.
214 if (decoded != "") {
215 // If the parsing fails, something is wrong. Immediately fail.
216 bool result = data.ParseFromString(decoded);
217 if (!result)
218 return false;
219 }
220
221 if (image_url.is_empty()) {
222 data.release_original_info();
223 } else {
224 // Regardless of whether an image info exists, we make a new one.
225 // Intentially make a raw pointer.
226 ImageData_ImageInfo* info = new ImageData_ImageInfo;
227 info->set_url(image_url.spec());
228 info->set_width(image_width);
229 info->set_height(image_height);
230 // This method consumes the raw pointer.
231 data.set_allocated_original_info(info);
232 }
233
234 if (thumbnail_url.is_empty()) {
235 data.release_thumbnail_info();
236 } else {
237 // Regardless of whether an image info exists, we make a new one.
238 // Intentially make a raw pointer.
239 ImageData_ImageInfo* info = new ImageData_ImageInfo;
240 info->set_url(thumbnail_url.spec());
241 info->set_width(thumbnail_width);
242 info->set_height(thumbnail_height);
243 // This method consumes the raw pointer.
244 data.set_allocated_thumbnail_info(info);
245 }
246 std::string output;
247 bool result = data.SerializePartialToString(&output);
248 if (!result)
249 return false;
250
251 std::string encoded;
252 base::Base64Encode(output, &encoded);
253 bookmark_model->SetNodeMetaInfo(node, kImageDataKey, encoded);
254 return true;
255}
256
257} // namespace enhanced_bookmarks