blob: 2e7285a87f366ed7b1c17b9caa087e3b18089624 [file] [log] [blame]
// 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<Element>::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<Element>::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<BookmarkNode*>& 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() : 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<Element> 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<BookmarkNode*> BookmarkDragData::GetNodes(Profile* profile) const {
std::vector<BookmarkNode*> 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<BookmarkNode*> 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() == profile_path_);
}