1 // Copyright (c) 2012 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 "chrome/browser/bookmarks/bookmark_node_data.h"
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 "chrome/browser/bookmarks/bookmark_model.h"
14 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "ui/base/clipboard/scoped_clipboard_writer.h"
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()),
27 title(node
->GetTitle()),
28 date_added(node
->date_added()),
29 date_folder_modified(node
->date_folder_modified()),
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
);
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
) {
63 if (!pickle
->ReadBool(iterator
, &is_url
) ||
64 !pickle
->ReadString(iterator
, &url_spec
) ||
65 !pickle
->ReadString16(iterator
, &title
) ||
66 !pickle
->ReadInt64(iterator
, &id_
)) {
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
))
76 for (uint64 i
= 0; i
< meta_field_count
; ++i
) {
79 if (!pickle
->ReadString(iterator
, &key
) ||
80 !pickle
->ReadString(iterator
, &value
)) {
83 meta_info_map
[key
] = value
;
87 uint64 children_count
;
88 if (!pickle
->ReadUInt64(iterator
, &children_count
))
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
))
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)
119 bool BookmarkNodeData::ClipboardContainsBookmarks() {
120 return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
121 ui::Clipboard::GetFormatType(kClipboardFormatString
),
122 ui::CLIPBOARD_TYPE_COPY_PASTE
);
126 bool BookmarkNodeData::ReadFromVector(
127 const std::vector
<const BookmarkNode
*>& nodes
) {
133 for (size_t i
= 0; i
< nodes
.size(); ++i
)
134 elements
.push_back(Element(nodes
[i
]));
139 bool BookmarkNodeData::ReadFromTuple(const GURL
& url
, const base::string16
& title
) {
146 element
.title
= title
;
148 element
.is_url
= true;
150 elements
.push_back(element
);
155 #if !defined(OS_MACOSX)
156 void BookmarkNodeData::WriteToClipboard(ui::ClipboardType type
) {
157 DCHECK_EQ(type
, ui::CLIPBOARD_TYPE_COPY_PASTE
);
158 ui::ScopedClipboardWriter
scw(ui::Clipboard::GetForCurrentThread(),
159 ui::CLIPBOARD_TYPE_COPY_PASTE
);
161 // If there is only one element and it is a URL, write the URL to the
163 if (elements
.size() == 1 && elements
[0].is_url
) {
164 const base::string16
& title
= elements
[0].title
;
165 const std::string url
= elements
[0].url
.spec();
167 scw
.WriteBookmark(title
, url
);
169 // Don't call scw.WriteHyperlink() here, since some rich text editors will
170 // change fonts when such data is pasted in; besides, most such editors
171 // auto-linkify at some point anyway.
173 // Also write the URL to the clipboard as text so that it can be pasted
174 // into text fields. We use WriteText instead of WriteURL because we don't
175 // want to clobber the X clipboard when the user copies out of the omnibox
176 // on Linux (on Windows and Mac, there is no difference between these
178 scw
.WriteText(base::UTF8ToUTF16(url
));
182 WriteToPickle(NULL
, &pickle
);
183 scw
.WritePickledData(pickle
,
184 ui::Clipboard::GetFormatType(kClipboardFormatString
));
187 bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type
) {
188 DCHECK_EQ(type
, ui::CLIPBOARD_TYPE_COPY_PASTE
);
190 ui::Clipboard
* clipboard
= ui::Clipboard::GetForCurrentThread();
191 clipboard
->ReadData(ui::Clipboard::GetFormatType(kClipboardFormatString
),
195 Pickle
pickle(data
.data(), data
.size());
196 if (ReadFromPickle(&pickle
))
200 base::string16 title
;
202 clipboard
->ReadBookmark(&title
, &url
);
205 element
.is_url
= true;
206 element
.url
= GURL(url
);
207 element
.title
= title
;
210 elements
.push_back(element
);
218 void BookmarkNodeData::WriteToPickle(Profile
* profile
, Pickle
* pickle
) const {
219 base::FilePath path
= profile
? profile
->GetPath() : base::FilePath();
220 path
.WriteToPickle(pickle
);
221 pickle
->WriteUInt64(elements
.size());
223 for (size_t i
= 0; i
< elements
.size(); ++i
)
224 elements
[i
].WriteToPickle(pickle
);
227 bool BookmarkNodeData::ReadFromPickle(Pickle
* pickle
) {
228 PickleIterator
data_iterator(*pickle
);
229 uint64 element_count
;
230 if (profile_path_
.ReadFromPickle(&data_iterator
) &&
231 pickle
->ReadUInt64(&data_iterator
, &element_count
)) {
232 std::vector
<Element
> tmp_elements
;
233 tmp_elements
.resize(element_count
);
234 for (uint64 i
= 0; i
< element_count
; ++i
) {
235 if (!tmp_elements
[i
].ReadFromPickle(pickle
, &data_iterator
)) {
239 elements
.swap(tmp_elements
);
245 std::vector
<const BookmarkNode
*> BookmarkNodeData::GetNodes(
246 Profile
* profile
) const {
247 std::vector
<const BookmarkNode
*> nodes
;
249 if (!IsFromProfile(profile
))
252 for (size_t i
= 0; i
< elements
.size(); ++i
) {
253 const BookmarkNode
* node
= BookmarkModelFactory::GetForProfile(
254 profile
)->GetNodeByID(elements
[i
].id_
);
259 nodes
.push_back(node
);
264 const BookmarkNode
* BookmarkNodeData::GetFirstNode(Profile
* profile
) const {
265 std::vector
<const BookmarkNode
*> nodes
= GetNodes(profile
);
266 return nodes
.size() == 1 ? nodes
[0] : NULL
;
269 void BookmarkNodeData::Clear() {
270 profile_path_
.clear();
274 void BookmarkNodeData::SetOriginatingProfile(Profile
* profile
) {
275 DCHECK(profile_path_
.empty());
278 profile_path_
= profile
->GetPath();
281 bool BookmarkNodeData::IsFromProfile(Profile
* profile
) const {
282 // An empty path means the data is not associated with any profile.
283 return !profile_path_
.empty() && profile_path_
== profile
->GetPath();