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

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: 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->set_bookmark_drag_delegate(this);
167 }
168
169 BookmarkManagerExtensionEventRouter::~BookmarkManagerExtensionEventRouter() {
170 BookmarkTabHelper* bookmark_tab_helper =
171 BookmarkTabHelper::FromWebContents(web_contents_);
172 if (bookmark_tab_helper->bookmark_drag_delegate() == this)
173 bookmark_tab_helper->set_bookmark_drag_delegate(NULL);
174 }
175
176 void BookmarkManagerExtensionEventRouter::DispatchEvent(
177 const char* event_name,
178 scoped_ptr<ListValue> args) {
179 if (!extensions::ExtensionSystem::Get(profile_)->event_router())
180 return;
181
182 scoped_ptr<extensions::Event> event(new extensions::Event(
183 event_name, args.Pass()));
184 extensions::ExtensionSystem::Get(profile_)->event_router()->
185 BroadcastEvent(event.Pass());
186 }
187
188 void BookmarkManagerExtensionEventRouter::DispatchDragEvent(
189 const BookmarkNodeData& data,
190 const char* event_name) {
191 if (data.size() == 0)
192 return;
193
194 scoped_ptr<ListValue> args(new ListValue());
195 BookmarkNodeDataToJSON(profile_, data, args.get());
196 DispatchEvent(event_name, args.Pass());
197 }
198
199 void BookmarkManagerExtensionEventRouter::OnDragEnter(
200 const BookmarkNodeData& data) {
201 DispatchDragEvent(data, keys::kOnBookmarkDragEnter);
202 }
203
204 void BookmarkManagerExtensionEventRouter::OnDragOver(
205 const BookmarkNodeData& data) {
206 // Intentionally empty since these events happens too often and floods the
207 // message queue. We do not need this event for the bookmark manager anyway.
208 }
209
210 void BookmarkManagerExtensionEventRouter::OnDragLeave(
211 const BookmarkNodeData& data) {
212 DispatchDragEvent(data, keys::kOnBookmarkDragLeave);
213 }
214
215 void BookmarkManagerExtensionEventRouter::OnDrop(
216 const BookmarkNodeData& data) {
217 DispatchDragEvent(data, keys::kOnBookmarkDrop);
218
219 // Make a copy that is owned by this instance.
220 ClearBookmarkNodeData();
221 bookmark_drag_data_ = data;
222 }
223
224 const BookmarkNodeData*
225 BookmarkManagerExtensionEventRouter::GetBookmarkNodeData() {
226 if (bookmark_drag_data_.is_valid())
227 return &bookmark_drag_data_;
228 return NULL;
229 }
230
231 void BookmarkManagerExtensionEventRouter::ClearBookmarkNodeData() {
232 bookmark_drag_data_.Clear();
233 }
234
235 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut) {
236 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
237 std::vector<const BookmarkNode*> nodes;
238 EXTENSION_FUNCTION_VALIDATE(GetNodesFromArguments(model, args_.get(),
239 0, &nodes));
240 bookmark_utils::CopyToClipboard(model, nodes, cut);
241 return true;
242 }
243
244 bool CopyBookmarkManagerFunction::RunImpl() {
245 return CopyOrCut(false);
246 }
247
248 bool CutBookmarkManagerFunction::RunImpl() {
249 if (!EditBookmarksEnabled())
250 return false;
251 return CopyOrCut(true);
252 }
253
254 bool PasteBookmarkManagerFunction::RunImpl() {
255 if (!EditBookmarksEnabled())
256 return false;
257 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
258 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
259 if (!parent_node) {
260 error_ = keys::kNoParentError;
261 return false;
262 }
263 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
264 if (!can_paste)
265 return false;
266
267 // We want to use the highest index of the selected nodes as a destination.
268 std::vector<const BookmarkNode*> nodes;
269 // No need to test return value, if we got an empty list, we insert at end.
270 GetNodesFromArguments(model, args_.get(), 1, &nodes);
271 int highest_index = -1; // -1 means insert at end of list.
272 for (size_t node = 0; node < nodes.size(); ++node) {
273 // + 1 so that we insert after the selection.
274 int this_node_index = parent_node->GetIndexOf(nodes[node]) + 1;
275 if (this_node_index > highest_index)
276 highest_index = this_node_index;
277 }
278
279 bookmark_utils::PasteFromClipboard(model, parent_node, highest_index);
280 return true;
281 }
282
283 bool CanPasteBookmarkManagerFunction::RunImpl() {
284 if (!EditBookmarksEnabled())
285 return false;
286 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
287 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
288 if (!parent_node) {
289 error_ = keys::kNoParentError;
290 return false;
291 }
292 bool can_paste = bookmark_utils::CanPasteFromClipboard(parent_node);
293 SetResult(new base::FundamentalValue(can_paste));
294 return true;
295 }
296
297 bool SortChildrenBookmarkManagerFunction::RunImpl() {
298 if (!EditBookmarksEnabled())
299 return false;
300 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
301 const BookmarkNode* parent_node = GetNodeFromArguments(model, args_.get());
302 if (!parent_node) {
303 error_ = keys::kNoParentError;
304 return false;
305 }
306 model->SortChildren(parent_node);
307 return true;
308 }
309
310 bool BookmarkManagerGetStringsFunction::RunImpl() {
311 DictionaryValue* localized_strings = new DictionaryValue();
312
313 localized_strings->SetString("title",
314 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE));
315 localized_strings->SetString("search_button",
316 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH_BUTTON));
317 localized_strings->SetString("show_in_folder",
318 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER));
319 localized_strings->SetString("sort",
320 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SORT));
321 localized_strings->SetString("organize_menu",
322 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU));
323 localized_strings->SetString("tools_menu",
324 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TOOLS_MENU));
325 localized_strings->SetString("import_menu",
326 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_IMPORT_MENU));
327 localized_strings->SetString("export_menu",
328 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_EXPORT_MENU));
329 localized_strings->SetString("rename_folder",
330 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_RENAME_FOLDER));
331 localized_strings->SetString("edit",
332 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT));
333 localized_strings->SetString("should_open_all",
334 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL));
335 localized_strings->SetString("open_incognito",
336 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_INCOGNITO));
337 localized_strings->SetString("open_in_new_tab",
338 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB));
339 localized_strings->SetString("open_in_new_window",
340 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW));
341 localized_strings->SetString("add_new_bookmark",
342 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
343 localized_strings->SetString("new_folder",
344 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_NEW_FOLDER));
345 localized_strings->SetString("open_all",
346 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL));
347 localized_strings->SetString("open_all_new_window",
348 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
349 localized_strings->SetString("open_all_incognito",
350 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
351 localized_strings->SetString("remove",
352 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_REMOVE));
353 localized_strings->SetString("copy",
354 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_COPY));
355 localized_strings->SetString("cut",
356 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_CUT));
357 localized_strings->SetString("paste",
358 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PASTE));
359 localized_strings->SetString("delete",
360 l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_DELETE));
361 localized_strings->SetString("undo_delete",
362 l10n_util::GetStringUTF16(IDS_UNDO_DELETE));
363 localized_strings->SetString("new_folder_name",
364 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME));
365 localized_strings->SetString("name_input_placeholder",
366 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER));
367 localized_strings->SetString("url_input_placeholder",
368 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER));
369 localized_strings->SetString("invalid_url",
370 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_INVALID_URL));
371 localized_strings->SetString("recent",
372 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_RECENT));
373 localized_strings->SetString("search",
374 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_SEARCH));
375 localized_strings->SetString("bookmark_all_tabs",
376 l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_BOOKMARK_ALL_TABS));
377 localized_strings->SetString("save",
378 l10n_util::GetStringUTF16(IDS_SAVE));
379 localized_strings->SetString("cancel",
380 l10n_util::GetStringUTF16(IDS_CANCEL));
381
382 ChromeURLDataManager::DataSource::SetFontAndTextDirection(localized_strings);
383
384 SetResult(localized_strings);
385
386 // This is needed because unlike the rest of these functions, this class
387 // inherits from AsyncFunction directly, rather than BookmarkFunction.
388 SendResponse(true);
389
390 return true;
391 }
392
393 bool StartDragBookmarkManagerFunction::RunImpl() {
394 if (!EditBookmarksEnabled())
395 return false;
396 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
397 std::vector<const BookmarkNode*> nodes;
398 EXTENSION_FUNCTION_VALIDATE(
399 GetNodesFromArguments(model, args_.get(), 0, &nodes));
400
401 WebContents* web_contents =
402 WebContents::FromRenderViewHost(render_view_host_);
403 if (chrome::GetViewType(web_contents) == chrome::VIEW_TYPE_TAB_CONTENTS) {
404 WebContents* web_contents =
405 dispatcher()->delegate()->GetAssociatedWebContents();
406 CHECK(web_contents);
407 bookmark_utils::DragBookmarks(profile(), nodes,
408 web_contents->GetNativeView());
409
410 return true;
411 } else {
412 NOTREACHED();
413 return false;
414 }
415 }
416
417 bool DropBookmarkManagerFunction::RunImpl() {
418 if (!EditBookmarksEnabled())
419 return false;
420
421 BookmarkModel* model =BookmarkModelFactory::GetForProfile(profile());
422
423 int64 id;
424 std::string id_string;
425 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
426
427 if (!base::StringToInt64(id_string, &id)) {
428 error_ = keys::kInvalidIdError;
429 return false;
430 }
431
432 const BookmarkNode* drop_parent = model->GetNodeByID(id);
433 if (!drop_parent) {
434 error_ = keys::kNoParentError;
435 return false;
436 }
437
438 int drop_index;
439 if (HasOptionalArgument(1))
440 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &drop_index));
441 else
442 drop_index = drop_parent->child_count();
443
444 WebContents* web_contents =
445 WebContents::FromRenderViewHost(render_view_host_);
446 if (chrome::GetViewType(web_contents) == chrome::VIEW_TYPE_TAB_CONTENTS) {
447 WebContents* web_contents =
448 dispatcher()->delegate()->GetAssociatedWebContents();
449 CHECK(web_contents);
450 ExtensionWebUI* web_ui =
451 static_cast<ExtensionWebUI*>(web_contents->GetWebUI()->GetController());
452 CHECK(web_ui);
453 BookmarkManagerExtensionEventRouter* router =
454 web_ui->bookmark_manager_extension_event_router();
455
456 DCHECK(router);
457 const BookmarkNodeData* drag_data = router->GetBookmarkNodeData();
458 if (drag_data == NULL) {
459 NOTREACHED() <<"Somehow we're dropping null bookmark data";
460 return false;
461 }
462 bookmark_utils::PerformBookmarkDrop(profile(),
463 *drag_data,
464 drop_parent, drop_index);
465
466 router->ClearBookmarkNodeData();
467 return true;
468 } else {
469 NOTREACHED();
470 return false;
471 }
472 }
473
474 bool GetSubtreeBookmarkManagerFunction::RunImpl() {
475 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
476 const BookmarkNode* node;
477 int64 id;
478 std::string id_string;
479 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
480 bool folders_only;
481 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &folders_only));
482 if (id_string == "") {
483 node = model->root_node();
484 } else {
485 if (!base::StringToInt64(id_string, &id)) {
486 error_ = keys::kInvalidIdError;
487 return false;
488 }
489 node = model->GetNodeByID(id);
490 }
491 if (!node) {
492 error_ = keys::kNoNodeError;
493 return false;
494 }
495 scoped_ptr<ListValue> json(new ListValue());
496 if (folders_only) {
497 extensions::bookmark_api_helpers::AddNodeFoldersOnly(node,
498 json.get(),
499 true);
500 } else {
501 extensions::bookmark_api_helpers::AddNode(node, json.get(), true);
502 }
503 SetResult(json.release());
504 return true;
505 }
506
507 bool CanEditBookmarkManagerFunction::RunImpl() {
508 PrefServiceBase* prefs = PrefServiceBase::FromBrowserContext(profile_);
509 SetResult(new base::FundamentalValue(
510 prefs->GetBoolean(prefs::kEditBookmarksEnabled)));
511 return true;
512 }
513
514 bool RecordLaunchBookmarkFunction::RunImpl() {
515 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_MANAGER);
516 return true;
517 }
518
519 bool CanOpenNewWindowsBookmarkFunction::RunImpl() {
520 bool can_open_new_windows = true;
521
522 #if defined(OS_WIN)
523 if (win8::IsSingleWindowMetroMode())
524 can_open_new_windows = false;
525 #endif // OS_WIN
526
527 SetResult(new base::FundamentalValue(can_open_new_windows));
528 return true;
529 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698