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/managed_bookmark_service_factory.h"
13 #include "chrome/browser/prefs/incognito_mode_prefs.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.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 "chrome/grit/generated_resources.h"
24 #include "components/bookmarks/browser/bookmark_client.h"
25 #include "components/bookmarks/browser/bookmark_model.h"
26 #include "components/bookmarks/browser/bookmark_utils.h"
27 #include "components/bookmarks/managed/managed_bookmark_service.h"
28 #include "components/undo/bookmark_undo_service.h"
29 #include "content/public/browser/page_navigator.h"
30 #include "content/public/browser/user_metrics.h"
31 #include "grit/components_strings.h"
32 #include "ui/base/l10n/l10n_util.h"
34 using base::UserMetricsAction
;
35 using bookmarks::BookmarkNode
;
36 using content::PageNavigator
;
38 BookmarkContextMenuController::BookmarkContextMenuController(
39 gfx::NativeWindow parent_window
,
40 BookmarkContextMenuControllerDelegate
* delegate
,
43 PageNavigator
* navigator
,
44 const BookmarkNode
* parent
,
45 const std::vector
<const BookmarkNode
*>& selection
)
46 : parent_window_(parent_window
),
50 navigator_(navigator
),
52 selection_(selection
),
53 model_(BookmarkModelFactory::GetForProfile(profile
)),
56 DCHECK(model_
->loaded());
57 menu_model_
.reset(new ui::SimpleMenuModel(this));
58 model_
->AddObserver(this);
63 BookmarkContextMenuController::~BookmarkContextMenuController() {
65 model_
->RemoveObserver(this);
68 void BookmarkContextMenuController::BuildMenu() {
69 if (selection_
.size() == 1 && selection_
[0]->is_url()) {
70 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
,
71 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB
);
72 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
73 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW
);
74 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
75 IDS_BOOKMARK_BAR_OPEN_INCOGNITO
);
77 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
, IDS_BOOKMARK_BAR_OPEN_ALL
);
78 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
79 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
);
80 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
81 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
);
85 if (selection_
.size() == 1 && selection_
[0]->is_folder()) {
86 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER
, IDS_BOOKMARK_BAR_RENAME_FOLDER
);
88 AddItem(IDC_BOOKMARK_BAR_EDIT
, IDS_BOOKMARK_BAR_EDIT
);
92 AddItem(IDC_CUT
, IDS_CUT
);
93 AddItem(IDC_COPY
, IDS_COPY
);
94 AddItem(IDC_PASTE
, IDS_PASTE
);
97 AddItem(IDC_BOOKMARK_BAR_REMOVE
, IDS_BOOKMARK_BAR_REMOVE
);
98 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
99 switches::kEnableBookmarkUndo
)) {
100 AddItem(IDC_BOOKMARK_BAR_UNDO
, IDS_BOOKMARK_BAR_UNDO
);
101 AddItem(IDC_BOOKMARK_BAR_REDO
, IDS_BOOKMARK_BAR_REDO
);
105 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK
);
106 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER
, IDS_BOOKMARK_BAR_NEW_FOLDER
);
109 AddItem(IDC_BOOKMARK_MANAGER
, IDS_BOOKMARK_MANAGER
);
110 // Use the native host desktop type in tests.
111 if (chrome::IsAppsShortcutEnabled(
113 browser_
? browser_
->host_desktop_type()
114 : chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
115 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
,
116 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
);
118 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
119 IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS_DEFAULT_NAME
);
120 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW
, IDS_SHOW_BOOKMARK_BAR
);
123 void BookmarkContextMenuController::AddItem(int id
, int localization_id
) {
124 menu_model_
->AddItemWithStringId(id
, localization_id
);
127 void BookmarkContextMenuController::AddSeparator() {
128 menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
131 void BookmarkContextMenuController::AddCheckboxItem(int id
,
132 int localization_id
) {
133 menu_model_
->AddCheckItemWithStringId(id
, localization_id
);
136 void BookmarkContextMenuController::ExecuteCommand(int id
, int event_flags
) {
138 delegate_
->WillExecuteCommand(id
, selection_
);
140 base::WeakPtr
<BookmarkContextMenuController
> ref(weak_factory_
.GetWeakPtr());
143 case IDC_BOOKMARK_BAR_OPEN_ALL
:
144 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
145 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
: {
146 WindowOpenDisposition initial_disposition
;
147 if (id
== IDC_BOOKMARK_BAR_OPEN_ALL
) {
148 initial_disposition
= NEW_BACKGROUND_TAB
;
149 content::RecordAction(
150 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
151 } else if (id
== IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
) {
152 initial_disposition
= NEW_WINDOW
;
153 content::RecordAction(
154 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
156 initial_disposition
= OFF_THE_RECORD
;
157 content::RecordAction(
158 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
160 chrome::OpenAll(parent_window_
, navigator_
, selection_
,
161 initial_disposition
, profile_
);
165 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
166 case IDC_BOOKMARK_BAR_EDIT
:
167 content::RecordAction(
168 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
170 if (selection_
.size() != 1) {
175 BookmarkEditor::Show(
178 BookmarkEditor::EditDetails::EditNode(selection_
[0]),
179 selection_
[0]->is_url() ? BookmarkEditor::SHOW_TREE
:
180 BookmarkEditor::NO_TREE
);
183 case IDC_BOOKMARK_BAR_UNDO
: {
184 content::RecordAction(
185 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
186 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
191 case IDC_BOOKMARK_BAR_REDO
: {
192 content::RecordAction(
193 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
194 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
199 case IDC_BOOKMARK_BAR_REMOVE
: {
200 content::RecordAction(
201 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
203 for (size_t i
= 0; i
< selection_
.size(); ++i
) {
204 int index
= selection_
[i
]->parent()->GetIndexOf(selection_
[i
]);
206 model_
->Remove(selection_
[i
]);
212 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
: {
213 content::RecordAction(
214 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
217 const BookmarkNode
* parent
=
218 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
220 base::string16 title
;
221 chrome::GetURLAndTitleToBookmark(
222 browser_
->tab_strip_model()->GetActiveWebContents(),
224 BookmarkEditor::Show(parent_window_
,
226 BookmarkEditor::EditDetails::AddNodeInFolder(
227 parent
, index
, url
, title
),
228 BookmarkEditor::SHOW_TREE
);
232 case IDC_BOOKMARK_BAR_NEW_FOLDER
: {
233 content::RecordAction(
234 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
237 const BookmarkNode
* parent
=
238 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
239 BookmarkEditor::Show(
242 BookmarkEditor::EditDetails::AddFolder(parent
, index
),
243 BookmarkEditor::SHOW_TREE
);
247 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
248 chrome::ToggleBookmarkBarWhenVisible(profile_
);
251 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
: {
252 PrefService
* prefs
= profile_
->GetPrefs();
254 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
255 !prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
));
259 case IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
: {
260 PrefService
* prefs
= profile_
->GetPrefs();
262 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
,
264 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
));
268 case IDC_BOOKMARK_MANAGER
: {
269 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
270 if (selection_
.size() != 1)
271 chrome::ShowBookmarkManager(browser_
);
272 else if (selection_
[0]->is_folder())
273 chrome::ShowBookmarkManagerForNode(browser_
, selection_
[0]->id());
275 chrome::ShowBookmarkManagerForNode(browser_
, parent_
->id());
277 chrome::ShowBookmarkManager(browser_
);
282 bookmarks::CopyToClipboard(model_
, selection_
, true);
286 bookmarks::CopyToClipboard(model_
, selection_
, false);
291 const BookmarkNode
* paste_target
=
292 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
296 bookmarks::PasteFromClipboard(model_
, paste_target
, index
);
304 // It's possible executing the command resulted in deleting |this|.
309 delegate_
->DidExecuteCommand(id
);
312 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id
)
314 return command_id
== IDC_BOOKMARK_BAR_UNDO
||
315 command_id
== IDC_BOOKMARK_BAR_REDO
||
316 command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
;
319 base::string16
BookmarkContextMenuController::GetLabelForCommandId(
320 int command_id
) const {
321 if (command_id
== IDC_BOOKMARK_BAR_UNDO
) {
322 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
323 undo_manager()->GetUndoLabel();
325 if (command_id
== IDC_BOOKMARK_BAR_REDO
) {
326 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
327 undo_manager()->GetRedoLabel();
329 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
330 bookmarks::ManagedBookmarkService
* managed
=
331 ManagedBookmarkServiceFactory::GetForProfile(profile_
);
332 return l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
333 managed
->managed_node()->GetTitle());
337 return base::string16();
340 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id
) const {
341 PrefService
* prefs
= profile_
->GetPrefs();
342 if (command_id
== IDC_BOOKMARK_BAR_ALWAYS_SHOW
)
343 return prefs
->GetBoolean(bookmarks::prefs::kShowBookmarkBar
);
344 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
)
345 return prefs
->GetBoolean(
346 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
);
348 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
, command_id
);
349 return prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
352 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id
) const {
353 PrefService
* prefs
= profile_
->GetPrefs();
355 bool is_root_node
= selection_
.size() == 1 &&
356 selection_
[0]->parent() == model_
->root_node();
357 bool can_edit
= prefs
->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled
) &&
358 bookmarks::CanAllBeEditedByUser(model_
->client(), selection_
);
359 IncognitoModePrefs::Availability incognito_avail
=
360 IncognitoModePrefs::GetAvailability(prefs
);
362 switch (command_id
) {
363 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO
:
364 return !profile_
->IsOffTheRecord() &&
365 incognito_avail
!= IncognitoModePrefs::DISABLED
;
367 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
368 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_
, profile_
)
370 !profile_
->IsOffTheRecord() &&
371 incognito_avail
!= IncognitoModePrefs::DISABLED
;
373 case IDC_BOOKMARK_BAR_OPEN_ALL
:
374 return chrome::HasBookmarkURLs(selection_
);
375 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
:
376 return chrome::HasBookmarkURLs(selection_
) &&
377 incognito_avail
!= IncognitoModePrefs::FORCED
;
379 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
380 case IDC_BOOKMARK_BAR_EDIT
:
381 return selection_
.size() == 1 && !is_root_node
&& can_edit
;
383 case IDC_BOOKMARK_BAR_UNDO
:
385 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
386 undo_manager()->undo_count() > 0;
388 case IDC_BOOKMARK_BAR_REDO
:
390 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
391 undo_manager()->redo_count() > 0;
393 case IDC_BOOKMARK_BAR_REMOVE
:
394 return !selection_
.empty() && !is_root_node
&& can_edit
;
396 case IDC_BOOKMARK_BAR_NEW_FOLDER
:
397 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
:
398 return can_edit
&& model_
->client()->CanBeEditedByUser(parent_
) &&
399 bookmarks::GetParentForNewNodes(parent_
, selection_
, NULL
) != NULL
;
401 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
402 return !prefs
->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar
);
404 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
:
405 return !prefs
->IsManagedPreference(
406 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
410 return !selection_
.empty() && !is_root_node
&&
411 (command_id
== IDC_COPY
|| can_edit
);
414 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
416 ((!selection_
.empty() &&
417 bookmarks::CanPasteFromClipboard(model_
, selection_
[0])) ||
418 bookmarks::CanPasteFromClipboard(model_
, parent_
));
423 bool BookmarkContextMenuController::IsCommandIdVisible(int command_id
) const {
424 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
425 // The option to hide the Managed Bookmarks folder is only available if
426 // there are any managed bookmarks configured at all.
427 bookmarks::ManagedBookmarkService
* managed
=
428 ManagedBookmarkServiceFactory::GetForProfile(profile_
);
429 return !managed
->managed_node()->empty();
435 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
437 ui::Accelerator
* accelerator
) {
441 void BookmarkContextMenuController::BookmarkModelChanged() {
443 delegate_
->CloseMenu();