fab0377648886353ba1c1a52ae0820ddc5b59d1d
[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/lazy_instance.h"
10 #include "base/memory/linked_ptr.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
16 #include "chrome/browser/bookmarks/bookmark_stats.h"
17 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
18 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
19 #include "chrome/browser/extensions/extension_web_ui.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
22 #include "chrome/browser/undo/bookmark_undo_service.h"
23 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
24 #include "chrome/common/extensions/api/bookmark_manager_private.h"
25 #include "chrome/common/pref_names.h"
26 #include "components/bookmarks/core/browser/bookmark_model.h"
27 #include "components/bookmarks/core/browser/bookmark_node_data.h"
28 #include "components/bookmarks/core/browser/bookmark_utils.h"
29 #include "components/bookmarks/core/browser/scoped_group_bookmark_actions.h"
30 #include "components/user_prefs/user_prefs.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/browser/web_contents.h"
33 #include "content/public/browser/web_ui.h"
34 #include "extensions/browser/extension_function_dispatcher.h"
35 #include "extensions/browser/view_type_utils.h"
36 #include "grit/generated_resources.h"
37 #include "ui/base/dragdrop/drag_drop_types.h"
38 #include "ui/base/l10n/l10n_util.h"
39 #include "ui/base/webui/web_ui_util.h"
40
41 namespace extensions {
42
43 namespace bookmark_keys = bookmark_api_constants;
44 namespace bookmark_manager_private = api::bookmark_manager_private;
45 namespace CanPaste = api::bookmark_manager_private::CanPaste;
46 namespace Copy = api::bookmark_manager_private::Copy;
47 namespace CreateWithMetaInfo =
48     api::bookmark_manager_private::CreateWithMetaInfo;
49 namespace Cut = api::bookmark_manager_private::Cut;
50 namespace Drop = api::bookmark_manager_private::Drop;
51 namespace GetSubtree = api::bookmark_manager_private::GetSubtree;
52 namespace GetMetaInfo = api::bookmark_manager_private::GetMetaInfo;
53 namespace Paste = api::bookmark_manager_private::Paste;
54 namespace RedoInfo = api::bookmark_manager_private::GetRedoInfo;
55 namespace RemoveTrees = api::bookmark_manager_private::RemoveTrees;
56 namespace SetMetaInfo = api::bookmark_manager_private::SetMetaInfo;
57 namespace SortChildren = api::bookmark_manager_private::SortChildren;
58 namespace StartDrag = api::bookmark_manager_private::StartDrag;
59 namespace UndoInfo = api::bookmark_manager_private::GetUndoInfo;
60 namespace UpdateMetaInfo = api::bookmark_manager_private::UpdateMetaInfo;
61
62 using content::WebContents;
63
64 namespace {
65
66 // Returns a single bookmark node from the argument ID.
67 // This returns NULL in case of failure.
68 const BookmarkNode* GetNodeFromString(BookmarkModel* model,
69                                       const std::string& id_string) {
70   int64 id;
71   if (!base::StringToInt64(id_string, &id))
72     return NULL;
73   return GetBookmarkNodeByID(model, id);
74 }
75
76 // Gets a vector of bookmark nodes from the argument list of IDs.
77 // This returns false in the case of failure.
78 bool GetNodesFromVector(BookmarkModel* model,
79                         const std::vector<std::string>& id_strings,
80                         std::vector<const BookmarkNode*>* nodes) {
81
82   if (id_strings.empty())
83     return false;
84
85   for (size_t i = 0; i < id_strings.size(); ++i) {
86     const BookmarkNode* node = GetNodeFromString(model, id_strings[i]);
87     if (!node)
88       return false;
89     nodes->push_back(node);
90   }
91
92   return true;
93 }
94
95 // Recursively create a bookmark_manager_private::BookmarkNodeDataElement from
96 // a bookmark node. This is by used |BookmarkNodeDataToJSON| when the data comes
97 // from the current profile. In this case we have a BookmarkNode since we got
98 // the data from the current profile.
99 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement>
100 CreateNodeDataElementFromBookmarkNode(const BookmarkNode& node) {
101   linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> element(
102       new bookmark_manager_private::BookmarkNodeDataElement);
103   // Add id and parentId so we can associate the data with existing nodes on the
104   // client side.
105   element->id.reset(new std::string(base::Int64ToString(node.id())));
106   element->parent_id.reset(
107       new std::string(base::Int64ToString(node.parent()->id())));
108
109   if (node.is_url())
110     element->url.reset(new std::string(node.url().spec()));
111
112   element->title = base::UTF16ToUTF8(node.GetTitle());
113   for (int i = 0; i < node.child_count(); ++i) {
114     element->children.push_back(
115         CreateNodeDataElementFromBookmarkNode(*node.GetChild(i)));
116   }
117
118   return element;
119 }
120
121 // Recursively create a bookmark_manager_private::BookmarkNodeDataElement from
122 // a BookmarkNodeData::Element. This is used by |BookmarkNodeDataToJSON| when
123 // the data comes from a different profile. When the data comes from a different
124 // profile we do not have any IDs or parent IDs.
125 linked_ptr<bookmark_manager_private::BookmarkNodeDataElement>
126 CreateApiNodeDataElement(const BookmarkNodeData::Element& element) {
127   linked_ptr<bookmark_manager_private::BookmarkNodeDataElement> node_element(
128       new bookmark_manager_private::BookmarkNodeDataElement);
129
130   if (element.is_url)
131     node_element->url.reset(new std::string(element.url.spec()));
132   node_element->title = base::UTF16ToUTF8(element.title);
133   for (size_t i = 0; i < element.children.size(); ++i) {
134     node_element->children.push_back(
135         CreateApiNodeDataElement(element.children[i]));
136   }
137
138   return node_element;
139 }
140
141 // Creates a bookmark_manager_private::BookmarkNodeData from a BookmarkNodeData.
142 scoped_ptr<bookmark_manager_private::BookmarkNodeData>
143 CreateApiBookmarkNodeData(Profile* profile, const BookmarkNodeData& data) {
144   const base::FilePath& profile_path = profile->GetPath();
145
146   scoped_ptr<bookmark_manager_private::BookmarkNodeData> node_data(
147       new bookmark_manager_private::BookmarkNodeData);
148   node_data->same_profile = data.IsFromProfilePath(profile_path);
149
150   if (node_data->same_profile) {
151     std::vector<const BookmarkNode*> nodes = data.GetNodes(
152         BookmarkModelFactory::GetForProfile(profile), profile_path);
153     for (size_t i = 0; i < nodes.size(); ++i) {
154       node_data->elements.push_back(
155           CreateNodeDataElementFromBookmarkNode(*nodes[i]));
156     }
157   } else {
158     // We do not have a node IDs when the data comes from a different profile.
159     std::vector<BookmarkNodeData::Element> elements = data.elements;
160     for (size_t i = 0; i < elements.size(); ++i)
161       node_data->elements.push_back(CreateApiNodeDataElement(elements[i]));
162   }
163   return node_data.Pass();
164 }
165
166 }  // namespace
167
168 BookmarkManagerPrivateEventRouter::BookmarkManagerPrivateEventRouter(
169     content::BrowserContext* browser_context,
170     BookmarkModel* bookmark_model)
171     : browser_context_(browser_context), bookmark_model_(bookmark_model) {
172   bookmark_model_->AddObserver(this);
173 }
174
175 BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() {
176   if (bookmark_model_)
177     bookmark_model_->RemoveObserver(this);
178 }
179
180 void BookmarkManagerPrivateEventRouter::DispatchEvent(
181     const std::string& event_name,
182     scoped_ptr<base::ListValue> event_args) {
183   extensions::EventRouter::Get(browser_context_)->BroadcastEvent(
184       make_scoped_ptr(new extensions::Event(event_name, event_args.Pass())));
185 }
186
187 void BookmarkManagerPrivateEventRouter::BookmarkModelChanged() {}
188
189 void BookmarkManagerPrivateEventRouter::BookmarkModelBeingDeleted(
190     BookmarkModel* model) {
191   bookmark_model_ = NULL;
192 }
193
194 void BookmarkManagerPrivateEventRouter::OnWillChangeBookmarkMetaInfo(
195     BookmarkModel* model,
196     const BookmarkNode* node) {
197   DCHECK(prev_meta_info_.empty());
198   if (node->GetMetaInfoMap())
199     prev_meta_info_ = *node->GetMetaInfoMap();
200 }
201
202 void BookmarkManagerPrivateEventRouter::BookmarkMetaInfoChanged(
203     BookmarkModel* model,
204     const BookmarkNode* node) {
205   const BookmarkNode::MetaInfoMap* new_meta_info = node->GetMetaInfoMap();
206   bookmark_manager_private::MetaInfoFields changes;
207
208   // Identify changed/removed fields:
209   for (BookmarkNode::MetaInfoMap::const_iterator it = prev_meta_info_.begin();
210        it != prev_meta_info_.end();
211        ++it) {
212     if (!new_meta_info) {
213       changes.additional_properties[it->first] = "";
214     } else {
215       BookmarkNode::MetaInfoMap::const_iterator new_meta_field =
216           new_meta_info->find(it->first);
217       if (new_meta_field == new_meta_info->end()) {
218         changes.additional_properties[it->first] = "";
219       } else if (it->second != new_meta_field->second) {
220         changes.additional_properties[it->first] = new_meta_field->second;
221       }
222     }
223   }
224
225   // Identify added fields:
226   if (new_meta_info) {
227     for (BookmarkNode::MetaInfoMap::const_iterator it = new_meta_info->begin();
228          it != new_meta_info->end();
229          ++it) {
230       BookmarkNode::MetaInfoMap::const_iterator prev_meta_field =
231           prev_meta_info_.find(it->first);
232       if (prev_meta_field == prev_meta_info_.end())
233         changes.additional_properties[it->first] = it->second;
234     }
235   }
236
237   prev_meta_info_.clear();
238   DispatchEvent(bookmark_manager_private::OnMetaInfoChanged::kEventName,
239                 bookmark_manager_private::OnMetaInfoChanged::Create(
240                     base::Int64ToString(node->id()), changes));
241 }
242
243 BookmarkManagerPrivateAPI::BookmarkManagerPrivateAPI(
244     content::BrowserContext* browser_context)
245     : browser_context_(browser_context) {
246   EventRouter* event_router = EventRouter::Get(browser_context);
247   event_router->RegisterObserver(
248       this, bookmark_manager_private::OnMetaInfoChanged::kEventName);
249 }
250
251 BookmarkManagerPrivateAPI::~BookmarkManagerPrivateAPI() {}
252
253 void BookmarkManagerPrivateAPI::Shutdown() {
254   EventRouter::Get(browser_context_)->UnregisterObserver(this);
255 }
256
257 static base::LazyInstance<
258     BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI> > g_factory =
259     LAZY_INSTANCE_INITIALIZER;
260
261 // static
262 BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI>*
263 BookmarkManagerPrivateAPI::GetFactoryInstance() {
264   return g_factory.Pointer();
265 }
266
267 void BookmarkManagerPrivateAPI::OnListenerAdded(
268     const EventListenerInfo& details) {
269   EventRouter::Get(browser_context_)->UnregisterObserver(this);
270   event_router_.reset(new BookmarkManagerPrivateEventRouter(
271       browser_context_,
272       BookmarkModelFactory::GetForProfile(
273           Profile::FromBrowserContext(browser_context_))));
274 }
275
276 BookmarkManagerPrivateDragEventRouter::BookmarkManagerPrivateDragEventRouter(
277     Profile* profile,
278     content::WebContents* web_contents)
279     : profile_(profile), web_contents_(web_contents) {
280   BookmarkTabHelper* bookmark_tab_helper =
281       BookmarkTabHelper::FromWebContents(web_contents_);
282   bookmark_tab_helper->set_bookmark_drag_delegate(this);
283 }
284
285 BookmarkManagerPrivateDragEventRouter::
286     ~BookmarkManagerPrivateDragEventRouter() {
287   BookmarkTabHelper* bookmark_tab_helper =
288       BookmarkTabHelper::FromWebContents(web_contents_);
289   if (bookmark_tab_helper->bookmark_drag_delegate() == this)
290     bookmark_tab_helper->set_bookmark_drag_delegate(NULL);
291 }
292
293 void BookmarkManagerPrivateDragEventRouter::DispatchEvent(
294     const std::string& event_name,
295     scoped_ptr<base::ListValue> args) {
296   EventRouter* event_router = EventRouter::Get(profile_);
297   if (!event_router)
298     return;
299
300   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
301   event_router->BroadcastEvent(event.Pass());
302 }
303
304 void BookmarkManagerPrivateDragEventRouter::OnDragEnter(
305     const BookmarkNodeData& data) {
306   if (data.size() == 0)
307     return;
308   DispatchEvent(bookmark_manager_private::OnDragEnter::kEventName,
309                 bookmark_manager_private::OnDragEnter::Create(
310                     *CreateApiBookmarkNodeData(profile_, data)));
311 }
312
313 void BookmarkManagerPrivateDragEventRouter::OnDragOver(
314     const BookmarkNodeData& data) {
315   // Intentionally empty since these events happens too often and floods the
316   // message queue. We do not need this event for the bookmark manager anyway.
317 }
318
319 void BookmarkManagerPrivateDragEventRouter::OnDragLeave(
320     const BookmarkNodeData& data) {
321   if (data.size() == 0)
322     return;
323   DispatchEvent(bookmark_manager_private::OnDragLeave::kEventName,
324                 bookmark_manager_private::OnDragLeave::Create(
325                     *CreateApiBookmarkNodeData(profile_, data)));
326 }
327
328 void BookmarkManagerPrivateDragEventRouter::OnDrop(
329     const BookmarkNodeData& data) {
330   if (data.size() == 0)
331     return;
332   DispatchEvent(bookmark_manager_private::OnDrop::kEventName,
333                 bookmark_manager_private::OnDrop::Create(
334                     *CreateApiBookmarkNodeData(profile_, data)));
335
336   // Make a copy that is owned by this instance.
337   ClearBookmarkNodeData();
338   bookmark_drag_data_ = data;
339 }
340
341 const BookmarkNodeData*
342 BookmarkManagerPrivateDragEventRouter::GetBookmarkNodeData() {
343   if (bookmark_drag_data_.is_valid())
344     return &bookmark_drag_data_;
345   return NULL;
346 }
347
348 void BookmarkManagerPrivateDragEventRouter::ClearBookmarkNodeData() {
349   bookmark_drag_data_.Clear();
350 }
351
352 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut,
353     const std::vector<std::string>& id_list) {
354   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
355   std::vector<const BookmarkNode*> nodes;
356   EXTENSION_FUNCTION_VALIDATE(GetNodesFromVector(model, id_list, &nodes));
357   bookmark_utils::CopyToClipboard(model, nodes, cut);
358   return true;
359 }
360
361 bool BookmarkManagerPrivateCopyFunction::RunOnReady() {
362   scoped_ptr<Copy::Params> params(Copy::Params::Create(*args_));
363   EXTENSION_FUNCTION_VALIDATE(params);
364   return CopyOrCut(false, params->id_list);
365 }
366
367 bool BookmarkManagerPrivateCutFunction::RunOnReady() {
368   if (!EditBookmarksEnabled())
369     return false;
370
371   scoped_ptr<Cut::Params> params(Cut::Params::Create(*args_));
372   EXTENSION_FUNCTION_VALIDATE(params);
373   return CopyOrCut(true, params->id_list);
374 }
375
376 bool BookmarkManagerPrivatePasteFunction::RunOnReady() {
377   if (!EditBookmarksEnabled())
378     return false;
379
380   scoped_ptr<Paste::Params> params(Paste::Params::Create(*args_));
381   EXTENSION_FUNCTION_VALIDATE(params);
382   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
383   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
384   if (!parent_node) {
385     error_ = bookmark_keys::kNoParentError;
386     return false;
387   }
388   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
389   if (!can_paste)
390     return false;
391
392   // We want to use the highest index of the selected nodes as a destination.
393   std::vector<const BookmarkNode*> nodes;
394   // No need to test return value, if we got an empty list, we insert at end.
395   if (params->selected_id_list)
396     GetNodesFromVector(model, *params->selected_id_list, &nodes);
397   int highest_index = -1;  // -1 means insert at end of list.
398   for (size_t i = 0; i < nodes.size(); ++i) {
399     // + 1 so that we insert after the selection.
400     int index = parent_node->GetIndexOf(nodes[i]) + 1;
401     if (index > highest_index)
402       highest_index = index;
403   }
404
405   bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
406   return true;
407 }
408
409 bool BookmarkManagerPrivateCanPasteFunction::RunOnReady() {
410   if (!EditBookmarksEnabled())
411     return false;
412
413   scoped_ptr<CanPaste::Params> params(CanPaste::Params::Create(*args_));
414   EXTENSION_FUNCTION_VALIDATE(params);
415
416   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
417   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
418   if (!parent_node) {
419     error_ = bookmark_keys::kNoParentError;
420     return false;
421   }
422   bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
423   SetResult(new base::FundamentalValue(can_paste));
424   return true;
425 }
426
427 bool BookmarkManagerPrivateSortChildrenFunction::RunOnReady() {
428   if (!EditBookmarksEnabled())
429     return false;
430
431   scoped_ptr<SortChildren::Params> params(SortChildren::Params::Create(*args_));
432   EXTENSION_FUNCTION_VALIDATE(params);
433
434   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
435   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
436   if (!parent_node) {
437     error_ = bookmark_keys::kNoParentError;
438     return false;
439   }
440   model->SortChildren(parent_node);
441   return true;
442 }
443
444 bool BookmarkManagerPrivateGetStringsFunction::RunAsync() {
445   base::DictionaryValue* localized_strings = new base::DictionaryValue();
446
447   localized_strings->SetString("title",
448       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
449   localized_strings->SetString("search_button",
450       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
451   localized_strings->SetString("organize_menu",
452       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
453   localized_strings->SetString("show_in_folder",
454       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
455   localized_strings->SetString("sort",
456       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
457   localized_strings->SetString("import_menu",
458       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
459   localized_strings->SetString("export_menu",
460       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
461   localized_strings->SetString("rename_folder",
462       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
463   localized_strings->SetString("edit",
464       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
465   localized_strings->SetString("should_open_all",
466       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
467   localized_strings->SetString("open_incognito",
468       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
469   localized_strings->SetString("open_in_new_tab",
470       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
471   localized_strings->SetString("open_in_new_window",
472       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
473   localized_strings->SetString("add_new_bookmark",
474       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
475   localized_strings->SetString("new_folder",
476       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
477   localized_strings->SetString("open_all",
478       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
479   localized_strings->SetString("open_all_new_window",
480       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
481   localized_strings->SetString("open_all_incognito",
482       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
483   localized_strings->SetString("remove",
484       l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
485   localized_strings->SetString("copy",
486       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
487   localized_strings->SetString("cut",
488       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
489   localized_strings->SetString("paste",
490       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
491   localized_strings->SetString("delete",
492       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
493   localized_strings->SetString("undo_delete",
494       l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
495   localized_strings->SetString("new_folder_name",
496       l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
497   localized_strings->SetString("name_input_placeholder",
498       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
499   localized_strings->SetString("url_input_placeholder",
500       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
501   localized_strings->SetString("invalid_url",
502       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
503   localized_strings->SetString("recent",
504       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
505   localized_strings->SetString("search",
506       l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
507   localized_strings->SetString("save",
508       l10n_util::GetStringUTF16(IDS_SAVE));
509   localized_strings->SetString("cancel",
510       l10n_util::GetStringUTF16(IDS_CANCEL));
511
512   webui::SetFontAndTextDirection(localized_strings);
513
514   SetResult(localized_strings);
515
516   // This is needed because unlike the rest of these functions, this class
517   // inherits from AsyncFunction directly, rather than BookmarkFunction.
518   SendResponse(true);
519
520   return true;
521 }
522
523 bool BookmarkManagerPrivateStartDragFunction::RunOnReady() {
524   if (!EditBookmarksEnabled())
525     return false;
526
527   scoped_ptr<StartDrag::Params> params(StartDrag::Params::Create(*args_));
528   EXTENSION_FUNCTION_VALIDATE(params);
529
530   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
531   std::vector<const BookmarkNode*> nodes;
532   EXTENSION_FUNCTION_VALIDATE(
533       GetNodesFromVector(model, params->id_list, &nodes));
534
535   WebContents* web_contents =
536       WebContents::FromRenderViewHost(render_view_host_);
537   if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
538     WebContents* web_contents =
539         dispatcher()->delegate()->GetAssociatedWebContents();
540     CHECK(web_contents);
541
542     ui::DragDropTypes::DragEventSource source =
543         ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
544     if (params->is_from_touch)
545       source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
546
547     chrome::DragBookmarks(
548         GetProfile(), nodes, web_contents->GetNativeView(), source);
549
550     return true;
551   } else {
552     NOTREACHED();
553     return false;
554   }
555 }
556
557 bool BookmarkManagerPrivateDropFunction::RunOnReady() {
558   if (!EditBookmarksEnabled())
559     return false;
560
561   scoped_ptr<Drop::Params> params(Drop::Params::Create(*args_));
562   EXTENSION_FUNCTION_VALIDATE(params);
563
564   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
565
566   const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
567   if (!drop_parent) {
568     error_ = bookmark_keys::kNoParentError;
569     return false;
570   }
571
572   int drop_index;
573   if (params->index)
574     drop_index = *params->index;
575   else
576     drop_index = drop_parent->child_count();
577
578   WebContents* web_contents =
579       WebContents::FromRenderViewHost(render_view_host_);
580   if (GetViewType(web_contents) == VIEW_TYPE_TAB_CONTENTS) {
581     WebContents* web_contents =
582         dispatcher()->delegate()->GetAssociatedWebContents();
583     CHECK(web_contents);
584     ExtensionWebUI* web_ui =
585         static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
586     CHECK(web_ui);
587     BookmarkManagerPrivateDragEventRouter* router =
588         web_ui->bookmark_manager_private_drag_event_router();
589
590     DCHECK(router);
591     const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
592     if (drag_data == NULL) {
593       NOTREACHED() <<"Somehow we're dropping null bookmark data";
594       return false;
595     }
596     chrome::DropBookmarks(GetProfile(), *drag_data, drop_parent, drop_index);
597
598     router->ClearBookmarkNodeData();
599     return true;
600   } else {
601     NOTREACHED();
602     return false;
603   }
604 }
605
606 bool BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() {
607   scoped_ptr<GetSubtree::Params> params(GetSubtree::Params::Create(*args_));
608   EXTENSION_FUNCTION_VALIDATE(params);
609
610   const BookmarkNode* node = NULL;
611
612   if (params->id == "") {
613     BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
614     node = model->root_node();
615   } else {
616     node = GetBookmarkNodeFromId(params->id);
617     if (!node)
618       return false;
619   }
620
621   std::vector<linked_ptr<api::bookmarks::BookmarkTreeNode> > nodes;
622   if (params->folders_only)
623     bookmark_api_helpers::AddNodeFoldersOnly(node, &nodes, true);
624   else
625     bookmark_api_helpers::AddNode(node, &nodes, true);
626   results_ = GetSubtree::Results::Create(nodes);
627   return true;
628 }
629
630 bool BookmarkManagerPrivateCanEditFunction::RunOnReady() {
631   PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
632   SetResult(new base::FundamentalValue(
633       prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
634   return true;
635 }
636
637 bool BookmarkManagerPrivateRecordLaunchFunction::RunOnReady() {
638   RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_MANAGER);
639   return true;
640 }
641
642 bool BookmarkManagerPrivateCreateWithMetaInfoFunction::RunOnReady() {
643   scoped_ptr<CreateWithMetaInfo::Params> params(
644       CreateWithMetaInfo::Params::Create(*args_));
645   EXTENSION_FUNCTION_VALIDATE(params);
646
647   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
648   const BookmarkNode* node = CreateBookmarkNode(
649       model, params->bookmark, &params->meta_info.additional_properties);
650   if (!node)
651     return false;
652
653   scoped_ptr<api::bookmarks::BookmarkTreeNode> result_node(
654       bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
655   results_ = CreateWithMetaInfo::Results::Create(*result_node);
656
657   return true;
658 }
659
660 bool BookmarkManagerPrivateGetMetaInfoFunction::RunOnReady() {
661   scoped_ptr<GetMetaInfo::Params> params(GetMetaInfo::Params::Create(*args_));
662   EXTENSION_FUNCTION_VALIDATE(params);
663
664   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
665   if (!node)
666     return false;
667
668   if (params->key) {
669     std::string value;
670     if (node->GetMetaInfo(*params->key, &value)) {
671       GetMetaInfo::Results::Value result;
672       result.as_string.reset(new std::string(value));
673       results_ = GetMetaInfo::Results::Create(result);
674     }
675   } else {
676     GetMetaInfo::Results::Value result;
677     result.as_meta_info_fields.reset(
678         new bookmark_manager_private::MetaInfoFields);
679
680     const BookmarkNode::MetaInfoMap* meta_info = node->GetMetaInfoMap();
681     if (meta_info)
682       result.as_meta_info_fields->additional_properties = *meta_info;
683     results_ = GetMetaInfo::Results::Create(result);
684   }
685
686   return true;
687 }
688
689 bool BookmarkManagerPrivateSetMetaInfoFunction::RunOnReady() {
690   scoped_ptr<SetMetaInfo::Params> params(SetMetaInfo::Params::Create(*args_));
691   EXTENSION_FUNCTION_VALIDATE(params);
692
693   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
694   if (!node)
695     return false;
696
697   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
698   model->SetNodeMetaInfo(node, params->key, params->value);
699   return true;
700 }
701
702 bool BookmarkManagerPrivateUpdateMetaInfoFunction::RunOnReady() {
703   scoped_ptr<UpdateMetaInfo::Params> params(
704       UpdateMetaInfo::Params::Create(*args_));
705   EXTENSION_FUNCTION_VALIDATE(params);
706
707   const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
708   if (!node)
709     return false;
710
711   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
712   BookmarkNode::MetaInfoMap new_meta_info(
713       params->meta_info_changes.additional_properties);
714   if (node->GetMetaInfoMap()) {
715     new_meta_info.insert(node->GetMetaInfoMap()->begin(),
716                          node->GetMetaInfoMap()->end());
717   }
718   model->SetNodeMetaInfoMap(node, new_meta_info);
719
720   return true;
721 }
722
723 bool BookmarkManagerPrivateCanOpenNewWindowsFunction::RunOnReady() {
724   bool can_open_new_windows = true;
725   SetResult(new base::FundamentalValue(can_open_new_windows));
726   return true;
727 }
728
729 bool BookmarkManagerPrivateRemoveTreesFunction::RunOnReady() {
730   scoped_ptr<RemoveTrees::Params> params(RemoveTrees::Params::Create(*args_));
731   EXTENSION_FUNCTION_VALIDATE(params);
732
733   BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
734 #if !defined(OS_ANDROID)
735   ScopedGroupBookmarkActions group_deletes(model);
736 #endif
737   int64 id;
738   for (size_t i = 0; i < params->id_list.size(); ++i) {
739     if (!GetBookmarkIdAsInt64(params->id_list[i], &id))
740       return false;
741     if (!bookmark_api_helpers::RemoveNode(model, id, true, &error_))
742       return false;
743   }
744
745   return true;
746 }
747
748 bool BookmarkManagerPrivateUndoFunction::RunOnReady() {
749 #if !defined(OS_ANDROID)
750   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
751       Undo();
752 #endif
753
754   return true;
755 }
756
757 bool BookmarkManagerPrivateRedoFunction::RunOnReady() {
758 #if !defined(OS_ANDROID)
759   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
760       Redo();
761 #endif
762
763   return true;
764 }
765
766 bool BookmarkManagerPrivateGetUndoInfoFunction::RunOnReady() {
767 #if !defined(OS_ANDROID)
768   UndoManager* undo_manager =
769       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
770
771   UndoInfo::Results::Result result;
772   result.enabled = undo_manager->undo_count() > 0;
773   result.label = base::UTF16ToUTF8(undo_manager->GetUndoLabel());
774
775   results_ = UndoInfo::Results::Create(result);
776 #endif  // !defined(OS_ANDROID)
777
778   return true;
779 }
780
781 bool BookmarkManagerPrivateGetRedoInfoFunction::RunOnReady() {
782 #if !defined(OS_ANDROID)
783   UndoManager* undo_manager =
784       BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager();
785
786   RedoInfo::Results::Result result;
787   result.enabled = undo_manager->redo_count() > 0;
788   result.label = base::UTF16ToUTF8(undo_manager->GetRedoLabel());
789
790   results_ = RedoInfo::Results::Create(result);
791 #endif  // !defined(OS_ANDROID)
792
793   return true;
794 }
795
796 }  // namespace extensions