Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / bookmarks / browser / bookmark_node_data.cc
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.
4
5 #include "components/bookmarks/browser/bookmark_node_data.h"
6
7 #include <string>
8
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"
15
16 namespace bookmarks {
17
18 const char* BookmarkNodeData::kClipboardFormatString =
19     "chromium/x-bookmark-entries";
20
21 BookmarkNodeData::Element::Element() : is_url(false), id_(0) {
22 }
23
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)));
35 }
36
37 BookmarkNodeData::Element::~Element() {
38 }
39
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->WriteSizeT(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);
50   }
51   if (!is_url) {
52     pickle->WriteSizeT(children.size());
53     for (std::vector<Element>::const_iterator i = children.begin();
54          i != children.end(); ++i) {
55       i->WriteToPickle(pickle);
56     }
57   }
58 }
59
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;
68   }
69   url = GURL(url_spec);
70   date_added = base::Time();
71   date_folder_modified = base::Time();
72   meta_info_map.clear();
73   size_t meta_field_count;
74   if (!pickle->ReadSizeT(iterator, &meta_field_count))
75     return false;
76   for (size_t 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;
82     }
83     meta_info_map[key] = value;
84   }
85   children.clear();
86   if (!is_url) {
87     size_t children_count;
88     if (!pickle->ReadSizeT(iterator, &children_count))
89       return false;
90     children.reserve(children_count);
91     for (size_t i = 0; i < children_count; ++i) {
92       children.push_back(Element());
93       if (!children.back().ReadFromPickle(pickle, iterator))
94         return false;
95     }
96   }
97   return true;
98 }
99
100 // BookmarkNodeData -----------------------------------------------------------
101
102 BookmarkNodeData::BookmarkNodeData() {
103 }
104
105 BookmarkNodeData::BookmarkNodeData(const BookmarkNode* node) {
106   elements.push_back(Element(node));
107 }
108
109 BookmarkNodeData::BookmarkNodeData(
110     const std::vector<const BookmarkNode*>& nodes) {
111   ReadFromVector(nodes);
112 }
113
114 BookmarkNodeData::~BookmarkNodeData() {
115 }
116
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);
123 }
124 #endif
125
126 bool BookmarkNodeData::ReadFromVector(
127     const std::vector<const BookmarkNode*>& nodes) {
128   Clear();
129
130   if (nodes.empty())
131     return false;
132
133   for (size_t i = 0; i < nodes.size(); ++i)
134     elements.push_back(Element(nodes[i]));
135
136   return true;
137 }
138
139 bool BookmarkNodeData::ReadFromTuple(const GURL& url,
140                                      const base::string16& title) {
141   Clear();
142
143   if (!url.is_valid())
144     return false;
145
146   Element element;
147   element.title = title;
148   element.url = url;
149   element.is_url = true;
150
151   elements.push_back(element);
152
153   return true;
154 }
155
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(clipboard_type);
161
162   // If there is only one element and it is a URL, write the URL to the
163   // clipboard.
164   if (elements.size() == 1 && elements[0].is_url) {
165     const base::string16& title = elements[0].title;
166     const std::string url = elements[0].url.spec();
167
168     scw.WriteBookmark(title, url);
169
170     // Don't call scw.WriteHyperlink() here, since some rich text editors will
171     // change fonts when such data is pasted in; besides, most such editors
172     // auto-linkify at some point anyway.
173
174     // Also write the URL to the clipboard as text so that it can be pasted
175     // into text fields. We use WriteText instead of WriteURL because we don't
176     // want to clobber the X clipboard when the user copies out of the omnibox
177     // on Linux (on Windows and Mac, there is no difference between these
178     // functions).
179     scw.WriteText(base::UTF8ToUTF16(url));
180   } else {
181     // We have either more than one URL, a folder, or a combination of URLs
182     // and folders.
183     base::string16 text;
184     for (size_t i = 0; i < elements.size(); i++) {
185       text += i == 0 ? base::ASCIIToUTF16("") : base::ASCIIToUTF16("\n");
186       if (!elements[i].is_url) {
187         // Then it's a folder. Only copy the name of the folder.
188         const base::string16 title = elements[i].title;
189         text += title;
190       } else {
191         const base::string16 url = base::UTF8ToUTF16(elements[i].url.spec());
192         text += url;
193       }
194     }
195     scw.WriteText(text);
196   }
197
198   Pickle pickle;
199   WriteToPickle(base::FilePath(), &pickle);
200   scw.WritePickledData(pickle,
201                        ui::Clipboard::GetFormatType(kClipboardFormatString));
202 }
203
204 bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
205   DCHECK_EQ(type, ui::CLIPBOARD_TYPE_COPY_PASTE);
206   std::string data;
207   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
208   clipboard->ReadData(ui::Clipboard::GetFormatType(kClipboardFormatString),
209                       &data);
210
211   if (!data.empty()) {
212     Pickle pickle(data.data(), static_cast<int>(data.size()));
213     if (ReadFromPickle(&pickle))
214       return true;
215   }
216
217   base::string16 title;
218   std::string url;
219   clipboard->ReadBookmark(&title, &url);
220   if (!url.empty()) {
221     Element element;
222     element.is_url = true;
223     element.url = GURL(url);
224     element.title = title;
225
226     elements.clear();
227     elements.push_back(element);
228     return true;
229   }
230
231   return false;
232 }
233 #endif
234
235 void BookmarkNodeData::WriteToPickle(const base::FilePath& profile_path,
236                                      Pickle* pickle) const {
237   profile_path.WriteToPickle(pickle);
238   pickle->WriteSizeT(elements.size());
239
240   for (size_t i = 0; i < elements.size(); ++i)
241     elements[i].WriteToPickle(pickle);
242 }
243
244 bool BookmarkNodeData::ReadFromPickle(Pickle* pickle) {
245   PickleIterator data_iterator(*pickle);
246   size_t element_count;
247   if (profile_path_.ReadFromPickle(&data_iterator) &&
248       pickle->ReadSizeT(&data_iterator, &element_count)) {
249     std::vector<Element> tmp_elements;
250     tmp_elements.resize(element_count);
251     for (size_t i = 0; i < element_count; ++i) {
252       if (!tmp_elements[i].ReadFromPickle(pickle, &data_iterator)) {
253         return false;
254       }
255     }
256     elements.swap(tmp_elements);
257   }
258
259   return true;
260 }
261
262 std::vector<const BookmarkNode*> BookmarkNodeData::GetNodes(
263     BookmarkModel* model,
264     const base::FilePath& profile_path) const {
265   std::vector<const BookmarkNode*> nodes;
266
267   if (!IsFromProfilePath(profile_path))
268     return nodes;
269
270   for (size_t i = 0; i < elements.size(); ++i) {
271     const BookmarkNode* node = GetBookmarkNodeByID(model, elements[i].id_);
272     if (!node) {
273       nodes.clear();
274       return nodes;
275     }
276     nodes.push_back(node);
277   }
278   return nodes;
279 }
280
281 const BookmarkNode* BookmarkNodeData::GetFirstNode(
282     BookmarkModel* model,
283     const base::FilePath& profile_path) const {
284   std::vector<const BookmarkNode*> nodes = GetNodes(model, profile_path);
285   return nodes.size() == 1 ? nodes[0] : NULL;
286 }
287
288 void BookmarkNodeData::Clear() {
289   profile_path_.clear();
290   elements.clear();
291 }
292
293 void BookmarkNodeData::SetOriginatingProfilePath(
294     const base::FilePath& profile_path) {
295   DCHECK(profile_path_.empty());
296   profile_path_ = profile_path;
297 }
298
299 bool BookmarkNodeData::IsFromProfilePath(
300     const base::FilePath& profile_path) const {
301   // An empty path means the data is not associated with any profile.
302   return !profile_path_.empty() && profile_path_ == profile_path;
303 }
304
305 }  // namespace bookmarks