Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / components / bookmarks / browser / bookmark_node_data.cc
blobad2ad42476dd5defdad41c779b04df457958c6f6
1 // 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.
5 #include "components/bookmarks/browser/bookmark_node_data.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/pickle.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/bookmarks/browser/bookmark_utils.h"
14 #include "ui/base/clipboard/scoped_clipboard_writer.h"
16 namespace bookmarks {
18 const char* BookmarkNodeData::kClipboardFormatString =
19 "chromium/x-bookmark-entries";
21 BookmarkNodeData::Element::Element() : is_url(false), id_(0) {
24 BookmarkNodeData::Element::Element(const BookmarkNode* node)
25 : is_url(node->is_url()),
26 url(node->url()),
27 title(node->GetTitle()),
28 date_added(node->date_added()),
29 date_folder_modified(node->date_folder_modified()),
30 id_(node->id()) {
31 if (node->GetMetaInfoMap())
32 meta_info_map = *node->GetMetaInfoMap();
33 for (int i = 0; i < node->child_count(); ++i)
34 children.push_back(Element(node->GetChild(i)));
37 BookmarkNodeData::Element::~Element() {
40 void BookmarkNodeData::Element::WriteToPickle(Pickle* pickle) const {
41 pickle->WriteBool(is_url);
42 pickle->WriteString(url.spec());
43 pickle->WriteString16(title);
44 pickle->WriteInt64(id_);
45 pickle->WriteUInt64(meta_info_map.size());
46 for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin();
47 it != meta_info_map.end(); ++it) {
48 pickle->WriteString(it->first);
49 pickle->WriteString(it->second);
51 if (!is_url) {
52 pickle->WriteUInt64(children.size());
53 for (std::vector<Element>::const_iterator i = children.begin();
54 i != children.end(); ++i) {
55 i->WriteToPickle(pickle);
60 bool BookmarkNodeData::Element::ReadFromPickle(Pickle* pickle,
61 PickleIterator* iterator) {
62 std::string url_spec;
63 if (!pickle->ReadBool(iterator, &is_url) ||
64 !pickle->ReadString(iterator, &url_spec) ||
65 !pickle->ReadString16(iterator, &title) ||
66 !pickle->ReadInt64(iterator, &id_)) {
67 return false;
69 url = GURL(url_spec);
70 date_added = base::Time();
71 date_folder_modified = base::Time();
72 meta_info_map.clear();
73 uint64 meta_field_count;
74 if (!pickle->ReadUInt64(iterator, &meta_field_count))
75 return false;
76 for (uint64 i = 0; i < meta_field_count; ++i) {
77 std::string key;
78 std::string value;
79 if (!pickle->ReadString(iterator, &key) ||
80 !pickle->ReadString(iterator, &value)) {
81 return false;
83 meta_info_map[key] = value;
85 children.clear();
86 if (!is_url) {
87 uint64 children_count;
88 if (!pickle->ReadUInt64(iterator, &children_count))
89 return false;
90 children.reserve(children_count);
91 for (uint64 i = 0; i < children_count; ++i) {
92 children.push_back(Element());
93 if (!children.back().ReadFromPickle(pickle, iterator))
94 return false;
97 return true;
100 // BookmarkNodeData -----------------------------------------------------------
102 BookmarkNodeData::BookmarkNodeData() {
105 BookmarkNodeData::BookmarkNodeData(const BookmarkNode* node) {
106 elements.push_back(Element(node));
109 BookmarkNodeData::BookmarkNodeData(
110 const std::vector<const BookmarkNode*>& nodes) {
111 ReadFromVector(nodes);
114 BookmarkNodeData::~BookmarkNodeData() {
117 #if !defined(OS_MACOSX)
118 // static
119 bool BookmarkNodeData::ClipboardContainsBookmarks() {
120 return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
121 ui::Clipboard::GetFormatType(kClipboardFormatString),
122 ui::CLIPBOARD_TYPE_COPY_PASTE);
124 #endif
126 bool BookmarkNodeData::ReadFromVector(
127 const std::vector<const BookmarkNode*>& nodes) {
128 Clear();
130 if (nodes.empty())
131 return false;
133 for (size_t i = 0; i < nodes.size(); ++i)
134 elements.push_back(Element(nodes[i]));
136 return true;
139 bool BookmarkNodeData::ReadFromTuple(const GURL& url,
140 const base::string16& title) {
141 Clear();
143 if (!url.is_valid())
144 return false;
146 Element element;
147 element.title = title;
148 element.url = url;
149 element.is_url = true;
151 elements.push_back(element);
153 return true;
156 #if !defined(OS_MACOSX)
157 void BookmarkNodeData::WriteToClipboard(ui::ClipboardType clipboard_type) {
158 DCHECK(clipboard_type == ui::CLIPBOARD_TYPE_COPY_PASTE ||
159 clipboard_type == ui::CLIPBOARD_TYPE_SELECTION);
160 ui::ScopedClipboardWriter scw(ui::Clipboard::GetForCurrentThread(),
161 clipboard_type);
163 // If there is only one element and it is a URL, write the URL to the
164 // clipboard.
165 if (elements.size() == 1 && elements[0].is_url) {
166 const base::string16& title = elements[0].title;
167 const std::string url = elements[0].url.spec();
169 scw.WriteBookmark(title, url);
171 // Don't call scw.WriteHyperlink() here, since some rich text editors will
172 // change fonts when such data is pasted in; besides, most such editors
173 // auto-linkify at some point anyway.
175 // Also write the URL to the clipboard as text so that it can be pasted
176 // into text fields. We use WriteText instead of WriteURL because we don't
177 // want to clobber the X clipboard when the user copies out of the omnibox
178 // on Linux (on Windows and Mac, there is no difference between these
179 // functions).
180 scw.WriteText(base::UTF8ToUTF16(url));
183 Pickle pickle;
184 WriteToPickle(base::FilePath(), &pickle);
185 scw.WritePickledData(pickle,
186 ui::Clipboard::GetFormatType(kClipboardFormatString));
189 bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
190 DCHECK_EQ(type, ui::CLIPBOARD_TYPE_COPY_PASTE);
191 std::string data;
192 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
193 clipboard->ReadData(ui::Clipboard::GetFormatType(kClipboardFormatString),
194 &data);
196 if (!data.empty()) {
197 Pickle pickle(data.data(), static_cast<int>(data.size()));
198 if (ReadFromPickle(&pickle))
199 return true;
202 base::string16 title;
203 std::string url;
204 clipboard->ReadBookmark(&title, &url);
205 if (!url.empty()) {
206 Element element;
207 element.is_url = true;
208 element.url = GURL(url);
209 element.title = title;
211 elements.clear();
212 elements.push_back(element);
213 return true;
216 return false;
218 #endif
220 void BookmarkNodeData::WriteToPickle(const base::FilePath& profile_path,
221 Pickle* pickle) const {
222 profile_path.WriteToPickle(pickle);
223 pickle->WriteUInt64(elements.size());
225 for (size_t i = 0; i < elements.size(); ++i)
226 elements[i].WriteToPickle(pickle);
229 bool BookmarkNodeData::ReadFromPickle(Pickle* pickle) {
230 PickleIterator data_iterator(*pickle);
231 uint64 element_count;
232 if (profile_path_.ReadFromPickle(&data_iterator) &&
233 pickle->ReadUInt64(&data_iterator, &element_count)) {
234 std::vector<Element> tmp_elements;
235 tmp_elements.resize(element_count);
236 for (uint64 i = 0; i < element_count; ++i) {
237 if (!tmp_elements[i].ReadFromPickle(pickle, &data_iterator)) {
238 return false;
241 elements.swap(tmp_elements);
244 return true;
247 std::vector<const BookmarkNode*> BookmarkNodeData::GetNodes(
248 BookmarkModel* model,
249 const base::FilePath& profile_path) const {
250 std::vector<const BookmarkNode*> nodes;
252 if (!IsFromProfilePath(profile_path))
253 return nodes;
255 for (size_t i = 0; i < elements.size(); ++i) {
256 const BookmarkNode* node = GetBookmarkNodeByID(model, elements[i].id_);
257 if (!node) {
258 nodes.clear();
259 return nodes;
261 nodes.push_back(node);
263 return nodes;
266 const BookmarkNode* BookmarkNodeData::GetFirstNode(
267 BookmarkModel* model,
268 const base::FilePath& profile_path) const {
269 std::vector<const BookmarkNode*> nodes = GetNodes(model, profile_path);
270 return nodes.size() == 1 ? nodes[0] : NULL;
273 void BookmarkNodeData::Clear() {
274 profile_path_.clear();
275 elements.clear();
278 void BookmarkNodeData::SetOriginatingProfilePath(
279 const base::FilePath& profile_path) {
280 DCHECK(profile_path_.empty());
281 profile_path_ = profile_path;
284 bool BookmarkNodeData::IsFromProfilePath(
285 const base::FilePath& profile_path) const {
286 // An empty path means the data is not associated with any profile.
287 return !profile_path_.empty() && profile_path_ == profile_path;
290 } // namespace bookmarks