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 bookmarks::BookmarkNode
;
35 using content::PageNavigator
;
37 BookmarkContextMenuController::BookmarkContextMenuController(
38 gfx::NativeWindow parent_window
,
39 BookmarkContextMenuControllerDelegate
* delegate
,
42 PageNavigator
* navigator
,
43 const BookmarkNode
* parent
,
44 const std::vector
<const BookmarkNode
*>& selection
)
45 : parent_window_(parent_window
),
49 navigator_(navigator
),
51 selection_(selection
),
52 model_(BookmarkModelFactory::GetForProfile(profile
)) {
54 DCHECK(model_
->loaded());
55 menu_model_
.reset(new ui::SimpleMenuModel(this));
56 model_
->AddObserver(this);
61 BookmarkContextMenuController::~BookmarkContextMenuController() {
63 model_
->RemoveObserver(this);
66 void BookmarkContextMenuController::BuildMenu() {
67 if (selection_
.size() == 1 && selection_
[0]->is_url()) {
68 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
,
69 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB
);
70 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
71 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW
);
72 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
73 IDS_BOOKMARK_BAR_OPEN_INCOGNITO
);
75 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
, IDS_BOOKMARK_BAR_OPEN_ALL
);
76 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
77 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
);
78 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
79 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
);
83 if (selection_
.size() == 1 && selection_
[0]->is_folder()) {
84 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER
, IDS_BOOKMARK_BAR_RENAME_FOLDER
);
86 AddItem(IDC_BOOKMARK_BAR_EDIT
, IDS_BOOKMARK_BAR_EDIT
);
90 AddItem(IDC_CUT
, IDS_CUT
);
91 AddItem(IDC_COPY
, IDS_COPY
);
92 AddItem(IDC_PASTE
, IDS_PASTE
);
95 AddItem(IDC_BOOKMARK_BAR_REMOVE
, IDS_BOOKMARK_BAR_REMOVE
);
96 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
97 switches::kEnableBookmarkUndo
)) {
98 AddItem(IDC_BOOKMARK_BAR_UNDO
, IDS_BOOKMARK_BAR_UNDO
);
99 AddItem(IDC_BOOKMARK_BAR_REDO
, IDS_BOOKMARK_BAR_REDO
);
103 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK
);
104 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER
, IDS_BOOKMARK_BAR_NEW_FOLDER
);
107 AddItem(IDC_BOOKMARK_MANAGER
, IDS_BOOKMARK_MANAGER
);
108 // Use the native host desktop type in tests.
109 if (chrome::IsAppsShortcutEnabled(
111 browser_
? browser_
->host_desktop_type()
112 : chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
113 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
,
114 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
);
116 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
117 IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS_DEFAULT_NAME
);
118 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW
, IDS_SHOW_BOOKMARK_BAR
);
121 void BookmarkContextMenuController::AddItem(int id
, int localization_id
) {
122 menu_model_
->AddItemWithStringId(id
, localization_id
);
125 void BookmarkContextMenuController::AddSeparator() {
126 menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
129 void BookmarkContextMenuController::AddCheckboxItem(int id
,
130 int localization_id
) {
131 menu_model_
->AddCheckItemWithStringId(id
, localization_id
);
134 void BookmarkContextMenuController::ExecuteCommand(int id
, int event_flags
) {
136 delegate_
->WillExecuteCommand(id
, selection_
);
139 case IDC_BOOKMARK_BAR_OPEN_ALL
:
140 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
141 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
: {
142 WindowOpenDisposition initial_disposition
;
143 if (id
== IDC_BOOKMARK_BAR_OPEN_ALL
) {
144 initial_disposition
= NEW_BACKGROUND_TAB
;
145 content::RecordAction(
146 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
147 } else if (id
== IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
) {
148 initial_disposition
= NEW_WINDOW
;
149 content::RecordAction(
150 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
152 initial_disposition
= OFF_THE_RECORD
;
153 content::RecordAction(
154 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
156 chrome::OpenAll(parent_window_
, navigator_
, selection_
,
157 initial_disposition
, profile_
);
161 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
162 case IDC_BOOKMARK_BAR_EDIT
:
163 content::RecordAction(
164 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
166 if (selection_
.size() != 1) {
171 BookmarkEditor::Show(
174 BookmarkEditor::EditDetails::EditNode(selection_
[0]),
175 selection_
[0]->is_url() ? BookmarkEditor::SHOW_TREE
:
176 BookmarkEditor::NO_TREE
);
179 case IDC_BOOKMARK_BAR_UNDO
: {
180 content::RecordAction(
181 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
182 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
187 case IDC_BOOKMARK_BAR_REDO
: {
188 content::RecordAction(
189 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
190 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
195 case IDC_BOOKMARK_BAR_REMOVE
: {
196 content::RecordAction(
197 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
199 for (size_t i
= 0; i
< selection_
.size(); ++i
) {
200 int index
= selection_
[i
]->parent()->GetIndexOf(selection_
[i
]);
202 model_
->Remove(selection_
[i
]->parent(), index
);
208 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
: {
209 content::RecordAction(
210 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
213 const BookmarkNode
* parent
=
214 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
216 base::string16 title
;
217 chrome::GetURLAndTitleToBookmark(
218 browser_
->tab_strip_model()->GetActiveWebContents(),
220 BookmarkEditor::Show(parent_window_
,
222 BookmarkEditor::EditDetails::AddNodeInFolder(
223 parent
, index
, url
, title
),
224 BookmarkEditor::SHOW_TREE
);
228 case IDC_BOOKMARK_BAR_NEW_FOLDER
: {
229 content::RecordAction(
230 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
233 const BookmarkNode
* parent
=
234 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
235 BookmarkEditor::Show(
238 BookmarkEditor::EditDetails::AddFolder(parent
, index
),
239 BookmarkEditor::SHOW_TREE
);
243 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
244 chrome::ToggleBookmarkBarWhenVisible(profile_
);
247 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
: {
248 PrefService
* prefs
= profile_
->GetPrefs();
250 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
251 !prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
));
255 case IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
: {
256 PrefService
* prefs
= profile_
->GetPrefs();
258 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
,
260 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
));
264 case IDC_BOOKMARK_MANAGER
: {
265 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
266 if (selection_
.size() != 1)
267 chrome::ShowBookmarkManager(browser_
);
268 else if (selection_
[0]->is_folder())
269 chrome::ShowBookmarkManagerForNode(browser_
, selection_
[0]->id());
271 chrome::ShowBookmarkManagerForNode(browser_
, parent_
->id());
273 chrome::ShowBookmarkManager(browser_
);
278 bookmarks::CopyToClipboard(model_
, selection_
, true);
282 bookmarks::CopyToClipboard(model_
, selection_
, false);
287 const BookmarkNode
* paste_target
=
288 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
292 bookmarks::PasteFromClipboard(model_
, paste_target
, index
);
301 delegate_
->DidExecuteCommand(id
);
304 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id
)
306 return command_id
== IDC_BOOKMARK_BAR_UNDO
||
307 command_id
== IDC_BOOKMARK_BAR_REDO
||
308 command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
;
311 base::string16
BookmarkContextMenuController::GetLabelForCommandId(
312 int command_id
) const {
313 if (command_id
== IDC_BOOKMARK_BAR_UNDO
) {
314 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
315 undo_manager()->GetUndoLabel();
317 if (command_id
== IDC_BOOKMARK_BAR_REDO
) {
318 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
319 undo_manager()->GetRedoLabel();
321 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
322 ChromeBookmarkClient
* client
=
323 ChromeBookmarkClientFactory::GetForProfile(profile_
);
324 return l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
325 client
->managed_node()->GetTitle());
329 return base::string16();
332 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id
) const {
333 PrefService
* prefs
= profile_
->GetPrefs();
334 if (command_id
== IDC_BOOKMARK_BAR_ALWAYS_SHOW
)
335 return prefs
->GetBoolean(bookmarks::prefs::kShowBookmarkBar
);
336 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
)
337 return prefs
->GetBoolean(
338 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
);
340 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
, command_id
);
341 return prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
344 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id
) const {
345 PrefService
* prefs
= profile_
->GetPrefs();
347 bool is_root_node
= selection_
.size() == 1 &&
348 selection_
[0]->parent() == model_
->root_node();
349 bool can_edit
= prefs
->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled
) &&
350 bookmarks::CanAllBeEditedByUser(model_
->client(), selection_
);
351 IncognitoModePrefs::Availability incognito_avail
=
352 IncognitoModePrefs::GetAvailability(prefs
);
354 switch (command_id
) {
355 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO
:
356 return !profile_
->IsOffTheRecord() &&
357 incognito_avail
!= IncognitoModePrefs::DISABLED
;
359 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
360 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_
, profile_
)
362 !profile_
->IsOffTheRecord() &&
363 incognito_avail
!= IncognitoModePrefs::DISABLED
;
365 case IDC_BOOKMARK_BAR_OPEN_ALL
:
366 return chrome::HasBookmarkURLs(selection_
);
367 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
:
368 return chrome::HasBookmarkURLs(selection_
) &&
369 incognito_avail
!= IncognitoModePrefs::FORCED
;
371 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
372 case IDC_BOOKMARK_BAR_EDIT
:
373 return selection_
.size() == 1 && !is_root_node
&& can_edit
;
375 case IDC_BOOKMARK_BAR_UNDO
:
377 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
378 undo_manager()->undo_count() > 0;
380 case IDC_BOOKMARK_BAR_REDO
:
382 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
383 undo_manager()->redo_count() > 0;
385 case IDC_BOOKMARK_BAR_REMOVE
:
386 return !selection_
.empty() && !is_root_node
&& can_edit
;
388 case IDC_BOOKMARK_BAR_NEW_FOLDER
:
389 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
:
390 return can_edit
&& model_
->client()->CanBeEditedByUser(parent_
) &&
391 bookmarks::GetParentForNewNodes(parent_
, selection_
, NULL
) != NULL
;
393 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
394 return !prefs
->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar
);
396 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
:
397 return !prefs
->IsManagedPreference(
398 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
402 return !selection_
.empty() && !is_root_node
&&
403 (command_id
== IDC_COPY
|| can_edit
);
406 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
408 ((!selection_
.empty() &&
409 bookmarks::CanPasteFromClipboard(model_
, selection_
[0])) ||
410 bookmarks::CanPasteFromClipboard(model_
, parent_
));
415 bool BookmarkContextMenuController::IsCommandIdVisible(int command_id
) const {
416 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
417 // The option to hide the Managed Bookmarks folder is only available if
418 // there are any managed bookmarks configured at all.
419 ChromeBookmarkClient
* client
=
420 ChromeBookmarkClientFactory::GetForProfile(profile_
);
421 return !client
->managed_node()->empty();
427 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
429 ui::Accelerator
* accelerator
) {
433 void BookmarkContextMenuController::BookmarkModelChanged() {
435 delegate_
->CloseMenu();