1 // Copyright (c) 2011 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_context_menu_controller.h"
6
7 #include "base/compiler_specific.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/bookmarks/bookmark_editor.h"
10 #include "chrome/browser/bookmarks/bookmark_folder_editor_controller.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_utils.h"
13 #include "chrome/browser/metrics/user_metrics.h"
14 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/common/pref_names.h"
19 #include "content/browser/tab_contents/page_navigator.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
22
BookmarkContextMenuController(gfx::NativeWindow parent_window,BookmarkContextMenuControllerDelegate * delegate,Profile * profile,PageNavigator * navigator,const BookmarkNode * parent,const std::vector<const BookmarkNode * > & selection)23 BookmarkContextMenuController::BookmarkContextMenuController(
24 gfx::NativeWindow parent_window,
25 BookmarkContextMenuControllerDelegate* delegate,
26 Profile* profile,
27 PageNavigator* navigator,
28 const BookmarkNode* parent,
29 const std::vector<const BookmarkNode*>& selection)
30 : parent_window_(parent_window),
31 delegate_(delegate),
32 profile_(profile),
33 navigator_(navigator),
34 parent_(parent),
35 selection_(selection),
36 model_(profile->GetBookmarkModel()) {
37 DCHECK(profile_);
38 DCHECK(model_->IsLoaded());
39 menu_model_.reset(new ui::SimpleMenuModel(this));
40 model_->AddObserver(this);
41
42 BuildMenu();
43 }
44
~BookmarkContextMenuController()45 BookmarkContextMenuController::~BookmarkContextMenuController() {
46 if (model_)
47 model_->RemoveObserver(this);
48 }
49
BuildMenu()50 void BookmarkContextMenuController::BuildMenu() {
51 if (selection_.size() == 1 && selection_[0]->is_url()) {
52 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL,
53 IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB);
54 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW,
55 IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW);
56 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
57 IDS_BOOMARK_BAR_OPEN_INCOGNITO);
58 } else {
59 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL, IDS_BOOMARK_BAR_OPEN_ALL);
60 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW,
61 IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW);
62 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO,
63 IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO);
64 }
65
66 AddSeparator();
67 if (selection_.size() == 1 && selection_[0]->is_folder()) {
68 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER, IDS_BOOKMARK_BAR_RENAME_FOLDER);
69 } else {
70 AddItem(IDC_BOOKMARK_BAR_EDIT, IDS_BOOKMARK_BAR_EDIT);
71 }
72
73 AddSeparator();
74 AddItem(IDC_CUT, IDS_CUT);
75 AddItem(IDC_COPY, IDS_COPY);
76 AddItem(IDC_PASTE, IDS_PASTE);
77
78 AddSeparator();
79 AddItem(IDC_BOOKMARK_BAR_REMOVE, IDS_BOOKMARK_BAR_REMOVE);
80
81 AddSeparator();
82 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK, IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK);
83 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER, IDS_BOOMARK_BAR_NEW_FOLDER);
84
85 AddSeparator();
86 AddItem(IDC_BOOKMARK_MANAGER, IDS_BOOKMARK_MANAGER);
87 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW, IDS_BOOMARK_BAR_ALWAYS_SHOW);
88 }
89
AddItem(int id,int localization_id)90 void BookmarkContextMenuController::AddItem(int id, int localization_id) {
91 menu_model_->AddItemWithStringId(id, localization_id);
92 }
93
AddSeparator()94 void BookmarkContextMenuController::AddSeparator() {
95 menu_model_->AddSeparator();
96 }
97
AddCheckboxItem(int id,int localization_id)98 void BookmarkContextMenuController::AddCheckboxItem(int id,
99 int localization_id) {
100 menu_model_->AddCheckItemWithStringId(id, localization_id);
101 }
102
ExecuteCommand(int id)103 void BookmarkContextMenuController::ExecuteCommand(int id) {
104 if (delegate_)
105 delegate_->WillExecuteCommand();
106
107 switch (id) {
108 case IDC_BOOKMARK_BAR_OPEN_ALL:
109 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
110 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW: {
111 WindowOpenDisposition initial_disposition;
112 if (id == IDC_BOOKMARK_BAR_OPEN_ALL) {
113 initial_disposition = NEW_FOREGROUND_TAB;
114 UserMetrics::RecordAction(
115 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"),
116 profile_);
117 } else if (id == IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW) {
118 initial_disposition = NEW_WINDOW;
119 UserMetrics::RecordAction(
120 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"),
121 profile_);
122 } else {
123 initial_disposition = OFF_THE_RECORD;
124 UserMetrics::RecordAction(
125 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"),
126 profile_);
127 }
128 bookmark_utils::OpenAll(parent_window_, profile_, navigator_, selection_,
129 initial_disposition);
130 break;
131 }
132
133 case IDC_BOOKMARK_BAR_RENAME_FOLDER:
134 case IDC_BOOKMARK_BAR_EDIT:
135 UserMetrics::RecordAction(
136 UserMetricsAction("BookmarkBar_ContextMenu_Edit"),
137 profile_);
138
139 if (selection_.size() != 1) {
140 NOTREACHED();
141 break;
142 }
143
144 if (selection_[0]->is_url()) {
145 BookmarkEditor::Show(parent_window_, profile_, parent_,
146 BookmarkEditor::EditDetails(selection_[0]),
147 BookmarkEditor::SHOW_TREE);
148 } else {
149 BookmarkFolderEditorController::Show(profile_, parent_window_,
150 selection_[0], -1,
151 BookmarkFolderEditorController::EXISTING_BOOKMARK);
152 }
153 break;
154
155 case IDC_BOOKMARK_BAR_REMOVE: {
156 UserMetrics::RecordAction(
157 UserMetricsAction("BookmarkBar_ContextMenu_Remove"),
158 profile_);
159
160 for (size_t i = 0; i < selection_.size(); ++i) {
161 int index = selection_[i]->parent()->GetIndexOf(selection_[i]);
162 if (index > -1)
163 model_->Remove(selection_[i]->parent(), index);
164 }
165 selection_.clear();
166 break;
167 }
168
169 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK: {
170 UserMetrics::RecordAction(
171 UserMetricsAction("BookmarkBar_ContextMenu_Add"),
172 profile_);
173
174 // TODO: this should honor the index from GetParentForNewNodes.
175 BookmarkEditor::Show(
176 parent_window_, profile_,
177 bookmark_utils::GetParentForNewNodes(parent_, selection_, NULL),
178 BookmarkEditor::EditDetails(), BookmarkEditor::SHOW_TREE);
179 break;
180 }
181
182 case IDC_BOOKMARK_BAR_NEW_FOLDER: {
183 UserMetrics::RecordAction(
184 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"),
185 profile_);
186 int index;
187 const BookmarkNode* parent =
188 bookmark_utils::GetParentForNewNodes(parent_, selection_, &index);
189 BookmarkFolderEditorController::Show(profile_, parent_window_, parent,
190 index, BookmarkFolderEditorController::NEW_BOOKMARK);
191 break;
192 }
193
194 case IDC_BOOKMARK_BAR_ALWAYS_SHOW:
195 bookmark_utils::ToggleWhenVisible(profile_);
196 break;
197
198 case IDC_BOOKMARK_MANAGER:
199 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarkManager"),
200 profile_);
201 {
202 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
203 if (browser)
204 browser->OpenBookmarkManager();
205 else
206 NOTREACHED();
207 }
208 break;
209
210 case IDC_CUT:
211 bookmark_utils::CopyToClipboard(model_, selection_, true);
212 break;
213
214 case IDC_COPY:
215 bookmark_utils::CopyToClipboard(model_, selection_, false);
216 break;
217
218 case IDC_PASTE: {
219 int index;
220 const BookmarkNode* paste_target =
221 bookmark_utils::GetParentForNewNodes(parent_, selection_, &index);
222 if (!paste_target)
223 return;
224
225 bookmark_utils::PasteFromClipboard(model_, paste_target, index);
226 break;
227 }
228
229 default:
230 NOTREACHED();
231 }
232
233 if (delegate_)
234 delegate_->DidExecuteCommand();
235 }
236
IsCommandIdChecked(int command_id) const237 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id) const {
238 DCHECK(command_id == IDC_BOOKMARK_BAR_ALWAYS_SHOW);
239 return profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
240 }
241
IsCommandIdEnabled(int command_id) const242 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id) const {
243 bool is_root_node =
244 (selection_.size() == 1 &&
245 selection_[0]->parent() == model_->root_node());
246 bool can_edit =
247 profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled);
248 switch (command_id) {
249 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO:
250 return !profile_->IsOffTheRecord() &&
251 profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
252
253 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO:
254 return HasURLs() && !profile_->IsOffTheRecord() &&
255 profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled);
256
257 case IDC_BOOKMARK_BAR_OPEN_ALL:
258 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW:
259 return HasURLs();
260
261 case IDC_BOOKMARK_BAR_RENAME_FOLDER:
262 case IDC_BOOKMARK_BAR_EDIT:
263 return selection_.size() == 1 && !is_root_node && can_edit;
264
265 case IDC_BOOKMARK_BAR_REMOVE:
266 return !selection_.empty() && !is_root_node && can_edit;
267
268 case IDC_BOOKMARK_BAR_NEW_FOLDER:
269 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK:
270 return can_edit && bookmark_utils::GetParentForNewNodes(
271 parent_, selection_, NULL) != NULL;
272
273 case IDC_BOOKMARK_BAR_ALWAYS_SHOW:
274 return !profile_->GetPrefs()->IsManagedPreference(
275 prefs::kEnableBookmarkBar);
276
277 case IDC_COPY:
278 case IDC_CUT:
279 return !selection_.empty() && !is_root_node &&
280 (command_id == IDC_COPY || can_edit);
281
282 case IDC_PASTE:
283 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
284 return can_edit &&
285 ((!selection_.empty() &&
286 bookmark_utils::CanPasteFromClipboard(selection_[0])) ||
287 bookmark_utils::CanPasteFromClipboard(parent_));
288 }
289 return true;
290 }
291
GetAcceleratorForCommandId(int command_id,ui::Accelerator * accelerator)292 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
293 int command_id,
294 ui::Accelerator* accelerator) {
295 return false;
296 }
297
BookmarkModelChanged()298 void BookmarkContextMenuController::BookmarkModelChanged() {
299 if (delegate_)
300 delegate_->CloseMenu();
301 }
302
HasURLs() const303 bool BookmarkContextMenuController::HasURLs() const {
304 for (size_t i = 0; i < selection_.size(); ++i) {
305 if (bookmark_utils::NodeHasURLs(selection_[i]))
306 return true;
307 }
308 return false;
309 }
310