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.
5 #include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/prefs/pref_service.h"
10 #include "chrome/app/chrome_command_ids.h"
11 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/bookmarks/chrome_bookmark_client.h"
13 #include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
14 #include "chrome/browser/prefs/incognito_mode_prefs.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
17 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/chrome_pages.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/undo/bookmark_undo_service.h"
22 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "components/bookmarks/browser/bookmark_client.h"
27 #include "components/bookmarks/browser/bookmark_model.h"
28 #include "components/bookmarks/browser/bookmark_utils.h"
29 #include "content/public/browser/page_navigator.h"
30 #include "content/public/browser/user_metrics.h"
31 #include "ui/base/l10n/l10n_util.h"
33 using base::UserMetricsAction;
34 using content::PageNavigator;
36 BookmarkContextMenuController::BookmarkContextMenuController(
37 gfx::NativeWindow parent_window,
38 BookmarkContextMenuControllerDelegate* delegate,
41 PageNavigator* navigator,
42 const BookmarkNode* parent,
43 const std::vector<const BookmarkNode*>& selection)
44 : parent_window_(parent_window),
48 navigator_(navigator),
50 selection_(selection),
51 model_(BookmarkModelFactory::GetForProfile(profile)) {
53 DCHECK(model_->loaded());
54 menu_model_.reset(new ui::SimpleMenuModel(this));
55 model_->AddObserver(this);
60 BookmarkContextMenuController::~BookmarkContextMenuController() {
62 model_->RemoveObserver(this);
65 void BookmarkContextMenuController::BuildMenu() {
66 if (selection_.size() == 1 && selection_[0]->is_url()) {
67 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL,
68 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB);
69 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW,
70 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW);
71 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
72 IDS_BOOKMARK_BAR_OPEN_INCOGNITO);
74 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL, IDS_BOOKMARK_BAR_OPEN_ALL);
75 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW,
76 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW);
77 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
78 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO);
82 if (selection_.size() == 1 && selection_[0]->is_folder()) {
83 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER, IDS_BOOKMARK_BAR_RENAME_FOLDER);
85 AddItem(IDC_BOOKMARK_BAR_EDIT, IDS_BOOKMARK_BAR_EDIT);
89 AddItem(IDC_CUT, IDS_CUT);
90 AddItem(IDC_COPY, IDS_COPY);
91 AddItem(IDC_PASTE, IDS_PASTE);
94 AddItem(IDC_BOOKMARK_BAR_REMOVE, IDS_BOOKMARK_BAR_REMOVE);
95 if (CommandLine::ForCurrentProcess()->HasSwitch(
96 switches::kEnableBookmarkUndo)) {
97 AddItem(IDC_BOOKMARK_BAR_UNDO, IDS_BOOKMARK_BAR_UNDO);
98 AddItem(IDC_BOOKMARK_BAR_REDO, IDS_BOOKMARK_BAR_REDO);
102 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK);
103 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER, IDS_BOOKMARK_BAR_NEW_FOLDER);
106 AddItem(IDC_BOOKMARK_MANAGER, IDS_BOOKMARK_MANAGER);
107 // Use the native host desktop type in tests.
108 if (chrome::IsAppsShortcutEnabled(
110 browser_ ? browser_->host_desktop_type()
111 : chrome::HOST_DESKTOP_TYPE_NATIVE)) {
112 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT,
113 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT);
115 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS,
116 IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS_DEFAULT_NAME);
117 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW, IDS_SHOW_BOOKMARK_BAR);
120 void BookmarkContextMenuController::AddItem(int id, int localization_id) {
121 menu_model_->AddItemWithStringId(id, localization_id);
124 void BookmarkContextMenuController::AddSeparator() {
125 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
128 void BookmarkContextMenuController::AddCheckboxItem(int id,
129 int localization_id) {
130 menu_model_->AddCheckItemWithStringId(id, localization_id);
133 void BookmarkContextMenuController::ExecuteCommand(int id, int event_flags) {
135 delegate_->WillExecuteCommand(id, selection_);
138 case IDC_BOOKMARK_BAR_OPEN_ALL:
139 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
140 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW: {
141 WindowOpenDisposition initial_disposition;
142 if (id == IDC_BOOKMARK_BAR_OPEN_ALL) {
143 initial_disposition = NEW_BACKGROUND_TAB;
144 content::RecordAction(
145 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
146 } else if (id == IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW) {
147 initial_disposition = NEW_WINDOW;
148 content::RecordAction(
149 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
151 initial_disposition = OFF_THE_RECORD;
152 content::RecordAction(
153 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
155 chrome::OpenAll(parent_window_, navigator_, selection_,
156 initial_disposition, profile_);
160 case IDC_BOOKMARK_BAR_RENAME_FOLDER:
161 case IDC_BOOKMARK_BAR_EDIT:
162 content::RecordAction(
163 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
165 if (selection_.size() != 1) {
170 BookmarkEditor::Show(
173 BookmarkEditor::EditDetails::EditNode(selection_[0]),
174 selection_[0]->is_url() ? BookmarkEditor::SHOW_TREE :
175 BookmarkEditor::NO_TREE);
178 case IDC_BOOKMARK_BAR_UNDO: {
179 content::RecordAction(
180 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
181 BookmarkUndoServiceFactory::GetForProfile(profile_)->undo_manager()->
186 case IDC_BOOKMARK_BAR_REDO: {
187 content::RecordAction(
188 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
189 BookmarkUndoServiceFactory::GetForProfile(profile_)->undo_manager()->
194 case IDC_BOOKMARK_BAR_REMOVE: {
195 content::RecordAction(
196 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
198 for (size_t i = 0; i < selection_.size(); ++i) {
199 int index = selection_[i]->parent()->GetIndexOf(selection_[i]);
201 model_->Remove(selection_[i]->parent(), index);
207 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK: {
208 content::RecordAction(
209 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
212 const BookmarkNode* parent =
213 bookmarks::GetParentForNewNodes(parent_, selection_, &index);
215 base::string16 title;
216 chrome::GetURLAndTitleToBookmark(
217 browser_->tab_strip_model()->GetActiveWebContents(),
219 BookmarkEditor::Show(parent_window_,
221 BookmarkEditor::EditDetails::AddNodeInFolder(
222 parent, index, url, title),
223 BookmarkEditor::SHOW_TREE);
227 case IDC_BOOKMARK_BAR_NEW_FOLDER: {
228 content::RecordAction(
229 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
232 const BookmarkNode* parent =
233 bookmarks::GetParentForNewNodes(parent_, selection_, &index);
234 BookmarkEditor::Show(
237 BookmarkEditor::EditDetails::AddFolder(parent, index),
238 BookmarkEditor::SHOW_TREE);
242 case IDC_BOOKMARK_BAR_ALWAYS_SHOW:
243 chrome::ToggleBookmarkBarWhenVisible(profile_);
246 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT: {
247 PrefService* prefs = profile_->GetPrefs();
249 bookmarks::prefs::kShowAppsShortcutInBookmarkBar,
250 !prefs->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar));
254 case IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS: {
255 PrefService* prefs = profile_->GetPrefs();
257 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar,
259 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar));
263 case IDC_BOOKMARK_MANAGER: {
264 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
265 if (selection_.size() != 1)
266 chrome::ShowBookmarkManager(browser_);
267 else if (selection_[0]->is_folder())
268 chrome::ShowBookmarkManagerForNode(browser_, selection_[0]->id());
270 chrome::ShowBookmarkManagerForNode(browser_, parent_->id());
272 chrome::ShowBookmarkManager(browser_);
277 bookmarks::CopyToClipboard(model_, selection_, true);
281 bookmarks::CopyToClipboard(model_, selection_, false);
286 const BookmarkNode* paste_target =
287 bookmarks::GetParentForNewNodes(parent_, selection_, &index);
291 bookmarks::PasteFromClipboard(model_, paste_target, index);
300 delegate_->DidExecuteCommand(id);
303 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id)
305 return command_id == IDC_BOOKMARK_BAR_UNDO ||
306 command_id == IDC_BOOKMARK_BAR_REDO ||
307 command_id == IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS;
310 base::string16 BookmarkContextMenuController::GetLabelForCommandId(
311 int command_id) const {
312 if (command_id == IDC_BOOKMARK_BAR_UNDO) {
313 return BookmarkUndoServiceFactory::GetForProfile(profile_)->
314 undo_manager()->GetUndoLabel();
316 if (command_id == IDC_BOOKMARK_BAR_REDO) {
317 return BookmarkUndoServiceFactory::GetForProfile(profile_)->
318 undo_manager()->GetRedoLabel();
320 if (command_id == IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS) {
321 ChromeBookmarkClient* client =
322 ChromeBookmarkClientFactory::GetForProfile(profile_);
323 return l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS,
324 client->managed_node()->GetTitle());
328 return base::string16();
331 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id) const {
332 PrefService* prefs = profile_->GetPrefs();
333 if (command_id == IDC_BOOKMARK_BAR_ALWAYS_SHOW)
334 return prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar);
335 if (command_id == IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS)
336 return prefs->GetBoolean(
337 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar);
339 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT, command_id);
340 return prefs->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar);
343 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id) const {
344 PrefService* prefs = profile_->GetPrefs();
346 bool is_root_node = selection_.size() == 1 &&
347 selection_[0]->parent() == model_->root_node();
348 bool can_edit = prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled) &&
349 bookmarks::CanAllBeEditedByUser(model_->client(), selection_);
350 IncognitoModePrefs::Availability incognito_avail =
351 IncognitoModePrefs::GetAvailability(prefs);
353 switch (command_id) {
354 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO:
355 return !profile_->IsOffTheRecord() &&
356 incognito_avail != IncognitoModePrefs::DISABLED;
358 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
359 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_, profile_)
361 !profile_->IsOffTheRecord() &&
362 incognito_avail != IncognitoModePrefs::DISABLED;
364 case IDC_BOOKMARK_BAR_OPEN_ALL:
365 return chrome::HasBookmarkURLs(selection_);
366 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW:
367 return chrome::HasBookmarkURLs(selection_) &&
368 incognito_avail != IncognitoModePrefs::FORCED;
370 case IDC_BOOKMARK_BAR_RENAME_FOLDER:
371 case IDC_BOOKMARK_BAR_EDIT:
372 return selection_.size() == 1 && !is_root_node && can_edit;
374 case IDC_BOOKMARK_BAR_UNDO:
376 BookmarkUndoServiceFactory::GetForProfile(profile_)->
377 undo_manager()->undo_count() > 0;
379 case IDC_BOOKMARK_BAR_REDO:
381 BookmarkUndoServiceFactory::GetForProfile(profile_)->
382 undo_manager()->redo_count() > 0;
384 case IDC_BOOKMARK_BAR_REMOVE:
385 return !selection_.empty() && !is_root_node && can_edit;
387 case IDC_BOOKMARK_BAR_NEW_FOLDER:
388 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK:
389 return can_edit && model_->client()->CanBeEditedByUser(parent_) &&
390 bookmarks::GetParentForNewNodes(parent_, selection_, NULL) != NULL;
392 case IDC_BOOKMARK_BAR_ALWAYS_SHOW:
393 return !prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar);
395 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT:
396 return !prefs->IsManagedPreference(
397 bookmarks::prefs::kShowAppsShortcutInBookmarkBar);
401 return !selection_.empty() && !is_root_node &&
402 (command_id == IDC_COPY || can_edit);
405 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
407 ((!selection_.empty() &&
408 bookmarks::CanPasteFromClipboard(model_, selection_[0])) ||
409 bookmarks::CanPasteFromClipboard(model_, parent_));
414 bool BookmarkContextMenuController::IsCommandIdVisible(int command_id) const {
415 if (command_id == IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS) {
416 // The option to hide the Managed Bookmarks folder is only available if
417 // there are any managed bookmarks configured at all.
418 ChromeBookmarkClient* client =
419 ChromeBookmarkClientFactory::GetForProfile(profile_);
420 return !client->managed_node()->empty();
426 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
428 ui::Accelerator* accelerator) {
432 void BookmarkContextMenuController::BookmarkModelChanged() {
434 delegate_->CloseMenu();