blob: 22d35500df1d9955fe0e933468ec25e642949f57 [file] [log] [blame]
// Copyright (c) 2012 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/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/lazy_instance.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
#include "chrome/browser/extensions/extension_web_ui.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
#include "chrome/browser/undo/bookmark_undo_service_factory.h"
#include "chrome/common/extensions/api/bookmark_manager_private.h"
#include "chrome/grit/generated_resources.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
#include "components/bookmarks/browser/bookmark_utils.h"
#include "components/bookmarks/browser/scoped_group_bookmark_actions.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/bookmarks/managed/managed_bookmark_service.h"
#include "components/prefs/pref_service.h"
#include "components/undo/bookmark_undo_service.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/browser/view_type_utils.h"
#include "grit/components_strings.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
using bookmarks::BookmarkModel;
using bookmarks::BookmarkNode;
using bookmarks::BookmarkNodeData;
using content::WebContents;
namespace extensions {
namespace bookmark_keys = bookmark_api_constants;
namespace bookmark_manager_private = api::bookmark_manager_private;
namespace CanPaste = api::bookmark_manager_private::CanPaste;
namespace Copy = api::bookmark_manager_private::Copy;
namespace CreateWithMetaInfo =
api::bookmark_manager_private::CreateWithMetaInfo;
namespace Cut = api::bookmark_manager_private::Cut;
namespace Drop = api::bookmark_manager_private::Drop;
namespace GetSubtree = api::bookmark_manager_private::GetSubtree;
namespace GetMetaInfo = api::bookmark_manager_private::GetMetaInfo;
namespace Paste = api::bookmark_manager_private::Paste;
namespace RedoInfo = api::bookmark_manager_private::GetRedoInfo;
namespace RemoveTrees = api::bookmark_manager_private::RemoveTrees;
namespace SetMetaInfo = api::bookmark_manager_private::SetMetaInfo;
namespace SortChildren = api::bookmark_manager_private::SortChildren;
namespace StartDrag = api::bookmark_manager_private::StartDrag;
namespace UndoInfo = api::bookmark_manager_private::GetUndoInfo;
namespace UpdateMetaInfo = api::bookmark_manager_private::UpdateMetaInfo;
namespace {
// Returns a single bookmark node from the argument ID.
// This returns NULL in case of failure.
const BookmarkNode* GetNodeFromString(BookmarkModel* model,
const std::string& id_string) {
int64_t id;
if (!base::StringToInt64(id_string, &id))
return NULL;
return bookmarks::GetBookmarkNodeByID(model, id);
}
// Gets a vector of bookmark nodes from the argument list of IDs.
// This returns false in the case of failure.
bool GetNodesFromVector(BookmarkModel* model,
const std::vector<std::string>& id_strings,
std::vector<const BookmarkNode*>* nodes) {
if (id_strings.empty())
return false;
for (size_t i = 0; i < id_strings.size(); ++i) {
const BookmarkNode* node = GetNodeFromString(model, id_strings[i]);
if (!node)
return false;
nodes->push_back(node);
}
return true;
}
// Recursively create a bookmark_manager_private::BookmarkNodeDataElement from
// a bookmark node. This is by used |BookmarkNodeDataToJSON| when the data comes
// from the current profile. In this case we have a BookmarkNode since we got
// the data from the current profile.
bookmark_manager_private::BookmarkNodeDataElement
CreateNodeDataElementFromBookmarkNode(const BookmarkNode& node) {
bookmark_manager_private::BookmarkNodeDataElement element;
// Add id and parentId so we can associate the data with existing nodes on the
// client side.
element.id.reset(new std::string(base::Int64ToString(node.id())));
element.parent_id.reset(
new std::string(base::Int64ToString(node.parent()->id())));
if (node.is_url())
element.url.reset(new std::string(node.url().spec()));
element.title = base::UTF16ToUTF8(node.GetTitle());
for (int i = 0; i < node.child_count(); ++i) {
element.children.push_back(
CreateNodeDataElementFromBookmarkNode(*node.GetChild(i)));
}
return element;
}
// Recursively create a bookmark_manager_private::BookmarkNodeDataElement from
// a BookmarkNodeData::Element. This is used by |BookmarkNodeDataToJSON| when
// the data comes from a different profile. When the data comes from a different
// profile we do not have any IDs or parent IDs.
bookmark_manager_private::BookmarkNodeDataElement CreateApiNodeDataElement(
const BookmarkNodeData::Element& element) {
bookmark_manager_private::BookmarkNodeDataElement node_element;
if (element.is_url)
node_element.url.reset(new std::string(element.url.spec()));
node_element.title = base::UTF16ToUTF8(element.title);
for (size_t i = 0; i < element.children.size(); ++i) {
node_element.children.push_back(
CreateApiNodeDataElement(element.children[i]));
}
return node_element;
}
// Creates a bookmark_manager_private::BookmarkNodeData from a BookmarkNodeData.
bookmark_manager_private::BookmarkNodeData CreateApiBookmarkNodeData(
Profile* profile,
const BookmarkNodeData& data) {
const base::FilePath& profile_path = profile->GetPath();
bookmark_manager_private::BookmarkNodeData node_data;
node_data.same_profile = data.IsFromProfilePath(profile_path);
if (node_data.same_profile) {
std::vector<const BookmarkNode*> nodes = data.GetNodes(
BookmarkModelFactory::GetForProfile(profile), profile_path);
for (size_t i = 0; i < nodes.size(); ++i) {
node_data.elements.push_back(
CreateNodeDataElementFromBookmarkNode(*nodes[i]));
}
} else {
// We do not have a node IDs when the data comes from a different profile.
for (size_t i = 0; i < data.size(); ++i)
node_data.elements.push_back(CreateApiNodeDataElement(data.elements[i]));
}
return node_data;
}
} // namespace
BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter(
content::BrowserContext* browser_context,
BookmarkModel* bookmark_model)
: browser_context_(browser_context), bookmark_model_(bookmark_model) {
bookmark_model_->AddObserver(this);
}
BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() {
if (bookmark_model_)
bookmark_model_->RemoveObserver(this);
}
void BookmarkManagerPrivateEventRouter::DispatchEvent(
events::HistogramValue histogram_value,
const std::string& event_name,
std::unique_ptr<base::ListValue> event_args) {
EventRouter::Get(browser_context_)
->BroadcastEvent(base::WrapUnique(
new Event(histogram_value, event_name, std::move(event_args))));
}
void BookmarkManagerPrivateEventRouter::BookmarkModelChanged() {}
void BookmarkManagerPrivateEventRouter::BookmarkModelBeingDeleted(
BookmarkModel* model) {
bookmark_model_ = NULL;
}
void BookmarkManagerPrivateEventRouter::OnWillChangeBookmarkMetaInfo(
BookmarkModel* model,
const BookmarkNode* node) {
DCHECK(prev_meta_info_.empty());
if (node->GetMetaInfoMap())
prev_meta_info_ = *node->GetMetaInfoMap();
}
void BookmarkManagerPrivateEventRouter::BookmarkMetaInfoChanged(
BookmarkModel* model,
const BookmarkNode* node) {
const BookmarkNode::MetaInfoMap* new_meta_info = node->GetMetaInfoMap();
bookmark_manager_private::MetaInfoFields changes;
// Identify changed/removed fields:
for (BookmarkNode::MetaInfoMap::const_iterator it = prev_meta_info_.begin();
it != prev_meta_info_.end();
++it) {
if (!new_meta_info) {
changes.additional_properties[it->first] = "";
} else {
BookmarkNode::MetaInfoMap::const_iterator new_meta_field =
new_meta_info->find(it->first);
if (new_meta_field == new_meta_info->end()) {
changes.additional_properties[it->first] = "";
} else if (it->second != new_meta_field->second) {
changes.additional_properties[it->first] = new_meta_field->second;
}
}
}
// Identify added fields:
if (new_meta_info) {
for (BookmarkNode::MetaInfoMap::const_iterator it = new_meta_info->begin();
it != new_meta_info->end();
++it) {
BookmarkNode::MetaInfoMap::const_iterator prev_meta_field =
prev_meta_info_.find(it->first);
if (prev_meta_field == prev_meta_info_.end())
changes.additional_properties[it->first] = it->second;
}
}
prev_meta_info_.clear();
DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_META_INFO_CHANGED,
bookmark_manager_private::OnMetaInfoChanged::kEventName,
bookmark_manager_private::OnMetaInfoChanged::Create(
base::Int64ToString(node->id()), changes));
}
BookmarkManagerPrivateAPI::BookmarkManagerPrivateAPI(
content::BrowserContext* browser_context)
: browser_context_(browser_context) {
EventRouter* event_router = EventRouter::Get(browser_context);
event_router->RegisterObserver(
this, bookmark_manager_private::OnMetaInfoChanged::kEventName);
}
BookmarkManagerPrivateAPI::~BookmarkManagerPrivateAPI() {}
void BookmarkManagerPrivateAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
static base::LazyInstance<
BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI> > g_factory =
LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI>*
BookmarkManagerPrivateAPI::GetFactoryInstance() {
return g_factory.Pointer();
}
void BookmarkManagerPrivateAPI::OnListenerAdded(
const EventListenerInfo& details) {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
event_router_.reset(new BookmarkManagerPrivateEventRouter(
browser_context_,
BookmarkModelFactory::GetForProfile(
Profile::FromBrowserContext(browser_context_))));
}
BookmarkManagerPrivateDragEventRouter::BookmarkManagerPrivateDragEventRouter(
Profile* profile,
content::WebContents* web_contents)
: profile_(profile), web_contents_(web_contents) {
BookmarkTabHelper* bookmark_tab_helper =
BookmarkTabHelper::FromWebContents(web_contents_);
bookmark_tab_helper->set_bookmark_drag_delegate(this);
}
BookmarkManagerPrivateDragEventRouter::
~BookmarkManagerPrivateDragEventRouter() {
BookmarkTabHelper* bookmark_tab_helper =
BookmarkTabHelper::FromWebContents(web_contents_);
if (bookmark_tab_helper->bookmark_drag_delegate() == this)
bookmark_tab_helper->set_bookmark_drag_delegate(NULL);
}
void BookmarkManagerPrivateDragEventRouter::DispatchEvent(
events::HistogramValue histogram_value,
const std::string& event_name,
std::unique_ptr<base::ListValue> args) {
EventRouter* event_router = EventRouter::Get(profile_);
if (!event_router)
return;
std::unique_ptr<Event> event(
new Event(histogram_value, event_name, std::move(args)));
event_router->BroadcastEvent(std::move(event));
}
void BookmarkManagerPrivateDragEventRouter::OnDragEnter(
const BookmarkNodeData& data) {
if (!data.is_valid())
return;
DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DRAG_ENTER,
bookmark_manager_private::OnDragEnter::kEventName,
bookmark_manager_private::OnDragEnter::Create(
CreateApiBookmarkNodeData(profile_, data)));
}
void BookmarkManagerPrivateDragEventRouter::OnDragOver(
const BookmarkNodeData& data) {
// Intentionally empty since these events happens too often and floods the
// message queue. We do not need this event for the bookmark manager anyway.
}
void BookmarkManagerPrivateDragEventRouter::OnDragLeave(
const BookmarkNodeData& data) {
if (!data.is_valid())
return;
DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DRAG_LEAVE,
bookmark_manager_private::OnDragLeave::kEventName,
bookmark_manager_private::OnDragLeave::Create(
CreateApiBookmarkNodeData(profile_, data)));
}
void BookmarkManagerPrivateDragEventRouter::OnDrop(
const BookmarkNodeData& data) {
if (!data.is_valid())
return;
DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DROP,
bookmark_manager_private::OnDrop::kEventName,
bookmark_manager_private::OnDrop::Create(
CreateApiBookmarkNodeData(profile_, data)));
// Make a copy that is owned by this instance.
ClearBookmarkNodeData();
bookmark_drag_data_ = data;
}
const BookmarkNodeData*
BookmarkManagerPrivateDragEventRouter::GetBookmarkNodeData() {
if (bookmark_drag_data_.is_valid())
return &bookmark_drag_data_;
return NULL;
}
void BookmarkManagerPrivateDragEventRouter::ClearBookmarkNodeData() {
bookmark_drag_data_.Clear();
}
bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut,
const std::vector<std::string>& id_list) {
BookmarkModel* model = GetBookmarkModel();
bookmarks::ManagedBookmarkService* managed = GetManagedBookmarkService();
std::vector<const BookmarkNode*> nodes;
EXTENSION_FUNCTION_VALIDATE(GetNodesFromVector(model, id_list, &nodes));
if (cut && bookmarks::HasDescendantsOf(nodes, managed->managed_node())) {
error_ = bookmark_keys::kModifyManagedError;
return false;
}
bookmarks::CopyToClipboard(model, nodes, cut);
return true;
}
bool BookmarkManagerPrivateCopyFunction::RunOnReady() {
std::unique_ptr<Copy::Params> params(Copy::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
return CopyOrCut(false, params->id_list);
}
bool BookmarkManagerPrivateCutFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<Cut::Params> params(Cut::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
return CopyOrCut(true, params->id_list);
}
bool BookmarkManagerPrivatePasteFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<Paste::Params> params(Paste::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
if (!CanBeModified(parent_node))
return false;
bool can_paste = bookmarks::CanPasteFromClipboard(model, parent_node);
if (!can_paste)
return false;
// We want to use the highest index of the selected nodes as a destination.
std::vector<const BookmarkNode*> nodes;
// No need to test return value, if we got an empty list, we insert at end.
if (params->selected_id_list)
GetNodesFromVector(model, *params->selected_id_list, &nodes);
int highest_index = -1; // -1 means insert at end of list.
for (size_t i = 0; i < nodes.size(); ++i) {
// + 1 so that we insert after the selection.
int index = parent_node->GetIndexOf(nodes[i]) + 1;
if (index > highest_index)
highest_index = index;
}
bookmarks::PasteFromClipboard(model, parent_node, highest_index);
return true;
}
bool BookmarkManagerPrivateCanPasteFunction::RunOnReady() {
std::unique_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
if (!prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled)) {
SetResult(base::MakeUnique<base::FundamentalValue>(false));
return true;
}
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
if (!parent_node) {
error_ = bookmark_keys::kNoParentError;
return false;
}
bool can_paste = bookmarks::CanPasteFromClipboard(model, parent_node);
SetResult(base::MakeUnique<base::FundamentalValue>(can_paste));
return true;
}
bool BookmarkManagerPrivateSortChildrenFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<SortChildren::Params> params(
SortChildren::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
if (!CanBeModified(parent_node))
return false;
model->SortChildren(parent_node);
return true;
}
bool BookmarkManagerPrivateGetStringsFunction::RunAsync() {
std::unique_ptr<base::DictionaryValue> localized_strings(
new base::DictionaryValue());
localized_strings->SetString("title",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
localized_strings->SetString("search_button",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
localized_strings->SetString("folders_menu",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_FOLDERS_MENU));
localized_strings->SetString("organize_menu",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
localized_strings->SetString("show_in_folder",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
localized_strings->SetString("sort",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
localized_strings->SetString("import_menu",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
localized_strings->SetString("export_menu",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
localized_strings->SetString("rename_folder",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
localized_strings->SetString("edit",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
localized_strings->SetString("should_open_all",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
localized_strings->SetString("open_incognito",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
localized_strings->SetString("open_in_new_tab",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
localized_strings->SetString("open_in_new_window",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
localized_strings->SetString("add_new_bookmark",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
localized_strings->SetString("new_folder",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
localized_strings->SetString("open_all",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
localized_strings->SetString("open_all_new_window",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
localized_strings->SetString("open_all_incognito",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
localized_strings->SetString("remove",
l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
localized_strings->SetString("copy",
l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
localized_strings->SetString("cut",
l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
localized_strings->SetString("paste",
l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
localized_strings->SetString("delete",
l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
localized_strings->SetString("undo_delete",
l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
localized_strings->SetString("new_folder_name",
l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
localized_strings->SetString("name_input_placeholder",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
localized_strings->SetString("url_input_placeholder",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
localized_strings->SetString("invalid_url",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
localized_strings->SetString("recent",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
localized_strings->SetString("search",
l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
localized_strings->SetString("save",
l10n_util::GetStringUTF16(IDS_SAVE));
localized_strings->SetString("cancel",
l10n_util::GetStringUTF16(IDS_CANCEL));
const std::string& app_locale = g_browser_process->GetApplicationLocale();
webui::SetLoadTimeDataDefaults(app_locale, localized_strings.get());
SetResult(std::move(localized_strings));
// This is needed because unlike the rest of these functions, this class
// inherits from AsyncFunction directly, rather than BookmarkFunction.
SendResponse(true);
return true;
}
bool BookmarkManagerPrivateStartDragFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
if (GetViewType(GetSenderWebContents()) != VIEW_TYPE_TAB_CONTENTS) {
NOTREACHED();
return false;
}
std::unique_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
std::vector<const BookmarkNode*> nodes;
EXTENSION_FUNCTION_VALIDATE(
GetNodesFromVector(model, params->id_list, &nodes));
content::WebContents* web_contents = GetAssociatedWebContents();
CHECK(web_contents);
ui::DragDropTypes::DragEventSource source =
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
if (params->is_from_touch)
source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
chrome::DragBookmarks(
GetProfile(), nodes, web_contents->GetNativeView(), source);
return true;
}
bool BookmarkManagerPrivateDropFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<Drop::Params> params(Drop::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
if (!CanBeModified(drop_parent))
return false;
if (GetViewType(GetSenderWebContents()) != VIEW_TYPE_TAB_CONTENTS) {
NOTREACHED();
return false;
}
int drop_index;
if (params->index)
drop_index = *params->index;
else
drop_index = drop_parent->child_count();
WebContents* web_contents = GetAssociatedWebContents();
CHECK(web_contents);
ExtensionWebUI* web_ui =
static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
CHECK(web_ui);
BookmarkManagerPrivateDragEventRouter* router =
web_ui->bookmark_manager_private_drag_event_router();
DCHECK(router);
const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
if (drag_data == NULL) {
NOTREACHED() <<"Somehow we're dropping null bookmark data";
return false;
}
const bool copy = false;
chrome::DropBookmarks(
GetProfile(), *drag_data, drop_parent, drop_index, copy);
router->ClearBookmarkNodeData();
return true;
}
bool BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() {
std::unique_ptr<GetSubtree::Params> params(
GetSubtree::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
const BookmarkNode* node = NULL;
if (params->id.empty()) {
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
node = model->root_node();
} else {
node = GetBookmarkNodeFromId(params->id);
if (!node)
return false;
}
std::vector<api::bookmarks::BookmarkTreeNode> nodes;
bookmarks::ManagedBookmarkService* managed = GetManagedBookmarkService();
if (params->folders_only)
bookmark_api_helpers::AddNodeFoldersOnly(managed, node, &nodes, true);
else
bookmark_api_helpers::AddNode(managed, node, &nodes, true);
results_ = GetSubtree::Results::Create(nodes);
return true;
}
bool BookmarkManagerPrivateCanEditFunction::RunOnReady() {
PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
SetResult(base::MakeUnique<base::FundamentalValue>(
prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled)));
return true;
}
bool BookmarkManagerPrivateRecordLaunchFunction::RunOnReady() {
RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER);
return true;
}
bool BookmarkManagerPrivateCreateWithMetaInfoFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<CreateWithMetaInfo::Params> params(
CreateWithMetaInfo::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* node = CreateBookmarkNode(
model, params->bookmark, &params->meta_info.additional_properties);
if (!node)
return false;
api::bookmarks::BookmarkTreeNode result_node =
bookmark_api_helpers::GetBookmarkTreeNode(GetManagedBookmarkService(),
node, false, false);
results_ = CreateWithMetaInfo::Results::Create(result_node);
return true;
}
bool BookmarkManagerPrivateGetMetaInfoFunction::RunOnReady() {
std::unique_ptr<GetMetaInfo::Params> params(
GetMetaInfo::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
if (params->id) {
const BookmarkNode* node = GetBookmarkNodeFromId(*params->id);
if (!node)
return false;
if (params->key) {
std::string value;
if (node->GetMetaInfo(*params->key, &value)) {
GetMetaInfo::Results::Value result;
result.as_string.reset(new std::string(value));
results_ = GetMetaInfo::Results::Create(result);
}
} else {
GetMetaInfo::Results::Value result;
result.as_object.reset(new GetMetaInfo::Results::Value::Object);
const BookmarkNode::MetaInfoMap* meta_info = node->GetMetaInfoMap();
if (meta_info) {
BookmarkNode::MetaInfoMap::const_iterator itr;
base::DictionaryValue& temp = result.as_object->additional_properties;
for (itr = meta_info->begin(); itr != meta_info->end(); itr++) {
temp.SetStringWithoutPathExpansion(itr->first, itr->second);
}
}
results_ = GetMetaInfo::Results::Create(result);
}
} else {
if (params->key) {
error_ = bookmark_api_constants::kInvalidParamError;
return true;
}
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
const BookmarkNode* node = model->root_node();
GetMetaInfo::Results::Value result;
result.as_object.reset(new GetMetaInfo::Results::Value::Object);
bookmark_api_helpers::GetMetaInfo(*node,
&result.as_object->additional_properties);
results_ = GetMetaInfo::Results::Create(result);
}
return true;
}
bool BookmarkManagerPrivateSetMetaInfoFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<SetMetaInfo::Params> params(
SetMetaInfo::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
if (!node)
return false;
if (!CanBeModified(node))
return false;
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
if (model->is_permanent_node(node)) {
error_ = bookmark_keys::kModifySpecialError;
return false;
}
model->SetNodeMetaInfo(node, params->key, params->value);
return true;
}
bool BookmarkManagerPrivateUpdateMetaInfoFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<UpdateMetaInfo::Params> params(
UpdateMetaInfo::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
if (!node)
return false;
if (!CanBeModified(node))
return false;
BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
if (model->is_permanent_node(node)) {
error_ = bookmark_keys::kModifySpecialError;
return false;
}
BookmarkNode::MetaInfoMap new_meta_info(
params->meta_info_changes.additional_properties);
if (node->GetMetaInfoMap()) {
new_meta_info.insert(node->GetMetaInfoMap()->begin(),
node->GetMetaInfoMap()->end());
}
model->SetNodeMetaInfoMap(node, new_meta_info);
return true;
}
bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunOnReady() {
bool can_open_new_windows = true;
SetResult(base::MakeUnique<base::FundamentalValue>(can_open_new_windows));
return true;
}
bool BookmarkManagerPrivateRemoveTreesFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
std::unique_ptr<RemoveTrees::Params> params(
RemoveTrees::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
BookmarkModel* model = GetBookmarkModel();
bookmarks::ManagedBookmarkService* managed = GetManagedBookmarkService();
bookmarks::ScopedGroupBookmarkActions group_deletes(model);
int64_t id;
for (size_t i = 0; i < params->id_list.size(); ++i) {
if (!GetBookmarkIdAsInt64(params->id_list[i], &id))
return false;
if (!bookmark_api_helpers::RemoveNode(model, managed, id, true, &error_))
return false;
}
return true;
}
bool BookmarkManagerPrivateUndoFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
Undo();
return true;
}
bool BookmarkManagerPrivateRedoFunction::RunOnReady() {
if (!EditBookmarksEnabled())
return false;
BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
Redo();
return true;
}
bool BookmarkManagerPrivateGetUndoInfoFunction::RunOnReady() {
UndoManager* undo_manager =
BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
UndoInfo::Results::Result result;
result.enabled = undo_manager->undo_count() > 0;
result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel());
results_ = UndoInfo::Results::Create(result);
return true;
}
bool BookmarkManagerPrivateGetRedoInfoFunction::RunOnReady() {
UndoManager* undo_manager =
BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
RedoInfo::Results::Result result;
result.enabled = undo_manager->redo_count() > 0;
result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel());
results_ = RedoInfo::Results::Create(result);
return true;
}
} // namespace extensions