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.
5 #include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
9 #include "base/memory/linked_ptr.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/bookmarks/bookmark_model.h"
15 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
16 #include "chrome/browser/bookmarks/bookmark_node_data.h"
17 #include "chrome/browser/bookmarks/bookmark_stats.h"
18 #include "chrome/browser/bookmarks/bookmark_utils.h"
19 #include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_constants.h"
20 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
21 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
22 #include "chrome/browser/extensions/extension_function_dispatcher.h"
23 #include "chrome/browser/extensions/extension_system.h"
24 #include "chrome/browser/extensions/extension_web_ui.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
27 #include "chrome/browser/undo/bookmark_undo_service.h"
28 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
29 #include "chrome/browser/undo/bookmark_undo_utils.h"
30 #include "chrome/common/extensions/api/bookmark_manager_private.h"
31 #include "chrome/common/pref_names.h"
32 #include "components/user_prefs/user_prefs.h"
33 #include "content/public/browser/render_view_host.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_contents_view.h"
36 #include "content/public/browser/web_ui.h"
37 #include "extensions/browser/event_router.h"
38 #include "extensions/browser/view_type_utils.h"
39 #include "grit/generated_resources.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/webui/web_ui_util.h"
44 #include "win8/util/win8_util.h"
47 namespace extensions {
49 namespace bookmark_keys = bookmark_api_constants;
50 namespace bookmark_manager_private = api::bookmark_manager_private;
51 namespace CanPaste = api::bookmark_manager_private::CanPaste;
52 namespace Copy = api::bookmark_manager_private::Copy;
53 namespace Cut = api::bookmark_manager_private::Cut;
54 namespace Drop = api::bookmark_manager_private::Drop;
55 namespace GetSubtree = api::bookmark_manager_private::GetSubtree;
56 namespace manager_keys = bookmark_manager_api_constants;
57 namespace GetMetaInfo = api::bookmark_manager_private::GetMetaInfo;
58 namespace Paste = api::bookmark_manager_private::Paste;
59 namespace RedoInfo = api::bookmark_manager_private::GetRedoInfo;
60 namespace RemoveTrees = api::bookmark_manager_private::RemoveTrees;
61 namespace SetMetaInfo = api::bookmark_manager_private::SetMetaInfo;
62 namespace SortChildren = api::bookmark_manager_private::SortChildren;
63 namespace StartDrag = api::bookmark_manager_private::StartDrag;
64 namespace UndoInfo = api::bookmark_manager_private::GetUndoInfo;
66 using content::WebContents;
70 // Returns a single bookmark node from the argument ID.
71 // This returns NULL in case of failure.
72 const BookmarkNode* GetNodeFromString(
73 BookmarkModel* model, const std::string& id_string) {
75 if (!base::StringToInt64(id_string, &id))
77 return model->GetNodeByID(id);
80 // Gets a vector of bookmark nodes from the argument list of IDs.
81 // This returns false in the case of failure.
82 bool GetNodesFromVector(BookmarkModel* model,
83 const std::vector<std::string>& id_strings,
84 std::vector<const BookmarkNode*>* nodes) {
86 if (id_strings.empty())
89 for (size_t i = 0; i < id_strings.size(); ++i) {
90 const BookmarkNode* node = GetNodeFromString(model, id_strings[i]);
93 nodes->push_back(node);
99 // Recursively adds a node to a list. This is by used |BookmarkNodeDataToJSON|
100 // when the data comes from the current profile. In this case we have a
101 // BookmarkNode since we got the data from the current profile.
102 void AddNodeToList(base::ListValue* list, const BookmarkNode& node) {
103 base::DictionaryValue* dict = new base::DictionaryValue();
105 // Add id and parentId so we can associate the data with existing nodes on the
107 std::string id_string = base::Int64ToString(node.id());
108 dict->SetString(bookmark_keys::kIdKey, id_string);
110 std::string parent_id_string = base::Int64ToString(node.parent()->id());
111 dict->SetString(bookmark_keys::kParentIdKey, parent_id_string);
114 dict->SetString(bookmark_keys::kUrlKey, node.url().spec());
116 dict->SetString(bookmark_keys::kTitleKey, node.GetTitle());
118 base::ListValue* children = new base::ListValue();
119 for (int i = 0; i < node.child_count(); ++i)
120 AddNodeToList(children, *node.GetChild(i));
121 dict->Set(bookmark_keys::kChildrenKey, children);
126 // Recursively adds an element to a list. This is used by
127 // |BookmarkNodeDataToJSON| when the data comes from a different profile. When
128 // the data comes from a different profile we do not have any IDs or parent IDs.
129 void AddElementToList(base::ListValue* list,
130 const BookmarkNodeData::Element& element) {
131 base::DictionaryValue* dict = new base::DictionaryValue();
134 dict->SetString(bookmark_keys::kUrlKey, element.url.spec());
136 dict->SetString(bookmark_keys::kTitleKey, element.title);
138 base::ListValue* children = new base::ListValue();
139 for (size_t i = 0; i < element.children.size(); ++i)
140 AddElementToList(children, element.children[i]);
141 dict->Set(bookmark_keys::kChildrenKey, children);
146 // Builds the JSON structure based on the BookmarksDragData.
147 void BookmarkNodeDataToJSON(Profile* profile, const BookmarkNodeData& data,
148 base::ListValue* args) {
149 bool same_profile = data.IsFromProfile(profile);
150 base::DictionaryValue* value = new base::DictionaryValue();
151 value->SetBoolean(manager_keys::kSameProfileKey, same_profile);
153 base::ListValue* list = new base::ListValue();
155 std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
156 for (size_t i = 0; i < nodes.size(); ++i)
157 AddNodeToList(list, *nodes[i]);
159 // We do not have an node IDs when the data comes from a different profile.
160 std::vector<BookmarkNodeData::Element> elements = data.elements;
161 for (size_t i = 0; i < elements.size(); ++i)
162 AddElementToList(list, elements[i]);
164 value->Set(manager_keys::kElementsKey, list);
171 BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter(
173 content::WebContents* web_contents)
175 web_contents_(web_contents) {
176 BookmarkTabHelper* bookmark_tab_helper =
177 BookmarkTabHelper::FromWebContents(web_contents_);
178 bookmark_tab_helper->set_bookmark_drag_delegate(this);
181 BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() {
182 BookmarkTabHelper* bookmark_tab_helper =
183 BookmarkTabHelper::FromWebContents(web_contents_);
184 if (bookmark_tab_helper->bookmark_drag_delegate() == this)
185 bookmark_tab_helper->set_bookmark_drag_delegate(NULL);
188 void BookmarkManagerPrivateEventRouter::DispatchEvent(
189 const std::string& event_name,
190 scoped_ptr<base::ListValue> args) {
191 if (!ExtensionSystem::Get(profile_)->event_router())
194 scoped_ptr<Event> event(new Event(event_name, args.Pass()));
195 ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
198 void BookmarkManagerPrivateEventRouter::DispatchDragEvent(
199 const BookmarkNodeData& data,
200 const std::string& event_name) {
201 if (data.size() == 0)
204 scoped_ptr<base::ListValue> args(new base::ListValue());
205 BookmarkNodeDataToJSON(profile_, data, args.get());
206 DispatchEvent(event_name, args.Pass());
209 void BookmarkManagerPrivateEventRouter::OnDragEnter(
210 const BookmarkNodeData& data) {
211 DispatchDragEvent(data, bookmark_manager_private::OnDragEnter::kEventName);
214 void BookmarkManagerPrivateEventRouter::OnDragOver(
215 const BookmarkNodeData& data) {
216 // Intentionally empty since these events happens too often and floods the
217 // message queue. We do not need this event for the bookmark manager anyway.
220 void BookmarkManagerPrivateEventRouter::OnDragLeave(
221 const BookmarkNodeData& data) {
222 DispatchDragEvent(data, bookmark_manager_private::OnDragLeave::kEventName);
225 void BookmarkManagerPrivateEventRouter::OnDrop(const BookmarkNodeData& data) {
226 DispatchDragEvent(data, bookmark_manager_private::OnDrop::kEventName);
228 // Make a copy that is owned by this instance.
229 ClearBookmarkNodeData();
230 bookmark_drag_data_ = data;
233 const BookmarkNodeData*
234 BookmarkManagerPrivateEventRouter::GetBookmarkNodeData() {
235 if (bookmark_drag_data_.is_valid())
236 return &bookmark_drag_data_;
240 void BookmarkManagerPrivateEventRouter::ClearBookmarkNodeData() {
241 bookmark_drag_data_.Clear();
244 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut,
245 const std::vector<std::string>& id_list) {
246 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
247 std::vector<const BookmarkNode*> nodes;
248 EXTENSION_FUNCTION_VALIDATE(GetNodesFromVector(model, id_list, &nodes));
249 bookmark_utils::CopyToClipboard(model, nodes, cut);
253 bool BookmarkManagerPrivateCopyFunction::RunImpl() {
254 scoped_ptr<Copy::Params> params(Copy::Params::Create(*args_));
255 EXTENSION_FUNCTION_VALIDATE(params);
256 return CopyOrCut(false, params->id_list);
259 bool BookmarkManagerPrivateCutFunction::RunImpl() {
260 if (!EditBookmarksEnabled())
263 scoped_ptr<Cut::Params> params(Cut::Params::Create(*args_));
264 EXTENSION_FUNCTION_VALIDATE(params);
265 return CopyOrCut(true, params->id_list);
268 bool BookmarkManagerPrivatePasteFunction::RunImpl() {
269 if (!EditBookmarksEnabled())
272 scoped_ptr<Paste::Params> params(Paste::Params::Create(*args_));
273 EXTENSION_FUNCTION_VALIDATE(params);
274 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
275 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
277 error_ = bookmark_keys::kNoParentError;
280 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
284 // We want to use the highest index of the selected nodes as a destination.
285 std::vector<const BookmarkNode*> nodes;
286 // No need to test return value, if we got an empty list, we insert at end.
287 if (params->selected_id_list)
288 GetNodesFromVector(model, *params->selected_id_list, &nodes);
289 int highest_index = -1; // -1 means insert at end of list.
290 for (size_t i = 0; i < nodes.size(); ++i) {
291 // + 1 so that we insert after the selection.
292 int index = parent_node->GetIndexOf(nodes[i]) + 1;
293 if (index > highest_index)
294 highest_index = index;
297 bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
301 bool BookmarkManagerPrivateCanPasteFunction::RunImpl() {
302 if (!EditBookmarksEnabled())
305 scoped_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_));
306 EXTENSION_FUNCTION_VALIDATE(params);
308 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
309 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
311 error_ = bookmark_keys::kNoParentError;
314 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
315 SetResult(new base::FundamentalValue(can_paste));
319 bool BookmarkManagerPrivateSortChildrenFunction::RunImpl() {
320 if (!EditBookmarksEnabled())
323 scoped_ptr<SortChildren::Params> params(SortChildren::Params::Create(*args_));
324 EXTENSION_FUNCTION_VALIDATE(params);
326 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
327 const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
329 error_ = bookmark_keys::kNoParentError;
332 model->SortChildren(parent_node);
336 bool BookmarkManagerPrivateGetStringsFunction::RunImpl() {
337 base::DictionaryValue* localized_strings = new base::DictionaryValue();
339 localized_strings->SetString("title",
340 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
341 localized_strings->SetString("search_button",
342 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
343 localized_strings->SetString("organize_menu",
344 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
345 localized_strings->SetString("show_in_folder",
346 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
347 localized_strings->SetString("sort",
348 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
349 localized_strings->SetString("import_menu",
350 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
351 localized_strings->SetString("export_menu",
352 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
353 localized_strings->SetString("rename_folder",
354 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
355 localized_strings->SetString("edit",
356 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
357 localized_strings->SetString("should_open_all",
358 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
359 localized_strings->SetString("open_incognito",
360 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
361 localized_strings->SetString("open_in_new_tab",
362 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
363 localized_strings->SetString("open_in_new_window",
364 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
365 localized_strings->SetString("add_new_bookmark",
366 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
367 localized_strings->SetString("new_folder",
368 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
369 localized_strings->SetString("open_all",
370 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
371 localized_strings->SetString("open_all_new_window",
372 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
373 localized_strings->SetString("open_all_incognito",
374 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
375 localized_strings->SetString("remove",
376 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
377 localized_strings->SetString("copy",
378 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
379 localized_strings->SetString("cut",
380 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
381 localized_strings->SetString("paste",
382 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
383 localized_strings->SetString("delete",
384 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
385 localized_strings->SetString("undo_delete",
386 l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
387 localized_strings->SetString("new_folder_name",
388 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
389 localized_strings->SetString("name_input_placeholder",
390 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
391 localized_strings->SetString("url_input_placeholder",
392 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
393 localized_strings->SetString("invalid_url",
394 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
395 localized_strings->SetString("recent",
396 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
397 localized_strings->SetString("search",
398 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
399 localized_strings->SetString("save",
400 l10n_util::GetStringUTF16(IDS_SAVE));
401 localized_strings->SetString("cancel",
402 l10n_util::GetStringUTF16(IDS_CANCEL));
404 webui::SetFontAndTextDirection(localized_strings);
406 SetResult(localized_strings);
408 // This is needed because unlike the rest of these functions, this class
409 // inherits from AsyncFunction directly, rather than BookmarkFunction.
415 bool BookmarkManagerPrivateStartDragFunction::RunImpl() {
416 if (!EditBookmarksEnabled())
419 scoped_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_));
420 EXTENSION_FUNCTION_VALIDATE(params);
422 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
423 std::vector<const BookmarkNode*> nodes;
424 EXTENSION_FUNCTION_VALIDATE(
425 GetNodesFromVector(model, params->id_list, &nodes));
427 WebContents* web_contents =
428 WebContents::FromRenderViewHost(render_view_host_);
429 if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
430 WebContents* web_contents =
431 dispatcher()->delegate()->GetAssociatedWebContents();
433 chrome::DragBookmarks(
434 GetProfile(), nodes, web_contents->GetView()->GetNativeView());
443 bool BookmarkManagerPrivateDropFunction::RunImpl() {
444 if (!EditBookmarksEnabled())
447 scoped_ptr<Drop::Params> params(Drop::Params::Create(*args_));
448 EXTENSION_FUNCTION_VALIDATE(params);
450 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
452 const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
454 error_ = bookmark_keys::kNoParentError;
460 drop_index = *params->index;
462 drop_index = drop_parent->child_count();
464 WebContents* web_contents =
465 WebContents::FromRenderViewHost(render_view_host_);
466 if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
467 WebContents* web_contents =
468 dispatcher()->delegate()->GetAssociatedWebContents();
470 ExtensionWebUI* web_ui =
471 static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
473 BookmarkManagerPrivateEventRouter* router =
474 web_ui->bookmark_manager_private_event_router();
477 const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
478 if (drag_data == NULL) {
479 NOTREACHED() <<"Somehow we're dropping null bookmark data";
482 chrome::DropBookmarks(GetProfile(), *drag_data, drop_parent, drop_index);
484 router->ClearBookmarkNodeData();
492 bool BookmarkManagerPrivateGetSubtreeFunction::RunImpl() {
493 scoped_ptr<GetSubtree::Params> params(GetSubtree::Params::Create(*args_));
494 EXTENSION_FUNCTION_VALIDATE(params);
496 const BookmarkNode* node = NULL;
498 if (params->id == "") {
499 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
500 node = model->root_node();
502 node = GetBookmarkNodeFromId(params->id);
507 std::vector<linked_ptr<api::bookmarks::BookmarkTreeNode> > nodes;
508 if (params->folders_only)
509 bookmark_api_helpers::AddNodeFoldersOnly(node, &nodes, true);
511 bookmark_api_helpers::AddNode(node, &nodes, true);
512 results_ = GetSubtree::Results::Create(nodes);
516 bool BookmarkManagerPrivateCanEditFunction::RunImpl() {
517 PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
518 SetResult(new base::FundamentalValue(
519 prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
523 bool BookmarkManagerPrivateRecordLaunchFunction::RunImpl() {
524 RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER);
528 bool BookmarkManagerPrivateGetMetaInfoFunction::RunImpl() {
529 scoped_ptr<GetMetaInfo::Params> params(GetMetaInfo::Params::Create(*args_));
530 EXTENSION_FUNCTION_VALIDATE(params);
532 const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
537 if (node->GetMetaInfo(params->key, &value))
538 results_ = GetMetaInfo::Results::Create(value);
542 bool BookmarkManagerPrivateSetMetaInfoFunction::RunImpl() {
543 scoped_ptr<SetMetaInfo::Params> params(SetMetaInfo::Params::Create(*args_));
544 EXTENSION_FUNCTION_VALIDATE(params);
546 const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
550 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
551 model->SetNodeMetaInfo(node, params->key, params->value);
555 bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunImpl() {
556 bool can_open_new_windows = true;
559 if (win8::IsSingleWindowMetroMode())
560 can_open_new_windows = false;
563 SetResult(new base::FundamentalValue(can_open_new_windows));
567 bool BookmarkManagerPrivateRemoveTreesFunction::RunImpl() {
568 scoped_ptr<RemoveTrees::Params> params(RemoveTrees::Params::Create(*args_));
569 EXTENSION_FUNCTION_VALIDATE(params);
571 #if !defined(OS_ANDROID)
572 ScopedGroupBookmarkActions group_deletes(GetProfile());
574 BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
576 for (size_t i = 0; i < params->id_list.size(); ++i) {
577 if (!GetBookmarkIdAsInt64(params->id_list[i], &id))
579 if (!bookmark_api_helpers::RemoveNode(model, id, true, &error_))
586 bool BookmarkManagerPrivateUndoFunction::RunImpl() {
587 #if !defined(OS_ANDROID)
588 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
595 bool BookmarkManagerPrivateRedoFunction::RunImpl() {
596 #if !defined(OS_ANDROID)
597 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
604 bool BookmarkManagerPrivateGetUndoInfoFunction::RunImpl() {
605 #if !defined(OS_ANDROID)
606 UndoManager* undo_manager =
607 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
609 UndoInfo::Results::Result result;
610 result.enabled = undo_manager->undo_count() > 0;
611 result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel());
613 results_ = UndoInfo::Results::Create(result);
614 #endif // !defined(OS_ANDROID)
619 bool BookmarkManagerPrivateGetRedoInfoFunction::RunImpl() {
620 #if !defined(OS_ANDROID)
621 UndoManager* undo_manager =
622 BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
624 RedoInfo::Results::Result result;
625 result.enabled = undo_manager->redo_count() > 0;
626 result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel());
628 results_ = RedoInfo::Results::Create(result);
629 #endif // !defined(OS_ANDROID)
634 } // namespace extensions