| OLD | NEW |
| (Empty) |
| 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/core/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/core/browser/bookmark_utils.h" | |
| 14 #include "ui/base/clipboard/scoped_clipboard_writer.h" | |
| 15 | |
| 16 const char* BookmarkNodeData::kClipboardFormatString = | |
| 17 "chromium/x-bookmark-entries"; | |
| 18 | |
| 19 BookmarkNodeData::Element::Element() : is_url(false), id_(0) { | |
| 20 } | |
| 21 | |
| 22 BookmarkNodeData::Element::Element(const BookmarkNode* node) | |
| 23 : is_url(node->is_url()), | |
| 24 url(node->url()), | |
| 25 title(node->GetTitle()), | |
| 26 date_added(node->date_added()), | |
| 27 date_folder_modified(node->date_folder_modified()), | |
| 28 id_(node->id()) { | |
| 29 if (node->GetMetaInfoMap()) | |
| 30 meta_info_map = *node->GetMetaInfoMap(); | |
| 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 pickle->WriteUInt64(meta_info_map.size()); | |
| 44 for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin(); | |
| 45 it != meta_info_map.end(); ++it) { | |
| 46 pickle->WriteString(it->first); | |
| 47 pickle->WriteString(it->second); | |
| 48 } | |
| 49 if (!is_url) { | |
| 50 pickle->WriteUInt64(children.size()); | |
| 51 for (std::vector<Element>::const_iterator i = children.begin(); | |
| 52 i != children.end(); ++i) { | |
| 53 i->WriteToPickle(pickle); | |
| 54 } | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 bool BookmarkNodeData::Element::ReadFromPickle(Pickle* pickle, | |
| 59 PickleIterator* iterator) { | |
| 60 std::string url_spec; | |
| 61 if (!pickle->ReadBool(iterator, &is_url) || | |
| 62 !pickle->ReadString(iterator, &url_spec) || | |
| 63 !pickle->ReadString16(iterator, &title) || | |
| 64 !pickle->ReadInt64(iterator, &id_)) { | |
| 65 return false; | |
| 66 } | |
| 67 url = GURL(url_spec); | |
| 68 date_added = base::Time(); | |
| 69 date_folder_modified = base::Time(); | |
| 70 meta_info_map.clear(); | |
| 71 uint64 meta_field_count; | |
| 72 if (!pickle->ReadUInt64(iterator, &meta_field_count)) | |
| 73 return false; | |
| 74 for (uint64 i = 0; i < meta_field_count; ++i) { | |
| 75 std::string key; | |
| 76 std::string value; | |
| 77 if (!pickle->ReadString(iterator, &key) || | |
| 78 !pickle->ReadString(iterator, &value)) { | |
| 79 return false; | |
| 80 } | |
| 81 meta_info_map[key] = value; | |
| 82 } | |
| 83 children.clear(); | |
| 84 if (!is_url) { | |
| 85 uint64 children_count; | |
| 86 if (!pickle->ReadUInt64(iterator, &children_count)) | |
| 87 return false; | |
| 88 children.reserve(children_count); | |
| 89 for (uint64 i = 0; i < children_count; ++i) { | |
| 90 children.push_back(Element()); | |
| 91 if (!children.back().ReadFromPickle(pickle, iterator)) | |
| 92 return false; | |
| 93 } | |
| 94 } | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 // BookmarkNodeData ----------------------------------------------------------- | |
| 99 | |
| 100 BookmarkNodeData::BookmarkNodeData() { | |
| 101 } | |
| 102 | |
| 103 BookmarkNodeData::BookmarkNodeData(const BookmarkNode* node) { | |
| 104 elements.push_back(Element(node)); | |
| 105 } | |
| 106 | |
| 107 BookmarkNodeData::BookmarkNodeData( | |
| 108 const std::vector<const BookmarkNode*>& nodes) { | |
| 109 ReadFromVector(nodes); | |
| 110 } | |
| 111 | |
| 112 BookmarkNodeData::~BookmarkNodeData() { | |
| 113 } | |
| 114 | |
| 115 #if !defined(OS_MACOSX) | |
| 116 // static | |
| 117 bool BookmarkNodeData::ClipboardContainsBookmarks() { | |
| 118 return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable( | |
| 119 ui::Clipboard::GetFormatType(kClipboardFormatString), | |
| 120 ui::CLIPBOARD_TYPE_COPY_PASTE); | |
| 121 } | |
| 122 #endif | |
| 123 | |
| 124 bool BookmarkNodeData::ReadFromVector( | |
| 125 const std::vector<const BookmarkNode*>& nodes) { | |
| 126 Clear(); | |
| 127 | |
| 128 if (nodes.empty()) | |
| 129 return false; | |
| 130 | |
| 131 for (size_t i = 0; i < nodes.size(); ++i) | |
| 132 elements.push_back(Element(nodes[i])); | |
| 133 | |
| 134 return true; | |
| 135 } | |
| 136 | |
| 137 bool BookmarkNodeData::ReadFromTuple(const GURL& url, const base::string16& titl
e) { | |
| 138 Clear(); | |
| 139 | |
| 140 if (!url.is_valid()) | |
| 141 return false; | |
| 142 | |
| 143 Element element; | |
| 144 element.title = title; | |
| 145 element.url = url; | |
| 146 element.is_url = true; | |
| 147 | |
| 148 elements.push_back(element); | |
| 149 | |
| 150 return true; | |
| 151 } | |
| 152 | |
| 153 #if !defined(OS_MACOSX) | |
| 154 void BookmarkNodeData::WriteToClipboard(ui::ClipboardType clipboard_type) { | |
| 155 DCHECK(clipboard_type == ui::CLIPBOARD_TYPE_COPY_PASTE || | |
| 156 clipboard_type == ui::CLIPBOARD_TYPE_SELECTION); | |
| 157 ui::ScopedClipboardWriter scw(ui::Clipboard::GetForCurrentThread(), | |
| 158 clipboard_type); | |
| 159 | |
| 160 // If there is only one element and it is a URL, write the URL to the | |
| 161 // clipboard. | |
| 162 if (elements.size() == 1 && elements[0].is_url) { | |
| 163 const base::string16& title = elements[0].title; | |
| 164 const std::string url = elements[0].url.spec(); | |
| 165 | |
| 166 scw.WriteBookmark(title, url); | |
| 167 | |
| 168 // Don't call scw.WriteHyperlink() here, since some rich text editors will | |
| 169 // change fonts when such data is pasted in; besides, most such editors | |
| 170 // auto-linkify at some point anyway. | |
| 171 | |
| 172 // Also write the URL to the clipboard as text so that it can be pasted | |
| 173 // into text fields. We use WriteText instead of WriteURL because we don't | |
| 174 // want to clobber the X clipboard when the user copies out of the omnibox | |
| 175 // on Linux (on Windows and Mac, there is no difference between these | |
| 176 // functions). | |
| 177 scw.WriteText(base::UTF8ToUTF16(url)); | |
| 178 } | |
| 179 | |
| 180 Pickle pickle; | |
| 181 WriteToPickle(base::FilePath(), &pickle); | |
| 182 scw.WritePickledData(pickle, | |
| 183 ui::Clipboard::GetFormatType(kClipboardFormatString)); | |
| 184 } | |
| 185 | |
| 186 bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) { | |
| 187 DCHECK_EQ(type, ui::CLIPBOARD_TYPE_COPY_PASTE); | |
| 188 std::string data; | |
| 189 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); | |
| 190 clipboard->ReadData(ui::Clipboard::GetFormatType(kClipboardFormatString), | |
| 191 &data); | |
| 192 | |
| 193 if (!data.empty()) { | |
| 194 Pickle pickle(data.data(), static_cast<int>(data.size())); | |
| 195 if (ReadFromPickle(&pickle)) | |
| 196 return true; | |
| 197 } | |
| 198 | |
| 199 base::string16 title; | |
| 200 std::string url; | |
| 201 clipboard->ReadBookmark(&title, &url); | |
| 202 if (!url.empty()) { | |
| 203 Element element; | |
| 204 element.is_url = true; | |
| 205 element.url = GURL(url); | |
| 206 element.title = title; | |
| 207 | |
| 208 elements.clear(); | |
| 209 elements.push_back(element); | |
| 210 return true; | |
| 211 } | |
| 212 | |
| 213 return false; | |
| 214 } | |
| 215 #endif | |
| 216 | |
| 217 void BookmarkNodeData::WriteToPickle(const base::FilePath& profile_path, | |
| 218 Pickle* pickle) const { | |
| 219 profile_path.WriteToPickle(pickle); | |
| 220 pickle->WriteUInt64(elements.size()); | |
| 221 | |
| 222 for (size_t i = 0; i < elements.size(); ++i) | |
| 223 elements[i].WriteToPickle(pickle); | |
| 224 } | |
| 225 | |
| 226 bool BookmarkNodeData::ReadFromPickle(Pickle* pickle) { | |
| 227 PickleIterator data_iterator(*pickle); | |
| 228 uint64 element_count; | |
| 229 if (profile_path_.ReadFromPickle(&data_iterator) && | |
| 230 pickle->ReadUInt64(&data_iterator, &element_count)) { | |
| 231 std::vector<Element> tmp_elements; | |
| 232 tmp_elements.resize(element_count); | |
| 233 for (uint64 i = 0; i < element_count; ++i) { | |
| 234 if (!tmp_elements[i].ReadFromPickle(pickle, &data_iterator)) { | |
| 235 return false; | |
| 236 } | |
| 237 } | |
| 238 elements.swap(tmp_elements); | |
| 239 } | |
| 240 | |
| 241 return true; | |
| 242 } | |
| 243 | |
| 244 std::vector<const BookmarkNode*> BookmarkNodeData::GetNodes( | |
| 245 BookmarkModel* model, | |
| 246 const base::FilePath& profile_path) const { | |
| 247 std::vector<const BookmarkNode*> nodes; | |
| 248 | |
| 249 if (!IsFromProfilePath(profile_path)) | |
| 250 return nodes; | |
| 251 | |
| 252 for (size_t i = 0; i < elements.size(); ++i) { | |
| 253 const BookmarkNode* node = GetBookmarkNodeByID(model, elements[i].id_); | |
| 254 if (!node) { | |
| 255 nodes.clear(); | |
| 256 return nodes; | |
| 257 } | |
| 258 nodes.push_back(node); | |
| 259 } | |
| 260 return nodes; | |
| 261 } | |
| 262 | |
| 263 const BookmarkNode* BookmarkNodeData::GetFirstNode( | |
| 264 BookmarkModel* model, | |
| 265 const base::FilePath& profile_path) const { | |
| 266 std::vector<const BookmarkNode*> nodes = GetNodes(model, profile_path); | |
| 267 return nodes.size() == 1 ? nodes[0] : NULL; | |
| 268 } | |
| 269 | |
| 270 void BookmarkNodeData::Clear() { | |
| 271 profile_path_.clear(); | |
| 272 elements.clear(); | |
| 273 } | |
| 274 | |
| 275 void BookmarkNodeData::SetOriginatingProfilePath( | |
| 276 const base::FilePath& profile_path) { | |
| 277 DCHECK(profile_path_.empty()); | |
| 278 profile_path_ = profile_path; | |
| 279 } | |
| 280 | |
| 281 bool BookmarkNodeData::IsFromProfilePath( | |
| 282 const base::FilePath& profile_path) const { | |
| 283 // An empty path means the data is not associated with any profile. | |
| 284 return !profile_path_.empty() && profile_path_ == profile_path; | |
| 285 } | |
| OLD | NEW |