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