24a884d060b8f43b982d2187dced77b8936fa363
[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_web_ui.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
26 #include "chrome/browser/undo/bookmark_undo_service.h"
27 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
28 #include "chrome/browser/undo/bookmark_undo_utils.h"
29 #include "chrome/common/extensions/api/bookmark_manager_private.h"
30 #include "chrome/common/pref_names.h"
31 #include "components/user_prefs/user_prefs.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/browser/web_contents_view.h"
35 #include "content/public/browser/web_ui.h"
36 #include "extensions/browser/event_router.h"
37 #include "extensions/browser/extension_system.h"
38 #include "extensions/browser/view_type_utils.h"
39 #include "grit/generated_resources.h"
40 #include "ui/base/dragdrop/drag_drop_types.h"
41 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/webui/web_ui_util.h"
43
44 #if defined(OS_WIN)
45 #include "win8/util/win8_util.h"
46 #endif  // OS_WIN
47
48 namespace extensions {
49
50 namespace bookmark_keys = bookmark_api_constants;
51 namespace bookmark_manager_private = api::bookmark_manager_private;
52 namespace CanPaste = api::bookmark_manager_private::CanPaste;
53 namespace Copy = api::bookmark_manager_private::Copy;
54 namespace Cut = api::bookmark_manager_private::Cut;
55 namespace Drop = api::bookmark_manager_private::Drop;
56 namespace GetSubtree = api::bookmark_manager_private::GetSubtree;
57 namespace manager_keys = bookmark_manager_api_constants;
58 namespace GetMetaInfo = api::bookmark_manager_private::GetMetaInfo;
59 namespace Paste = api::bookmark_manager_private::Paste;
60 namespace RedoInfo = api::bookmark_manager_private::GetRedoInfo;
61 namespace RemoveTrees = api::bookmark_manager_private::RemoveTrees;
62 namespace SetMetaInfo = api::bookmark_manager_private::SetMetaInfo;
63 namespace SortChildren = api::bookmark_manager_private::SortChildren;
64 namespace StartDrag = api::bookmark_manager_private::StartDrag;
65 namespace UndoInfo = api::bookmark_manager_private::GetUndoInfo;
66
67 using content::WebContents;
68
69 namespace {
70
71 // Returns a single bookmark node from the argument ID.
72 // This returns NULL in case of failure.
73 const BookmarkNode* GetNodeFromString(
74     BookmarkModel* model, const std::string& id_string) {
75   int64 id;
76   if (!base::StringToInt64(id_string, &id))
77     return NULL;
78   return model->GetNodeByID(id);
79 }
80
81 // Gets a vector of bookmark nodes from the argument list of IDs.
82 // This returns false in the case of failure.
83 bool GetNodesFromVector(BookmarkModel* model,
84                         const std::vector<std::string>& id_strings,
85                         std::vector<const BookmarkNode*>* nodes) {
86
87   if (id_strings.empty())
88     return false;
89
90   for (size_t i = 0; i < id_strings.size(); ++i) {
91     const BookmarkNode* node = GetNodeFromString(model, id_strings[i]);
92     if (!node)
93       return false;
94     nodes->push_back(node);
95   }
96
97   return true;
98 }
99
100 // Recursively adds a node to a list. This is by used |BookmarkNodeDataToJSON|
101 // when the data comes from the current profile. In this case we have a
102 // BookmarkNode since we got the data from the current profile.
103 void AddNodeToList(base::ListValue* list, const BookmarkNode& node) {
104   base::DictionaryValue* dict = new base::DictionaryValue();
105
106   // Add id and parentId so we can associate the data with existing nodes on the
107   // client side.
108   std::string id_string = base::Int64ToString(node.id());
109   dict->SetString(bookmark_keys::kIdKey, id_string);
110
111   std::string parent_id_string = base::Int64ToString(node.parent()->id());
112   dict->SetString(bookmark_keys::kParentIdKey, parent_id_string);
113
114   if (node.is_url())
115     dict->SetString(bookmark_keys::kUrlKey, node.url().spec());
116
117   dict->SetString(bookmark_keys::kTitleKey, node.GetTitle());
118
119   base::ListValue* children = new base::ListValue();
120   for (int i = 0; i < node.child_count(); ++i)
121     AddNodeToList(children, *node.GetChild(i));
122   dict->Set(bookmark_keys::kChildrenKey, children);
123
124   list->Append(dict);
125 }
126
127 // Recursively adds an element to a list. This is used by
128 // |BookmarkNodeDataToJSON| when the data comes from a different profile. When
129 // the data comes from a different profile we do not have any IDs or parent IDs.
130 void AddElementToList(base::ListValue* list,
131                       const BookmarkNodeData::Element& element) {
132   base::DictionaryValue* dict = new base::DictionaryValue();
133
134   if (element.is_url)
135     dict->SetString(bookmark_keys::kUrlKey, element.url.spec());
136
137   dict->SetString(bookmark_keys::kTitleKey, element.title);
138
139   base::ListValue* children = new base::ListValue();
140   for (size_t i = 0; i < element.children.size(); ++i)
141     AddElementToList(children, element.children[i]);
142   dict->Set(bookmark_keys::kChildrenKey, children);
143
144   list->Append(dict);
145 }
146
147 // Builds the JSON structure based on the BookmarksDragData.
148 void BookmarkNodeDataToJSON(Profile* profile, const BookmarkNodeData& data,
149                             base::ListValue* args) {
150   bool same_profile = data.IsFromProfile(profile);
151   base::DictionaryValue* value = new base::DictionaryValue();
152   value->SetBoolean(manager_keys::kSameProfileKey, same_profile);
153
154   base::ListValue* list = new base::ListValue();
155   if (same_profile) {
156     std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
157     for (size_t i = 0; i < nodes.size(); ++i)
158       AddNodeToList(list, *nodes[i]);
159   } else {
160     // We do not have an node IDs when the data comes from a different profile.
161     std::vector<BookmarkNodeData::Element> elements = data.elements;
162     for (size_t i = 0; i < elements.size(); ++i)
163       AddElementToList(list, elements[i]);
164   }
165   value->Set(manager_keys::kElementsKey, list);
166
167   args->Append(value);
168 }
169
170 }  // namespace
171
172 BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter(
173     Profile* profile,
174     content::WebContents* web_contents)
175     : profile_(profile),
176       web_contents_(web_contents) {
177   BookmarkTabHelper* bookmark_tab_helper =
178       BookmarkTabHelper::FromWebContents(web_contents_);
179   bookmark_tab_helper->set_bookmark_drag_delegate(this);
180 }
181
182 BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() {
183   BookmarkTabHelper* bookmark_tab_helper =
184       BookmarkTabHelper::FromWebContents(web_contents_);
185   if (bookmark_tab_helper->bookmark_drag_delegate() == this)
186     bookmark_tab_helper->set_bookmark_drag_delegate(NULL);
187 }
188
189 void BookmarkManagerPrivateEventRouter::DispatchEvent(
190     const std::string& event_name,
191     scoped_ptr<base::ListValue> args) {
192   if (!ExtensionSystem::Get(profile_)->event_router())
193     return;
194
195   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
196   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
197 }
198
199 void BookmarkManagerPrivateEventRouter::DispatchDragEvent(
200     const BookmarkNodeData& data,
201     const std::string& event_name) {
202   if (data.size() == 0)
203     return;
204
205   scoped_ptr<base::ListValue> args(new base::ListValue());
206   BookmarkNodeDataToJSON(profile_, data, args.get());
207   DispatchEvent(event_name, args.Pass());
208 }
209
210 void BookmarkManagerPrivateEventRouter::OnDragEnter(
211     const BookmarkNodeData& data) {
212   DispatchDragEvent(data, bookmark_manager_private::OnDragEnter::kEventName);
213 }
214
215 void BookmarkManagerPrivateEventRouter::OnDragOver(
216     const BookmarkNodeData& data) {
217   // Intentionally empty since these events happens too often and floods the
218   // message queue. We do not need this event for the bookmark manager anyway.
219 }
220
221 void BookmarkManagerPrivateEventRouter::OnDragLeave(
222     const BookmarkNodeData& data) {
223   DispatchDragEvent(data, bookmark_manager_private::OnDragLeave::kEventName);
224 }
225
226 void BookmarkManagerPrivateEventRouter::OnDrop(const BookmarkNodeData& data) {
227   DispatchDragEvent(data, bookmark_manager_private::OnDrop::kEventName);
228
229   // Make a copy that is owned by this instance.
230   ClearBookmarkNodeData();
231   bookmark_drag_data_ = data;
232 }
233
234 const BookmarkNodeData*
235 BookmarkManagerPrivateEventRouter::GetBookmarkNodeData() {
236   if (bookmark_drag_data_.is_valid())
237     return &bookmark_drag_data_;
238   return NULL;
239 }
240
241 void BookmarkManagerPrivateEventRouter::ClearBookmarkNodeData() {
242   bookmark_drag_data_.Clear();
243 }
244
245 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut,
246     const std::vector<std::string>& id_list) {
247   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
248   std::vector<const BookmarkNode*> nodes;
249   EXTENSION_FUNCTION_VALIDATE(GetNodesFromVector(model, id_list, &nodes));
250   bookmark_utils::CopyToClipboard(model, nodes, cut);
251   return true;
252 }
253
254 bool BookmarkManagerPrivateCopyFunction::RunImpl() {
255   scoped_ptr<Copy::Params> params(Copy::Params::Create(*args_));
256   EXTENSION_FUNCTION_VALIDATE(params);
257   return CopyOrCut(false, params->id_list);
258 }
259
260 bool BookmarkManagerPrivateCutFunction::RunImpl() {
261   if (!EditBookmarksEnabled())
262     return false;
263
264   scoped_ptr<Cut::Params> params(Cut::Params::Create(*args_));
265   EXTENSION_FUNCTION_VALIDATE(params);
266   return CopyOrCut(true, params->id_list);
267 }
268
269 bool BookmarkManagerPrivatePasteFunction::RunImpl() {
270   if (!EditBookmarksEnabled())
271     return false;
272
273   scoped_ptr<Paste::Params> params(Paste::Params::Create(*args_));
274   EXTENSION_FUNCTION_VALIDATE(params);
275   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
276   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
277   if (!parent_node) {
278     error_ = bookmark_keys::kNoParentError;
279     return false;
280   }
281   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
282   if (!can_paste)
283     return false;
284
285   // We want to use the highest index of the selected nodes as a destination.
286   std::vector<const BookmarkNode*> nodes;
287   // No need to test return value, if we got an empty list, we insert at end.
288   if (params->selected_id_list)
289     GetNodesFromVector(model, *params->selected_id_list, &nodes);
290   int highest_index = -1;  // -1 means insert at end of list.
291   for (size_t i = 0; i < nodes.size(); ++i) {
292     // + 1 so that we insert after the selection.
293     int index = parent_node->GetIndexOf(nodes[i]) + 1;
294     if (index > highest_index)
295       highest_index = index;
296   }
297
298   bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
299   return true;
300 }
301
302 bool BookmarkManagerPrivateCanPasteFunction::RunImpl() {
303   if (!EditBookmarksEnabled())
304     return false;
305
306   scoped_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_));
307   EXTENSION_FUNCTION_VALIDATE(params);
308
309   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
310   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
311   if (!parent_node) {
312     error_ = bookmark_keys::kNoParentError;
313     return false;
314   }
315   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
316   SetResult(new base::FundamentalValue(can_paste));
317   return true;
318 }
319
320 bool BookmarkManagerPrivateSortChildrenFunction::RunImpl() {
321   if (!EditBookmarksEnabled())
322     return false;
323
324   scoped_ptr<SortChildren::Params> params(SortChildren::Params::Create(*args_));
325   EXTENSION_FUNCTION_VALIDATE(params);
326
327   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
328   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
329   if (!parent_node) {
330     error_ = bookmark_keys::kNoParentError;
331     return false;
332   }
333   model->SortChildren(parent_node);
334   return true;
335 }
336
337 bool BookmarkManagerPrivateGetStringsFunction::RunImpl() {
338   base::DictionaryValue* localized_strings = new base::DictionaryValue();
339
340   localized_strings->SetString("title",
341       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
342   localized_strings->SetString("search_button",
343       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
344   localized_strings->SetString("organize_menu",
345       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
346   localized_strings->SetString("show_in_folder",
347       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
348   localized_strings->SetString("sort",
349       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
350   localized_strings->SetString("import_menu",
351       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
352   localized_strings->SetString("export_menu",
353       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
354   localized_strings->SetString("rename_folder",
355       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
356   localized_strings->SetString("edit",
357       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
358   localized_strings->SetString("should_open_all",
359       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
360   localized_strings->SetString("open_incognito",
361       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
362   localized_strings->SetString("open_in_new_tab",
363       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
364   localized_strings->SetString("open_in_new_window",
365       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
366   localized_strings->SetString("add_new_bookmark",
367       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
368   localized_strings->SetString("new_folder",
369       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
370   localized_strings->SetString("open_all",
371       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
372   localized_strings->SetString("open_all_new_window",
373       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
374   localized_strings->SetString("open_all_incognito",
375       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
376   localized_strings->SetString("remove",
377       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
378   localized_strings->SetString("copy",
379       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
380   localized_strings->SetString("cut",
381       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
382   localized_strings->SetString("paste",
383       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
384   localized_strings->SetString("delete",
385       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
386   localized_strings->SetString("undo_delete",
387       l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
388   localized_strings->SetString("new_folder_name",
389       l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
390   localized_strings->SetString("name_input_placeholder",
391       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
392   localized_strings->SetString("url_input_placeholder",
393       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
394   localized_strings->SetString("invalid_url",
395       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
396   localized_strings->SetString("recent",
397       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
398   localized_strings->SetString("search",
399       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
400   localized_strings->SetString("save",
401       l10n_util::GetStringUTF16(IDS_SAVE));
402   localized_strings->SetString("cancel",
403       l10n_util::GetStringUTF16(IDS_CANCEL));
404
405   webui::SetFontAndTextDirection(localized_strings);
406
407   SetResult(localized_strings);
408
409   // This is needed because unlike the rest of these functions, this class
410   // inherits from AsyncFunction directly, rather than BookmarkFunction.
411   SendResponse(true);
412
413   return true;
414 }
415
416 bool BookmarkManagerPrivateStartDragFunction::RunImpl() {
417   if (!EditBookmarksEnabled())
418     return false;
419
420   scoped_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_));
421   EXTENSION_FUNCTION_VALIDATE(params);
422
423   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
424   std::vector<const BookmarkNode*> nodes;
425   EXTENSION_FUNCTION_VALIDATE(
426       GetNodesFromVector(model, params->id_list, &nodes));
427
428   WebContents* web_contents =
429       WebContents::FromRenderViewHost(render_view_host_);
430   if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
431     WebContents* web_contents =
432         dispatcher()->delegate()->GetAssociatedWebContents();
433     CHECK(web_contents);
434
435     ui::DragDropTypes::DragEventSource source =
436         ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
437     if (params->is_from_touch)
438       source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
439
440     chrome::DragBookmarks(
441         GetProfile(), nodes, web_contents->GetView()->GetNativeView(), source);
442
443     return true;
444   } else {
445     NOTREACHED();
446     return false;
447   }
448 }
449
450 bool BookmarkManagerPrivateDropFunction::RunImpl() {
451   if (!EditBookmarksEnabled())
452     return false;
453
454   scoped_ptr<Drop::Params> params(Drop::Params::Create(*args_));
455   EXTENSION_FUNCTION_VALIDATE(params);
456
457   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
458
459   const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
460   if (!drop_parent) {
461     error_ = bookmark_keys::kNoParentError;
462     return false;
463   }
464
465   int drop_index;
466   if (params->index)
467     drop_index = *params->index;
468   else
469     drop_index = drop_parent->child_count();
470
471   WebContents* web_contents =
472       WebContents::FromRenderViewHost(render_view_host_);
473   if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
474     WebContents* web_contents =
475         dispatcher()->delegate()->GetAssociatedWebContents();
476     CHECK(web_contents);
477     ExtensionWebUI* web_ui =
478         static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
479     CHECK(web_ui);
480     BookmarkManagerPrivateEventRouter* router =
481         web_ui->bookmark_manager_private_event_router();
482
483     DCHECK(router);
484     const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
485     if (drag_data == NULL) {
486       NOTREACHED() <<"Somehow we're dropping null bookmark data";
487       return false;
488     }
489     chrome::DropBookmarks(GetProfile(), *drag_data, drop_parent, drop_index);
490
491     router->ClearBookmarkNodeData();
492     return true;
493   } else {
494     NOTREACHED();
495     return false;
496   }
497 }
498
499 bool BookmarkManagerPrivateGetSubtreeFunction::RunImpl() {
500   scoped_ptr<GetSubtree::Params> params(GetSubtree::Params::Create(*args_));
501   EXTENSION_FUNCTION_VALIDATE(params);
502
503   const BookmarkNode* node = NULL;
504
505   if (params->id == "") {
506     BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
507     node = model->root_node();
508   } else {
509     node = GetBookmarkNodeFromId(params->id);
510     if (!node)
511       return false;
512   }
513
514   std::vector<linked_ptr<api::bookmarks::BookmarkTreeNode> > nodes;
515   if (params->folders_only)
516     bookmark_api_helpers::AddNodeFoldersOnly(node, &nodes, true);
517   else
518     bookmark_api_helpers::AddNode(node, &nodes, true);
519   results_ = GetSubtree::Results::Create(nodes);
520   return true;
521 }
522
523 bool BookmarkManagerPrivateCanEditFunction::RunImpl() {
524   PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
525   SetResult(new base::FundamentalValue(
526       prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
527   return true;
528 }
529
530 bool BookmarkManagerPrivateRecordLaunchFunction::RunImpl() {
531   RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER);
532   return true;
533 }
534
535 bool BookmarkManagerPrivateGetMetaInfoFunction::RunImpl() {
536   scoped_ptr<GetMetaInfo::Params> params(GetMetaInfo::Params::Create(*args_));
537   EXTENSION_FUNCTION_VALIDATE(params);
538
539   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
540   if (!node)
541     return false;
542
543   std::string value;
544   if (node->GetMetaInfo(params->key, &value))
545     results_ = GetMetaInfo::Results::Create(value);
546   return true;
547 }
548
549 bool BookmarkManagerPrivateSetMetaInfoFunction::RunImpl() {
550   scoped_ptr<SetMetaInfo::Params> params(SetMetaInfo::Params::Create(*args_));
551   EXTENSION_FUNCTION_VALIDATE(params);
552
553   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
554   if (!node)
555     return false;
556
557   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
558   model->SetNodeMetaInfo(node, params->key, params->value);
559   return true;
560 }
561
562 bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunImpl() {
563   bool can_open_new_windows = true;
564
565 #if defined(OS_WIN)
566   if (win8::IsSingleWindowMetroMode())
567     can_open_new_windows = false;
568 #endif  // OS_WIN
569
570   SetResult(new base::FundamentalValue(can_open_new_windows));
571   return true;
572 }
573
574 bool BookmarkManagerPrivateRemoveTreesFunction::RunImpl() {
575   scoped_ptr<RemoveTrees::Params> params(RemoveTrees::Params::Create(*args_));
576   EXTENSION_FUNCTION_VALIDATE(params);
577
578 #if !defined(OS_ANDROID)
579   ScopedGroupBookmarkActions group_deletes(GetProfile());
580 #endif
581   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
582   int64 id;
583   for (size_t i = 0; i < params->id_list.size(); ++i) {
584     if (!GetBookmarkIdAsInt64(params->id_list[i], &id))
585       return false;
586     if (!bookmark_api_helpers::RemoveNode(model, id, true, &error_))
587       return false;
588   }
589
590   return true;
591 }
592
593 bool BookmarkManagerPrivateUndoFunction::RunImpl() {
594 #if !defined(OS_ANDROID)
595   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
596       Undo();
597 #endif
598
599   return true;
600 }
601
602 bool BookmarkManagerPrivateRedoFunction::RunImpl() {
603 #if !defined(OS_ANDROID)
604   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
605       Redo();
606 #endif
607
608   return true;
609 }
610
611 bool BookmarkManagerPrivateGetUndoInfoFunction::RunImpl() {
612 #if !defined(OS_ANDROID)
613   UndoManager* undo_manager =
614       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
615
616   UndoInfo::Results::Result result;
617   result.enabled = undo_manager->undo_count() > 0;
618   result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel());
619
620   results_ = UndoInfo::Results::Create(result);
621 #endif  // !defined(OS_ANDROID)
622
623   return true;
624 }
625
626 bool BookmarkManagerPrivateGetRedoInfoFunction::RunImpl() {
627 #if !defined(OS_ANDROID)
628   UndoManager* undo_manager =
629       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
630
631   RedoInfo::Results::Result result;
632   result.enabled = undo_manager->redo_count() > 0;
633   result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel());
634
635   results_ = RedoInfo::Results::Create(result);
636 #endif  // !defined(OS_ANDROID)
637
638   return true;
639 }
640
641 }  // namespace extensions