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/prefs/incognito_mode_prefs.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
15 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/chrome_pages.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/browser/undo/bookmark_undo_service.h"
20 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/bookmarks/browser/bookmark_model.h"
24 #include "components/bookmarks/browser/bookmark_utils.h"
25 #include "content/public/browser/page_navigator.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "grit/generated_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
30 using base::UserMetricsAction
;
31 using content::PageNavigator
;
33 BookmarkContextMenuController::BookmarkContextMenuController(
34 gfx::NativeWindow parent_window
,
35 BookmarkContextMenuControllerDelegate
* delegate
,
38 PageNavigator
* navigator
,
39 const BookmarkNode
* parent
,
40 const std::vector
<const BookmarkNode
*>& selection
)
41 : parent_window_(parent_window
),
45 navigator_(navigator
),
47 selection_(selection
),
48 model_(BookmarkModelFactory::GetForProfile(profile
)) {
50 DCHECK(model_
->loaded());
51 menu_model_
.reset(new ui::SimpleMenuModel(this));
52 model_
->AddObserver(this);
57 BookmarkContextMenuController::~BookmarkContextMenuController() {
59 model_
->RemoveObserver(this);
62 void BookmarkContextMenuController::BuildMenu() {
63 if (selection_
.size() == 1 && selection_
[0]->is_url()) {
64 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
,
65 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB
);
66 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
67 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW
);
68 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
69 IDS_BOOKMARK_BAR_OPEN_INCOGNITO
);
71 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
, IDS_BOOKMARK_BAR_OPEN_ALL
);
72 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
73 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
);
74 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
75 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
);
79 if (selection_
.size() == 1 && selection_
[0]->is_folder()) {
80 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER
, IDS_BOOKMARK_BAR_RENAME_FOLDER
);
82 AddItem(IDC_BOOKMARK_BAR_EDIT
, IDS_BOOKMARK_BAR_EDIT
);
86 AddItem(IDC_CUT
, IDS_CUT
);
87 AddItem(IDC_COPY
, IDS_COPY
);
88 AddItem(IDC_PASTE
, IDS_PASTE
);
91 AddItem(IDC_BOOKMARK_BAR_REMOVE
, IDS_BOOKMARK_BAR_REMOVE
);
92 if (CommandLine::ForCurrentProcess()->HasSwitch(
93 switches::kEnableBookmarkUndo
)) {
94 AddItem(IDC_BOOKMARK_BAR_UNDO
, IDS_BOOKMARK_BAR_UNDO
);
95 AddItem(IDC_BOOKMARK_BAR_REDO
, IDS_BOOKMARK_BAR_REDO
);
99 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK
);
100 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER
, IDS_BOOKMARK_BAR_NEW_FOLDER
);
103 AddItem(IDC_BOOKMARK_MANAGER
, IDS_BOOKMARK_MANAGER
);
104 // Use the native host desktop type in tests.
105 if (chrome::IsAppsShortcutEnabled(
107 browser_
? browser_
->host_desktop_type()
108 : chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
109 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
,
110 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
);
112 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW
, IDS_SHOW_BOOKMARK_BAR
);
115 void BookmarkContextMenuController::AddItem(int id
, int localization_id
) {
116 menu_model_
->AddItemWithStringId(id
, localization_id
);
119 void BookmarkContextMenuController::AddSeparator() {
120 menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
123 void BookmarkContextMenuController::AddCheckboxItem(int id
,
124 int localization_id
) {
125 menu_model_
->AddCheckItemWithStringId(id
, localization_id
);
128 void BookmarkContextMenuController::ExecuteCommand(int id
, int event_flags
) {
130 delegate_
->WillExecuteCommand(id
, selection_
);
133 case IDC_BOOKMARK_BAR_OPEN_ALL
:
134 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
135 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
: {
136 WindowOpenDisposition initial_disposition
;
137 if (id
== IDC_BOOKMARK_BAR_OPEN_ALL
) {
138 initial_disposition
= NEW_BACKGROUND_TAB
;
139 content::RecordAction(
140 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
141 } else if (id
== IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
) {
142 initial_disposition
= NEW_WINDOW
;
143 content::RecordAction(
144 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
146 initial_disposition
= OFF_THE_RECORD
;
147 content::RecordAction(
148 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
150 chrome::OpenAll(parent_window_
, navigator_
, selection_
,
151 initial_disposition
, profile_
);
155 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
156 case IDC_BOOKMARK_BAR_EDIT
:
157 content::RecordAction(
158 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
160 if (selection_
.size() != 1) {
165 BookmarkEditor::Show(
168 BookmarkEditor::EditDetails::EditNode(selection_
[0]),
169 selection_
[0]->is_url() ? BookmarkEditor::SHOW_TREE
:
170 BookmarkEditor::NO_TREE
);
173 case IDC_BOOKMARK_BAR_UNDO
: {
174 content::RecordAction(
175 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
176 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
181 case IDC_BOOKMARK_BAR_REDO
: {
182 content::RecordAction(
183 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
184 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
189 case IDC_BOOKMARK_BAR_REMOVE
: {
190 content::RecordAction(
191 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
193 for (size_t i
= 0; i
< selection_
.size(); ++i
) {
194 int index
= selection_
[i
]->parent()->GetIndexOf(selection_
[i
]);
196 model_
->Remove(selection_
[i
]->parent(), index
);
202 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
: {
203 content::RecordAction(
204 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
207 const BookmarkNode
* parent
=
208 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
210 base::string16 title
;
211 chrome::GetURLAndTitleToBookmark(
212 browser_
->tab_strip_model()->GetActiveWebContents(),
214 BookmarkEditor::Show(parent_window_
,
216 BookmarkEditor::EditDetails::AddNodeInFolder(
217 parent
, index
, url
, title
),
218 BookmarkEditor::SHOW_TREE
);
222 case IDC_BOOKMARK_BAR_NEW_FOLDER
: {
223 content::RecordAction(
224 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
227 const BookmarkNode
* parent
=
228 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
229 BookmarkEditor::Show(
232 BookmarkEditor::EditDetails::AddFolder(parent
, index
),
233 BookmarkEditor::SHOW_TREE
);
237 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
238 chrome::ToggleBookmarkBarWhenVisible(profile_
);
241 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
: {
242 PrefService
* prefs
= profile_
->GetPrefs();
244 prefs::kShowAppsShortcutInBookmarkBar
,
245 !prefs
->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar
));
249 case IDC_BOOKMARK_MANAGER
: {
250 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
251 if (selection_
.size() != 1)
252 chrome::ShowBookmarkManager(browser_
);
253 else if (selection_
[0]->is_folder())
254 chrome::ShowBookmarkManagerForNode(browser_
, selection_
[0]->id());
256 chrome::ShowBookmarkManagerForNode(browser_
, parent_
->id());
258 chrome::ShowBookmarkManager(browser_
);
263 bookmark_utils::CopyToClipboard(model_
, selection_
, true);
267 bookmark_utils::CopyToClipboard(model_
, selection_
, false);
272 const BookmarkNode
* paste_target
=
273 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
277 bookmark_utils::PasteFromClipboard(model_
, paste_target
, index
);
286 delegate_
->DidExecuteCommand(id
);
289 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id
)
291 return command_id
== IDC_BOOKMARK_BAR_UNDO
||
292 command_id
== IDC_BOOKMARK_BAR_REDO
;
295 base::string16
BookmarkContextMenuController::GetLabelForCommandId(
296 int command_id
) const {
297 if (command_id
== IDC_BOOKMARK_BAR_UNDO
) {
298 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
299 undo_manager()->GetUndoLabel();
301 if (command_id
== IDC_BOOKMARK_BAR_REDO
) {
302 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
303 undo_manager()->GetRedoLabel();
307 return base::string16();
310 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id
) const {
311 PrefService
* prefs
= profile_
->GetPrefs();
312 if (command_id
== IDC_BOOKMARK_BAR_ALWAYS_SHOW
)
313 return prefs
->GetBoolean(prefs::kShowBookmarkBar
);
315 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
, command_id
);
316 return prefs
->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar
);
319 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id
) const {
320 PrefService
* prefs
= profile_
->GetPrefs();
322 bool is_root_node
= selection_
.size() == 1 &&
323 selection_
[0]->parent() == model_
->root_node();
324 bool can_edit
= prefs
->GetBoolean(prefs::kEditBookmarksEnabled
);
325 IncognitoModePrefs::Availability incognito_avail
=
326 IncognitoModePrefs::GetAvailability(prefs
);
327 switch (command_id
) {
328 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO
:
329 return !profile_
->IsOffTheRecord() &&
330 incognito_avail
!= IncognitoModePrefs::DISABLED
;
332 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
333 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_
, profile_
)
335 !profile_
->IsOffTheRecord() &&
336 incognito_avail
!= IncognitoModePrefs::DISABLED
;
338 case IDC_BOOKMARK_BAR_OPEN_ALL
:
339 return chrome::HasBookmarkURLs(selection_
);
340 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
:
341 return chrome::HasBookmarkURLs(selection_
) &&
342 incognito_avail
!= IncognitoModePrefs::FORCED
;
344 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
345 case IDC_BOOKMARK_BAR_EDIT
:
346 return selection_
.size() == 1 && !is_root_node
&& can_edit
;
348 case IDC_BOOKMARK_BAR_UNDO
:
350 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
351 undo_manager()->undo_count() > 0;
353 case IDC_BOOKMARK_BAR_REDO
:
355 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
356 undo_manager()->redo_count() > 0;
358 case IDC_BOOKMARK_BAR_REMOVE
:
359 return !selection_
.empty() && !is_root_node
&& can_edit
;
361 case IDC_BOOKMARK_BAR_NEW_FOLDER
:
362 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
:
363 return can_edit
&& bookmark_utils::GetParentForNewNodes(
364 parent_
, selection_
, NULL
) != NULL
;
366 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
367 return !prefs
->IsManagedPreference(prefs::kShowBookmarkBar
);
369 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
:
370 return !prefs
->IsManagedPreference(prefs::kShowAppsShortcutInBookmarkBar
);
374 return !selection_
.empty() && !is_root_node
&&
375 (command_id
== IDC_COPY
|| can_edit
);
378 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
380 ((!selection_
.empty() &&
381 bookmark_utils::CanPasteFromClipboard(selection_
[0])) ||
382 bookmark_utils::CanPasteFromClipboard(parent_
));
387 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
389 ui::Accelerator
* accelerator
) {
393 void BookmarkContextMenuController::BookmarkModelChanged() {
395 delegate_
->CloseMenu();