Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Side by Side Diff: chrome/browser/bookmarks/bookmark_manager_extension_api.cc

Issue 11516010: Move BookmarkManagerAPI to c/b/e/api (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_ungoop4
Patch Set: s/bookmark_manager/bookmark_manager_private Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/bookmarks/bookmark_manager_extension_api.h"
6
7 #include <vector>
8
9 #include "base/json/json_writer.h"
10 #include "base/prefs/public/pref_service_base.h"
11 #include "base/string_number_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/bookmarks/bookmark_model.h"
14 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
15 #include "chrome/browser/bookmarks/bookmark_node_data.h"
16 #include "chrome/browser/bookmarks/bookmark_utils.h"
17 // TODO (rdevlin.cronin): Move BookmarkManagerAPI to
18 // chrome/browser/extensions/api so these two aren't interdependent.
19 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
20 #include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
21 #include "chrome/browser/extensions/event_router.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/webui/chrome_url_data_manager.h"
27 #include "chrome/browser/view_type_utils.h"
28 #include "chrome/common/pref_names.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/browser/web_ui.h"
32 #include "grit/generated_resources.h"
33 #include "ui/base/l10n/l10n_util.h"
34
35 #if defined(OS_WIN)
36 #include "win8/util/win8_util.h"
37 #endif // OS_WIN
38
39 namespace keys = extensions::bookmark_api_constants;
40
41 using content::WebContents;
42
43 namespace {
44
45 // Returns a single bookmark node from the argument ID.
46 // This returns NULL in case of failure.
47 const BookmarkNode* GetNodeFromArguments(BookmarkModel* model,
48 const ListValue* args) {
49 std::string id_string;
50 if (!args->GetString(0, &id_string))
51 return NULL;
52 int64 id;
53 if (!base::StringToInt64(id_string, &id))
54 return NULL;
55 return model->GetNodeByID(id);
56 }
57
58 // Gets a vector of bookmark nodes from the argument list of IDs.
59 // This returns false in the case of failure.
60 bool GetNodesFromArguments(BookmarkModel* model, const ListValue* args,
61 size_t args_index, std::vector<const BookmarkNode*>* nodes) {
62
63 const ListValue* ids;
64 if (!args->GetList(args_index, &ids))
65 return false;
66
67 size_t count = ids->GetSize();
68 if (count == 0)
69 return false;
70
71 for (size_t i = 0; i < count; ++i) {
72 std::string id_string;
73 if (!ids->GetString(i, &id_string))
74 return false;
75 int64 id;
76 if (!base::StringToInt64(id_string, &id))
77 return false;
78 const BookmarkNode* node = model->GetNodeByID(id);
79 if (!node)
80 return false;
81 nodes->push_back(node);
82 }
83
84 return true;
85 }
86
87 // Recursively adds a node to a list. This is by used |BookmarkNodeDataToJSON|
88 // when the data comes from the current profile. In this case we have a
89 // BookmarkNode since we got the data from the current profile.
90 void AddNodeToList(ListValue* list, const BookmarkNode& node) {
91 DictionaryValue* dict = new DictionaryValue();
92
93 // Add id and parentId so we can associate the data with existing nodes on the
94 // client side.
95 std::string id_string = base::Int64ToString(node.id());
96 dict->SetString(keys::kIdKey, id_string);
97
98 std::string parent_id_string = base::Int64ToString(node.parent()->id());
99 dict->SetString(keys::kParentIdKey, parent_id_string);
100
101 if (node.is_url())
102 dict->SetString(keys::kUrlKey, node.url().spec());
103
104 dict->SetString(keys::kTitleKey, node.GetTitle());
105
106 ListValue* children = new ListValue();
107 for (int i = 0; i < node.child_count(); ++i)
108 AddNodeToList(children, *node.GetChild(i));
109 dict->Set(keys::kChildrenKey, children);
110
111 list->Append(dict);
112 }
113
114 // Recursively adds an element to a list. This is used by
115 // |BookmarkNodeDataToJSON| when the data comes from a different profile. When
116 // the data comes from a different profile we do not have any IDs or parent IDs.
117 void AddElementToList(ListValue* list,
118 const BookmarkNodeData::Element& element) {
119 DictionaryValue* dict = new DictionaryValue();
120
121 if (element.is_url)
122 dict->SetString(keys::kUrlKey, element.url.spec());
123
124 dict->SetString(keys::kTitleKey, element.title);
125
126 ListValue* children = new ListValue();
127 for (size_t i = 0; i < element.children.size(); ++i)
128 AddElementToList(children, element.children[i]);
129 dict->Set(keys::kChildrenKey, children);
130
131 list->Append(dict);
132 }
133
134 // Builds the JSON structure based on the BookmarksDragData.
135 void BookmarkNodeDataToJSON(Profile* profile, const BookmarkNodeData& data,
136 ListValue* args) {
137 bool same_profile = data.IsFromProfile(profile);
138 DictionaryValue* value = new DictionaryValue();
139 value->SetBoolean(keys::kSameProfileKey, same_profile);
140
141 ListValue* list = new ListValue();
142 if (same_profile) {
143 std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
144 for (size_t i = 0; i < nodes.size(); ++i)
145 AddNodeToList(list, *nodes[i]);
146 } else {
147 // We do not have an node IDs when the data comes from a different profile.
148 std::vector<BookmarkNodeData::Element> elements = data.elements;
149 for (size_t i = 0; i < elements.size(); ++i)
150 AddElementToList(list, elements[i]);
151 }
152 value->Set(keys::kElementsKey, list);
153
154 args->Append(value);
155 }
156
157 } // namespace
158
159 BookmarkManagerExtensionEventRouter::BookmarkManagerExtensionEventRouter(
160 Profile* profile,
161 content::WebContents* web_contents)
162 : profile_(profile),
163 web_contents_(web_contents) {
164 BookmarkTabHelper* bookmark_tab_helper =
165 BookmarkTabHelper::FromWebContents(web_contents_);
166 bookmark_tab_helper->SetBookmarkDragDelegate(this);
167 }
168
169 BookmarkManagerExtensionEventRouter::~BookmarkManagerExtensionEventRouter() {
170 BookmarkTabHelper* bookmark_tab_helper =
171 BookmarkTabHelper::FromWebContents(web_contents_);
172 if (bookmark_tab_helper->GetBookmarkDragDelegate() == this)
173 bookmark_tab_helper->SetBookmarkDragDelegate(NULL);
174 }
175
176 void BookmarkManagerExtensionEventRouter::DispatchEvent(
177 const char* event_name, scoped_ptr<ListValue> args) {
178 if (!extensions::ExtensionSystem::Get(profile_)->event_router())
179 return;
180
181 scoped_ptr<extensions::Event> event(new extensions::Event(
182 event_name, args.Pass()));
183 extensions::ExtensionSystem::Get(profile_)->event_router()->
184 BroadcastEvent(event.Pass());
185 }
186
187 void BookmarkManagerExtensionEventRouter::DispatchDragEvent(
188 const BookmarkNodeData& data, const char* event_name) {
189 if (data.size() == 0)
190 return;
191
192 scoped_ptr<ListValue> args(new ListValue());
193 BookmarkNodeDataToJSON(profile_, data, args.get());
194 DispatchEvent(event_name, args.Pass());
195 }
196
197 void BookmarkManagerExtensionEventRouter::OnDragEnter(
198 const BookmarkNodeData& data) {
199 DispatchDragEvent(data, keys::kOnBookmarkDragEnter);
200 }
201
202 void BookmarkManagerExtensionEventRouter::OnDragOver(
203 const BookmarkNodeData& data) {
204 // Intentionally empty since these events happens too often and floods the
205 // message queue. We do not need this event for the bookmark manager anyway.
206 }
207
208 void BookmarkManagerExtensionEventRouter::OnDragLeave(
209 const BookmarkNodeData& data) {
210 DispatchDragEvent(data, keys::kOnBookmarkDragLeave);
211 }
212
213 void BookmarkManagerExtensionEventRouter::OnDrop(
214 const BookmarkNodeData& data) {
215 DispatchDragEvent(data, keys::kOnBookmarkDrop);
216
217 // Make a copy that is owned by this instance.
218 ClearBookmarkNodeData();
219 bookmark_drag_data_ = data;
220 }
221
222 const BookmarkNodeData*
223 BookmarkManagerExtensionEventRouter::GetBookmarkNodeData() {
224 if (bookmark_drag_data_.is_valid())
225 return &bookmark_drag_data_;
226 return NULL;
227 }
228
229 void BookmarkManagerExtensionEventRouter::ClearBookmarkNodeData() {
230 bookmark_drag_data_.Clear();
231 }
232
233 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut) {
234 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
235 std::vector<const BookmarkNode*> nodes;
236 EXTENSION_FUNCTION_VALIDATE(GetNodesFromArguments(model, args_.get(),
237 0, &nodes));
238 bookmark_utils::CopyToClipboard(model, nodes, cut);
239 return true;
240 }
241
242 bool CopyBookmarkManagerFunction::RunImpl() {
243 return CopyOrCut(false);
244 }
245
246 bool CutBookmarkManagerFunction::RunImpl() {
247 if (!EditBookmarksEnabled())
248 return false;
249 return CopyOrCut(true);
250 }
251
252 bool PasteBookmarkManagerFunction::RunImpl() {
253 if (!EditBookmarksEnabled())
254 return false;
255 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
256 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
257 if (!parent_node) {
258 error_ = keys::kNoParentError;
259 return false;
260 }
261 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
262 if (!can_paste)
263 return false;
264
265 // We want to use the highest index of the selected nodes as a destination.
266 std::vector<const BookmarkNode*> nodes;
267 // No need to test return value, if we got an empty list, we insert at end.
268 GetNodesFromArguments(model, args_.get(), 1, &nodes);
269 int highest_index = -1; // -1 means insert at end of list.
270 for (size_t node = 0; node < nodes.size(); ++node) {
271 // + 1 so that we insert after the selection.
272 int this_node_index = parent_node->GetIndexOf(nodes[node]) + 1;
273 if (this_node_index > highest_index)
274 highest_index = this_node_index;
275 }
276
277 bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
278 return true;
279 }
280
281 bool CanPasteBookmarkManagerFunction::RunImpl() {
282 if (!EditBookmarksEnabled())
283 return false;
284 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
285 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
286 if (!parent_node) {
287 error_ = keys::kNoParentError;
288 return false;
289 }
290 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
291 SetResult(new base::FundamentalValue(can_paste));
292 return true;
293 }
294
295 bool SortChildrenBookmarkManagerFunction::RunImpl() {
296 if (!EditBookmarksEnabled())
297 return false;
298 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
299 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
300 if (!parent_node) {
301 error_ = keys::kNoParentError;
302 return false;
303 }
304 model->SortChildren(parent_node);
305 return true;
306 }
307
308 bool BookmarkManagerGetStringsFunction::RunImpl() {
309 DictionaryValue* localized_strings = new DictionaryValue();
310
311 localized_strings->SetString("title",
312 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
313 localized_strings->SetString("search_button",
314 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
315 localized_strings->SetString("show_in_folder",
316 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
317 localized_strings->SetString("sort",
318 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
319 localized_strings->SetString("organize_menu",
320 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
321 localized_strings->SetString("tools_menu",
322 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TOOLS_MENU));
323 localized_strings->SetString("import_menu",
324 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
325 localized_strings->SetString("export_menu",
326 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
327 localized_strings->SetString("rename_folder",
328 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
329 localized_strings->SetString("edit",
330 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
331 localized_strings->SetString("should_open_all",
332 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
333 localized_strings->SetString("open_incognito",
334 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
335 localized_strings->SetString("open_in_new_tab",
336 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
337 localized_strings->SetString("open_in_new_window",
338 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
339 localized_strings->SetString("add_new_bookmark",
340 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
341 localized_strings->SetString("new_folder",
342 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
343 localized_strings->SetString("open_all",
344 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
345 localized_strings->SetString("open_all_new_window",
346 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
347 localized_strings->SetString("open_all_incognito",
348 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
349 localized_strings->SetString("remove",
350 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
351 localized_strings->SetString("copy",
352 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
353 localized_strings->SetString("cut",
354 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
355 localized_strings->SetString("paste",
356 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
357 localized_strings->SetString("delete",
358 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
359 localized_strings->SetString("undo_delete",
360 l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
361 localized_strings->SetString("new_folder_name",
362 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
363 localized_strings->SetString("name_input_placeholder",
364 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
365 localized_strings->SetString("url_input_placeholder",
366 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
367 localized_strings->SetString("invalid_url",
368 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
369 localized_strings->SetString("recent",
370 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
371 localized_strings->SetString("search",
372 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
373 localized_strings->SetString("bookmark_all_tabs",
374 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_BOOKMARK_ALL_TABS));
375 localized_strings->SetString("save",
376 l10n_util::GetStringUTF16(IDS_SAVE));
377 localized_strings->SetString("cancel",
378 l10n_util::GetStringUTF16(IDS_CANCEL));
379
380 ChromeURLDataManager::DataSource::SetFontAndTextDirection(localized_strings);
381
382 SetResult(localized_strings);
383
384 // This is needed because unlike the rest of these functions, this class
385 // inherits from AsyncFunction directly, rather than BookmarkFunction.
386 SendResponse(true);
387
388 return true;
389 }
390
391 bool StartDragBookmarkManagerFunction::RunImpl() {
392 if (!EditBookmarksEnabled())
393 return false;
394 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
395 std::vector<const BookmarkNode*> nodes;
396 EXTENSION_FUNCTION_VALIDATE(
397 GetNodesFromArguments(model, args_.get(), 0, &nodes));
398
399 WebContents* web_contents =
400 WebContents::FromRenderViewHost(render_view_host_);
401 if (chrome::GetViewType(web_contents) == chrome::VIEW_TYPE_TAB_CONTENTS) {
402 WebContents* web_contents =
403 dispatcher()->delegate()->GetAssociatedWebContents();
404 CHECK(web_contents);
405 bookmark_utils::DragBookmarks(profile(), nodes,
406 web_contents->GetNativeView());
407
408 return true;
409 } else {
410 NOTREACHED();
411 return false;
412 }
413 }
414
415 bool DropBookmarkManagerFunction::RunImpl() {
416 if (!EditBookmarksEnabled())
417 return false;
418
419 BookmarkModel* model =BookmarkModelFactory::GetForProfile(profile());
420
421 int64 id;
422 std::string id_string;
423 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
424
425 if (!base::StringToInt64(id_string, &id)) {
426 error_ = keys::kInvalidIdError;
427 return false;
428 }
429
430 const BookmarkNode* drop_parent = model->GetNodeByID(id);
431 if (!drop_parent) {
432 error_ = keys::kNoParentError;
433 return false;
434 }
435
436 int drop_index;
437 if (HasOptionalArgument(1))
438 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &drop_index));
439 else
440 drop_index = drop_parent->child_count();
441
442 WebContents* web_contents =
443 WebContents::FromRenderViewHost(render_view_host_);
444 if (chrome::GetViewType(web_contents) == chrome::VIEW_TYPE_TAB_CONTENTS) {
445 WebContents* web_contents =
446 dispatcher()->delegate()->GetAssociatedWebContents();
447 CHECK(web_contents);
448 ExtensionWebUI* web_ui =
449 static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
450 CHECK(web_ui);
451 BookmarkManagerExtensionEventRouter* router =
452 web_ui->bookmark_manager_extension_event_router();
453
454 DCHECK(router);
455 const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
456 if (drag_data == NULL) {
457 NOTREACHED() <<"Somehow we're dropping null bookmark data";
458 return false;
459 }
460 bookmark_utils::PerformBookmarkDrop(profile(),
461 *drag_data,
462 drop_parent, drop_index);
463
464 router->ClearBookmarkNodeData();
465 return true;
466 } else {
467 NOTREACHED();
468 return false;
469 }
470 }
471
472 bool GetSubtreeBookmarkManagerFunction::RunImpl() {
473 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
474 const BookmarkNode* node;
475 int64 id;
476 std::string id_string;
477 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
478 bool folders_only;
479 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &folders_only));
480 if (id_string == "") {
481 node = model->root_node();
482 } else {
483 if (!base::StringToInt64(id_string, &id)) {
484 error_ = keys::kInvalidIdError;
485 return false;
486 }
487 node = model->GetNodeByID(id);
488 }
489 if (!node) {
490 error_ = keys::kNoNodeError;
491 return false;
492 }
493 scoped_ptr<ListValue> json(new ListValue());
494 if (folders_only) {
495 extensions::bookmark_api_helpers::AddNodeFoldersOnly(node,
496 json.get(),
497 true);
498 } else {
499 extensions::bookmark_api_helpers::AddNode(node, json.get(), true);
500 }
501 SetResult(json.release());
502 return true;
503 }
504
505 bool CanEditBookmarkManagerFunction::RunImpl() {
506 PrefServiceBase* prefs = PrefServiceBase::FromBrowserContext(profile_);
507 SetResult(new base::FundamentalValue(
508 prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
509 return true;
510 }
511
512 bool RecordLaunchBookmarkFunction::RunImpl() {
513 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_MANAGER);
514 return true;
515 }
516
517 bool CanOpenNewWindowsBookmarkFunction::RunImpl() {
518 bool can_open_new_windows = true;
519
520 #if defined(OS_WIN)
521 if (win8::IsSingleWindowMetroMode())
522 can_open_new_windows = false;
523 #endif // OS_WIN
524
525 SetResult(new base::FundamentalValue(can_open_new_windows));
526 return true;
527 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698