03f3f5d28bf507ce079930b0b6d6dbba2daad0e1
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / bookmark_manager_private / bookmark_manager_private_api.cc
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.
4
5 #include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
6
7 #include <vector>
8
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"
42
43 #if defined(OS_WIN)
44 #include "win8/util/win8_util.h"
45 #endif  // OS_WIN
46
47 namespace extensions {
48
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;
65
66 using content::WebContents;
67
68 namespace {
69
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) {
74   int64 id;
75   if (!base::StringToInt64(id_string, &id))
76     return NULL;
77   return model->GetNodeByID(id);
78 }
79
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) {
85
86   if (id_strings.empty())
87     return false;
88
89   for (size_t i = 0; i < id_strings.size(); ++i) {
90     const BookmarkNode* node = GetNodeFromString(model, id_strings[i]);
91     if (!node)
92       return false;
93     nodes->push_back(node);
94   }
95
96   return true;
97 }
98
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();
104
105   // Add id and parentId so we can associate the data with existing nodes on the
106   // client side.
107   std::string id_string = base::Int64ToString(node.id());
108   dict->SetString(bookmark_keys::kIdKey, id_string);
109
110   std::string parent_id_string = base::Int64ToString(node.parent()->id());
111   dict->SetString(bookmark_keys::kParentIdKey, parent_id_string);
112
113   if (node.is_url())
114     dict->SetString(bookmark_keys::kUrlKey, node.url().spec());
115
116   dict->SetString(bookmark_keys::kTitleKey, node.GetTitle());
117
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);
122
123   list->Append(dict);
124 }
125
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();
132
133   if (element.is_url)
134     dict->SetString(bookmark_keys::kUrlKey, element.url.spec());
135
136   dict->SetString(bookmark_keys::kTitleKey, element.title);
137
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);
142
143   list->Append(dict);
144 }
145
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);
152
153   base::ListValue* list = new base::ListValue();
154   if (same_profile) {
155     std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
156     for (size_t i = 0; i < nodes.size(); ++i)
157       AddNodeToList(list, *nodes[i]);
158   } else {
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]);
163   }
164   value->Set(manager_keys::kElementsKey, list);
165
166   args->Append(value);
167 }
168
169 }  // namespace
170
171 BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter(
172     Profile* profile,
173     content::WebContents* web_contents)
174     : profile_(profile),
175       web_contents_(web_contents) {
176   BookmarkTabHelper* bookmark_tab_helper =
177       BookmarkTabHelper::FromWebContents(web_contents_);
178   bookmark_tab_helper->set_bookmark_drag_delegate(this);
179 }
180
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);
186 }
187
188 void BookmarkManagerPrivateEventRouter::DispatchEvent(
189     const std::string& event_name,
190     scoped_ptr<base::ListValue> args) {
191   if (!ExtensionSystem::Get(profile_)->event_router())
192     return;
193
194   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
195   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
196 }
197
198 void BookmarkManagerPrivateEventRouter::DispatchDragEvent(
199     const BookmarkNodeData& data,
200     const std::string& event_name) {
201   if (data.size() == 0)
202     return;
203
204   scoped_ptr<base::ListValue> args(new base::ListValue());
205   BookmarkNodeDataToJSON(profile_, data, args.get());
206   DispatchEvent(event_name, args.Pass());
207 }
208
209 void BookmarkManagerPrivateEventRouter::OnDragEnter(
210     const BookmarkNodeData& data) {
211   DispatchDragEvent(data, bookmark_manager_private::OnDragEnter::kEventName);
212 }
213
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.
218 }
219
220 void BookmarkManagerPrivateEventRouter::OnDragLeave(
221     const BookmarkNodeData& data) {
222   DispatchDragEvent(data, bookmark_manager_private::OnDragLeave::kEventName);
223 }
224
225 void BookmarkManagerPrivateEventRouter::OnDrop(const BookmarkNodeData& data) {
226   DispatchDragEvent(data, bookmark_manager_private::OnDrop::kEventName);
227
228   // Make a copy that is owned by this instance.
229   ClearBookmarkNodeData();
230   bookmark_drag_data_ = data;
231 }
232
233 const BookmarkNodeData*
234 BookmarkManagerPrivateEventRouter::GetBookmarkNodeData() {
235   if (bookmark_drag_data_.is_valid())
236     return &bookmark_drag_data_;
237   return NULL;
238 }
239
240 void BookmarkManagerPrivateEventRouter::ClearBookmarkNodeData() {
241   bookmark_drag_data_.Clear();
242 }
243
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);
250   return true;
251 }
252
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);
257 }
258
259 bool BookmarkManagerPrivateCutFunction::RunImpl() {
260   if (!EditBookmarksEnabled())
261     return false;
262
263   scoped_ptr<Cut::Params> params(Cut::Params::Create(*args_));
264   EXTENSION_FUNCTION_VALIDATE(params);
265   return CopyOrCut(true, params->id_list);
266 }
267
268 bool BookmarkManagerPrivatePasteFunction::RunImpl() {
269   if (!EditBookmarksEnabled())
270     return false;
271
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);
276   if (!parent_node) {
277     error_ = bookmark_keys::kNoParentError;
278     return false;
279   }
280   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
281   if (!can_paste)
282     return false;
283
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;
295   }
296
297   bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
298   return true;
299 }
300
301 bool BookmarkManagerPrivateCanPasteFunction::RunImpl() {
302   if (!EditBookmarksEnabled())
303     return false;
304
305   scoped_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_));
306   EXTENSION_FUNCTION_VALIDATE(params);
307
308   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
309   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
310   if (!parent_node) {
311     error_ = bookmark_keys::kNoParentError;
312     return false;
313   }
314   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
315   SetResult(new base::FundamentalValue(can_paste));
316   return true;
317 }
318
319 bool BookmarkManagerPrivateSortChildrenFunction::RunImpl() {
320   if (!EditBookmarksEnabled())
321     return false;
322
323   scoped_ptr<SortChildren::Params> params(SortChildren::Params::Create(*args_));
324   EXTENSION_FUNCTION_VALIDATE(params);
325
326   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
327   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
328   if (!parent_node) {
329     error_ = bookmark_keys::kNoParentError;
330     return false;
331   }
332   model->SortChildren(parent_node);
333   return true;
334 }
335
336 bool BookmarkManagerPrivateGetStringsFunction::RunImpl() {
337   base::DictionaryValue* localized_strings = new base::DictionaryValue();
338
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));
403
404   webui::SetFontAndTextDirection(localized_strings);
405
406   SetResult(localized_strings);
407
408   // This is needed because unlike the rest of these functions, this class
409   // inherits from AsyncFunction directly, rather than BookmarkFunction.
410   SendResponse(true);
411
412   return true;
413 }
414
415 bool BookmarkManagerPrivateStartDragFunction::RunImpl() {
416   if (!EditBookmarksEnabled())
417     return false;
418
419   scoped_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_));
420   EXTENSION_FUNCTION_VALIDATE(params);
421
422   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
423   std::vector<const BookmarkNode*> nodes;
424   EXTENSION_FUNCTION_VALIDATE(
425       GetNodesFromVector(model, params->id_list, &nodes));
426
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();
432     CHECK(web_contents);
433     chrome::DragBookmarks(
434         GetProfile(), nodes, web_contents->GetView()->GetNativeView());
435
436     return true;
437   } else {
438     NOTREACHED();
439     return false;
440   }
441 }
442
443 bool BookmarkManagerPrivateDropFunction::RunImpl() {
444   if (!EditBookmarksEnabled())
445     return false;
446
447   scoped_ptr<Drop::Params> params(Drop::Params::Create(*args_));
448   EXTENSION_FUNCTION_VALIDATE(params);
449
450   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
451
452   const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
453   if (!drop_parent) {
454     error_ = bookmark_keys::kNoParentError;
455     return false;
456   }
457
458   int drop_index;
459   if (params->index)
460     drop_index = *params->index;
461   else
462     drop_index = drop_parent->child_count();
463
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();
469     CHECK(web_contents);
470     ExtensionWebUI* web_ui =
471         static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
472     CHECK(web_ui);
473     BookmarkManagerPrivateEventRouter* router =
474         web_ui->bookmark_manager_private_event_router();
475
476     DCHECK(router);
477     const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
478     if (drag_data == NULL) {
479       NOTREACHED() <<"Somehow we're dropping null bookmark data";
480       return false;
481     }
482     chrome::DropBookmarks(GetProfile(), *drag_data, drop_parent, drop_index);
483
484     router->ClearBookmarkNodeData();
485     return true;
486   } else {
487     NOTREACHED();
488     return false;
489   }
490 }
491
492 bool BookmarkManagerPrivateGetSubtreeFunction::RunImpl() {
493   scoped_ptr<GetSubtree::Params> params(GetSubtree::Params::Create(*args_));
494   EXTENSION_FUNCTION_VALIDATE(params);
495
496   const BookmarkNode* node = NULL;
497
498   if (params->id == "") {
499     BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
500     node = model->root_node();
501   } else {
502     node = GetBookmarkNodeFromId(params->id);
503     if (!node)
504       return false;
505   }
506
507   std::vector<linked_ptr<api::bookmarks::BookmarkTreeNode> > nodes;
508   if (params->folders_only)
509     bookmark_api_helpers::AddNodeFoldersOnly(node, &nodes, true);
510   else
511     bookmark_api_helpers::AddNode(node, &nodes, true);
512   results_ = GetSubtree::Results::Create(nodes);
513   return true;
514 }
515
516 bool BookmarkManagerPrivateCanEditFunction::RunImpl() {
517   PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
518   SetResult(new base::FundamentalValue(
519       prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
520   return true;
521 }
522
523 bool BookmarkManagerPrivateRecordLaunchFunction::RunImpl() {
524   RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER);
525   return true;
526 }
527
528 bool BookmarkManagerPrivateGetMetaInfoFunction::RunImpl() {
529   scoped_ptr<GetMetaInfo::Params> params(GetMetaInfo::Params::Create(*args_));
530   EXTENSION_FUNCTION_VALIDATE(params);
531
532   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
533   if (!node)
534     return false;
535
536   std::string value;
537   if (node->GetMetaInfo(params->key, &value))
538     results_ = GetMetaInfo::Results::Create(value);
539   return true;
540 }
541
542 bool BookmarkManagerPrivateSetMetaInfoFunction::RunImpl() {
543   scoped_ptr<SetMetaInfo::Params> params(SetMetaInfo::Params::Create(*args_));
544   EXTENSION_FUNCTION_VALIDATE(params);
545
546   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
547   if (!node)
548     return false;
549
550   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
551   model->SetNodeMetaInfo(node, params->key, params->value);
552   return true;
553 }
554
555 bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunImpl() {
556   bool can_open_new_windows = true;
557
558 #if defined(OS_WIN)
559   if (win8::IsSingleWindowMetroMode())
560     can_open_new_windows = false;
561 #endif  // OS_WIN
562
563   SetResult(new base::FundamentalValue(can_open_new_windows));
564   return true;
565 }
566
567 bool BookmarkManagerPrivateRemoveTreesFunction::RunImpl() {
568   scoped_ptr<RemoveTrees::Params> params(RemoveTrees::Params::Create(*args_));
569   EXTENSION_FUNCTION_VALIDATE(params);
570
571 #if !defined(OS_ANDROID)
572   ScopedGroupBookmarkActions group_deletes(GetProfile());
573 #endif
574   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
575   int64 id;
576   for (size_t i = 0; i < params->id_list.size(); ++i) {
577     if (!GetBookmarkIdAsInt64(params->id_list[i], &id))
578       return false;
579     if (!bookmark_api_helpers::RemoveNode(model, id, true, &error_))
580       return false;
581   }
582
583   return true;
584 }
585
586 bool BookmarkManagerPrivateUndoFunction::RunImpl() {
587 #if !defined(OS_ANDROID)
588   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
589       Undo();
590 #endif
591
592   return true;
593 }
594
595 bool BookmarkManagerPrivateRedoFunction::RunImpl() {
596 #if !defined(OS_ANDROID)
597   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
598       Redo();
599 #endif
600
601   return true;
602 }
603
604 bool BookmarkManagerPrivateGetUndoInfoFunction::RunImpl() {
605 #if !defined(OS_ANDROID)
606   UndoManager* undo_manager =
607       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
608
609   UndoInfo::Results::Result result;
610   result.enabled = undo_manager->undo_count() > 0;
611   result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel());
612
613   results_ = UndoInfo::Results::Create(result);
614 #endif  // !defined(OS_ANDROID)
615
616   return true;
617 }
618
619 bool BookmarkManagerPrivateGetRedoInfoFunction::RunImpl() {
620 #if !defined(OS_ANDROID)
621   UndoManager* undo_manager =
622       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
623
624   RedoInfo::Results::Result result;
625   result.enabled = undo_manager->redo_count() > 0;
626   result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel());
627
628   results_ = RedoInfo::Results::Create(result);
629 #endif  // !defined(OS_ANDROID)
630
631   return true;
632 }
633
634 }  // namespace extensions