// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "base/pickle.h" #include "base/string_util.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/profile.h" #include "chrome/common/os_exchange_data.h" static CLIPFORMAT clipboard_format = 0; static void RegisterFormat() { if (clipboard_format == 0) { clipboard_format = RegisterClipboardFormat(L"chrome/x-bookmark-entries"); DCHECK(clipboard_format); } } BookmarkDragData::Element::Element(BookmarkNode* node) : is_url(node->is_url()), url(node->GetURL()), title(node->GetTitle()), id_(node->id()) { for (int i = 0; i < node->GetChildCount(); ++i) children.push_back(Element(node->GetChild(i))); } void BookmarkDragData::Element::WriteToPickle(Pickle* pickle) const { pickle->WriteBool(is_url); pickle->WriteString(url.spec()); pickle->WriteWString(title); pickle->WriteInt(id_); if (!is_url) { pickle->WriteSize(children.size()); for (std::vector::const_iterator i = children.begin(); i != children.end(); ++i) { i->WriteToPickle(pickle); } } } bool BookmarkDragData::Element::ReadFromPickle(Pickle* pickle, void** iterator) { std::string url_spec; if (!pickle->ReadBool(iterator, &is_url) || !pickle->ReadString(iterator, &url_spec) || !pickle->ReadWString(iterator, &title) || !pickle->ReadInt(iterator, &id_)) { return false; } url = GURL(url_spec); children.clear(); if (!is_url) { size_t children_count; if (!pickle->ReadSize(iterator, &children_count)) return false; children.resize(children_count); for (std::vector::iterator i = children.begin(); i != children.end(); ++i) { if (!i->ReadFromPickle(pickle, iterator)) return false; } } return true; } BookmarkDragData::BookmarkDragData(BookmarkNode* node) { elements.push_back(Element(node)); } BookmarkDragData::BookmarkDragData(const std::vector& nodes) { for (size_t i = 0; i < nodes.size(); ++i) elements.push_back(Element(nodes[i])); } void BookmarkDragData::Write(Profile* profile, OSExchangeData* data) const { RegisterFormat(); DCHECK(data); // If there is only one element and it is a URL, write the URL to the // clipboard. if (elements.size() == 1 && elements[0].is_url) { if (elements[0].url.SchemeIs("javascript")) { data->SetString(ASCIIToWide(elements[0].url.spec())); } else { data->SetURL(elements[0].url, elements[0].title); } } Pickle data_pickle; data_pickle.WriteWString( profile ? profile->GetPath().ToWStringHack() : std::wstring()); data_pickle.WriteSize(elements.size()); for (size_t i = 0; i < elements.size(); ++i) elements[i].WriteToPickle(&data_pickle); data->SetPickledData(clipboard_format, data_pickle); } bool BookmarkDragData::Read(const OSExchangeData& data) { RegisterFormat(); elements.clear(); profile_path_.clear(); if (data.HasFormat(clipboard_format)) { Pickle drag_data_pickle; if (data.GetPickledData(clipboard_format, &drag_data_pickle)) { void* data_iterator = NULL; size_t element_count; if (drag_data_pickle.ReadWString(&data_iterator, &profile_path_) && drag_data_pickle.ReadSize(&data_iterator, &element_count)) { std::vector tmp_elements; tmp_elements.resize(element_count); for (size_t i = 0; i < element_count; ++i) { if (!tmp_elements[i].ReadFromPickle(&drag_data_pickle, &data_iterator)) { return false; } } elements.swap(tmp_elements); } } } else { // See if there is a URL on the clipboard. Element element; if (data.GetURLAndTitle(&element.url, &element.title) && element.url.is_valid()) { element.is_url = true; elements.push_back(element); } } return is_valid(); } std::vector BookmarkDragData::GetNodes(Profile* profile) const { std::vector nodes; if (!IsFromProfile(profile)) return nodes; for (size_t i = 0; i < elements.size(); ++i) { BookmarkNode* node = profile->GetBookmarkModel()->GetNodeByID(elements[i].id_); if (!node) { nodes.clear(); return nodes; } nodes.push_back(node); } return nodes; } BookmarkNode* BookmarkDragData::GetFirstNode(Profile* profile) const { std::vector nodes = GetNodes(profile); return nodes.size() == 1 ? nodes[0] : NULL; } bool BookmarkDragData::IsFromProfile(Profile* profile) const { // An empty path means the data is not associated with any profile. return (!profile_path_.empty() && profile->GetPath().ToWStringHack() == profile_path_); }