- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / bookmarks / bookmark_node_data.cc
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.
4
5 #include "chrome/browser/bookmarks/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 "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"
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   for (int i = 0; i < node->child_count(); ++i)
32     children.push_back(Element(node->GetChild(i)));
33 }
34
35 BookmarkNodeData::Element::~Element() {
36 }
37
38 void BookmarkNodeData::Element::WriteToPickle(Pickle* pickle) const {
39   pickle->WriteBool(is_url);
40   pickle->WriteString(url.spec());
41   pickle->WriteString16(title);
42   pickle->WriteInt64(id_);
43   if (!is_url) {
44     pickle->WriteUInt64(children.size());
45     for (std::vector<Element>::const_iterator i = children.begin();
46          i != children.end(); ++i) {
47       i->WriteToPickle(pickle);
48     }
49   }
50 }
51
52 bool BookmarkNodeData::Element::ReadFromPickle(Pickle* pickle,
53                                                PickleIterator* iterator) {
54   std::string url_spec;
55   if (!pickle->ReadBool(iterator, &is_url) ||
56       !pickle->ReadString(iterator, &url_spec) ||
57       !pickle->ReadString16(iterator, &title) ||
58       !pickle->ReadInt64(iterator, &id_)) {
59     return false;
60   }
61   url = GURL(url_spec);
62   date_added = base::Time();
63   date_folder_modified = base::Time();
64   children.clear();
65   if (!is_url) {
66     uint64 children_count;
67     if (!pickle->ReadUInt64(iterator, &children_count))
68       return false;
69     children.reserve(children_count);
70     for (uint64 i = 0; i < children_count; ++i) {
71       children.push_back(Element());
72       if (!children.back().ReadFromPickle(pickle, iterator))
73         return false;
74     }
75   }
76   return true;
77 }
78
79 // BookmarkNodeData -----------------------------------------------------------
80
81 BookmarkNodeData::BookmarkNodeData() {
82 }
83
84 BookmarkNodeData::BookmarkNodeData(const BookmarkNode* node) {
85   elements.push_back(Element(node));
86 }
87
88 BookmarkNodeData::BookmarkNodeData(
89     const std::vector<const BookmarkNode*>& nodes) {
90   ReadFromVector(nodes);
91 }
92
93 BookmarkNodeData::~BookmarkNodeData() {
94 }
95
96 #if !defined(OS_MACOSX)
97 // static
98 bool BookmarkNodeData::ClipboardContainsBookmarks() {
99   return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
100       ui::Clipboard::GetFormatType(kClipboardFormatString),
101       ui::CLIPBOARD_TYPE_COPY_PASTE);
102 }
103 #endif
104
105 bool BookmarkNodeData::ReadFromVector(
106     const std::vector<const BookmarkNode*>& nodes) {
107   Clear();
108
109   if (nodes.empty())
110     return false;
111
112   for (size_t i = 0; i < nodes.size(); ++i)
113     elements.push_back(Element(nodes[i]));
114
115   return true;
116 }
117
118 bool BookmarkNodeData::ReadFromTuple(const GURL& url, const string16& title) {
119   Clear();
120
121   if (!url.is_valid())
122     return false;
123
124   Element element;
125   element.title = title;
126   element.url = url;
127   element.is_url = true;
128
129   elements.push_back(element);
130
131   return true;
132 }
133
134 #if !defined(OS_MACOSX)
135 void BookmarkNodeData::WriteToClipboard(ui::ClipboardType type) {
136   DCHECK_EQ(type, ui::CLIPBOARD_TYPE_COPY_PASTE);
137   ui::ScopedClipboardWriter scw(ui::Clipboard::GetForCurrentThread(),
138                                 ui::CLIPBOARD_TYPE_COPY_PASTE);
139
140   // If there is only one element and it is a URL, write the URL to the
141   // clipboard.
142   if (elements.size() == 1 && elements[0].is_url) {
143     const string16& title = elements[0].title;
144     const std::string url = elements[0].url.spec();
145
146     scw.WriteBookmark(title, url);
147
148     // Don't call scw.WriteHyperlink() here, since some rich text editors will
149     // change fonts when such data is pasted in; besides, most such editors
150     // auto-linkify at some point anyway.
151
152     // Also write the URL to the clipboard as text so that it can be pasted
153     // into text fields. We use WriteText instead of WriteURL because we don't
154     // want to clobber the X clipboard when the user copies out of the omnibox
155     // on Linux (on Windows and Mac, there is no difference between these
156     // functions).
157     scw.WriteText(UTF8ToUTF16(url));
158   }
159
160   Pickle pickle;
161   WriteToPickle(NULL, &pickle);
162   scw.WritePickledData(pickle,
163                        ui::Clipboard::GetFormatType(kClipboardFormatString));
164 }
165
166 bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
167   DCHECK_EQ(type, ui::CLIPBOARD_TYPE_COPY_PASTE);
168   std::string data;
169   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
170   clipboard->ReadData(ui::Clipboard::GetFormatType(kClipboardFormatString),
171                       &data);
172
173   if (!data.empty()) {
174     Pickle pickle(data.data(), data.size());
175     if (ReadFromPickle(&pickle))
176       return true;
177   }
178
179   string16 title;
180   std::string url;
181   clipboard->ReadBookmark(&title, &url);
182   if (!url.empty()) {
183     Element element;
184     element.is_url = true;
185     element.url = GURL(url);
186     element.title = title;
187
188     elements.clear();
189     elements.push_back(element);
190     return true;
191   }
192
193   return false;
194 }
195 #endif
196
197 void BookmarkNodeData::WriteToPickle(Profile* profile, Pickle* pickle) const {
198   base::FilePath path = profile ? profile->GetPath() : base::FilePath();
199   path.WriteToPickle(pickle);
200   pickle->WriteUInt64(elements.size());
201
202   for (size_t i = 0; i < elements.size(); ++i)
203     elements[i].WriteToPickle(pickle);
204 }
205
206 bool BookmarkNodeData::ReadFromPickle(Pickle* pickle) {
207   PickleIterator data_iterator(*pickle);
208   uint64 element_count;
209   if (profile_path_.ReadFromPickle(&data_iterator) &&
210       pickle->ReadUInt64(&data_iterator, &element_count)) {
211     std::vector<Element> tmp_elements;
212     tmp_elements.resize(element_count);
213     for (uint64 i = 0; i < element_count; ++i) {
214       if (!tmp_elements[i].ReadFromPickle(pickle, &data_iterator)) {
215         return false;
216       }
217     }
218     elements.swap(tmp_elements);
219   }
220
221   return true;
222 }
223
224 std::vector<const BookmarkNode*> BookmarkNodeData::GetNodes(
225     Profile* profile) const {
226   std::vector<const BookmarkNode*> nodes;
227
228   if (!IsFromProfile(profile))
229     return nodes;
230
231   for (size_t i = 0; i < elements.size(); ++i) {
232     const BookmarkNode* node = BookmarkModelFactory::GetForProfile(
233         profile)->GetNodeByID(elements[i].id_);
234     if (!node) {
235       nodes.clear();
236       return nodes;
237     }
238     nodes.push_back(node);
239   }
240   return nodes;
241 }
242
243 const BookmarkNode* BookmarkNodeData::GetFirstNode(Profile* profile) const {
244   std::vector<const BookmarkNode*> nodes = GetNodes(profile);
245   return nodes.size() == 1 ? nodes[0] : NULL;
246 }
247
248 void BookmarkNodeData::Clear() {
249   profile_path_.clear();
250   elements.clear();
251 }
252
253 void BookmarkNodeData::SetOriginatingProfile(Profile* profile) {
254   DCHECK(profile_path_.empty());
255
256   if (profile)
257     profile_path_ = profile->GetPath();
258 }
259
260 bool BookmarkNodeData::IsFromProfile(Profile* profile) const {
261   // An empty path means the data is not associated with any profile.
262   return !profile_path_.empty() && profile_path_ == profile->GetPath();
263 }