bookmark_context_menu_controller.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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. 4 5#include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h" 6 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.h" 12#include "chrome/browser/bookmarks/bookmark_model_factory.h" 13#include "chrome/browser/bookmarks/bookmark_utils.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 "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" 29 30using base::UserMetricsAction; 31using content::PageNavigator; 32 33BookmarkContextMenuController::BookmarkContextMenuController( 34 gfx::NativeWindow parent_window, 35 BookmarkContextMenuControllerDelegate* delegate, 36 Browser* browser, 37 Profile* profile, 38 PageNavigator* navigator, 39 const BookmarkNode* parent, 40 const std::vector<const BookmarkNode*>& selection) 41 : parent_window_(parent_window), 42 delegate_(delegate), 43 browser_(browser), 44 profile_(profile), 45 navigator_(navigator), 46 parent_(parent), 47 selection_(selection), 48 model_(BookmarkModelFactory::GetForProfile(profile)) { 49 DCHECK(profile_); 50 DCHECK(model_->loaded()); 51 menu_model_.reset(new ui::SimpleMenuModel(this)); 52 model_->AddObserver(this); 53 54 BuildMenu(); 55} 56 57BookmarkContextMenuController::~BookmarkContextMenuController() { 58 if (model_) 59 model_->RemoveObserver(this); 60} 61 62void 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); 70 } else { 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); 76 } 77 78 AddSeparator(); 79 if (selection_.size() == 1 && selection_[0]->is_folder()) { 80 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER, IDS_BOOKMARK_BAR_RENAME_FOLDER); 81 } else { 82 AddItem(IDC_BOOKMARK_BAR_EDIT, IDS_BOOKMARK_BAR_EDIT); 83 } 84 85 AddSeparator(); 86 AddItem(IDC_CUT, IDS_CUT); 87 AddItem(IDC_COPY, IDS_COPY); 88 AddItem(IDC_PASTE, IDS_PASTE); 89 90 AddSeparator(); 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); 96 } 97 98 AddSeparator(); 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); 101 102 AddSeparator(); 103 AddItem(IDC_BOOKMARK_MANAGER, IDS_BOOKMARK_MANAGER); 104 // Use the native host desktop type in tests. 105 if (chrome::IsAppsShortcutEnabled( 106 profile_, 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); 111 } 112 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW, IDS_SHOW_BOOKMARK_BAR); 113} 114 115void BookmarkContextMenuController::AddItem(int id, int localization_id) { 116 menu_model_->AddItemWithStringId(id, localization_id); 117} 118 119void BookmarkContextMenuController::AddSeparator() { 120 menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); 121} 122 123void BookmarkContextMenuController::AddCheckboxItem(int id, 124 int localization_id) { 125 menu_model_->AddCheckItemWithStringId(id, localization_id); 126} 127 128void BookmarkContextMenuController::ExecuteCommand(int id, int event_flags) { 129 if (delegate_) 130 delegate_->WillExecuteCommand(id, selection_); 131 132 switch (id) { 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")); 145 } else { 146 initial_disposition = OFF_THE_RECORD; 147 content::RecordAction( 148 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito")); 149 } 150 chrome::OpenAll(parent_window_, navigator_, selection_, 151 initial_disposition, profile_); 152 break; 153 } 154 155 case IDC_BOOKMARK_BAR_RENAME_FOLDER: 156 case IDC_BOOKMARK_BAR_EDIT: 157 content::RecordAction( 158 UserMetricsAction("BookmarkBar_ContextMenu_Edit")); 159 160 if (selection_.size() != 1) { 161 NOTREACHED(); 162 break; 163 } 164 165 BookmarkEditor::Show( 166 parent_window_, 167 profile_, 168 BookmarkEditor::EditDetails::EditNode(selection_[0]), 169 selection_[0]->is_url() ? BookmarkEditor::SHOW_TREE : 170 BookmarkEditor::NO_TREE); 171 break; 172 173 case IDC_BOOKMARK_BAR_UNDO: { 174 content::RecordAction( 175 UserMetricsAction("BookmarkBar_ContextMenu_Undo")); 176 BookmarkUndoServiceFactory::GetForProfile(profile_)->undo_manager()-> 177 Undo(); 178 break; 179 } 180 181 case IDC_BOOKMARK_BAR_REDO: { 182 content::RecordAction( 183 UserMetricsAction("BookmarkBar_ContextMenu_Redo")); 184 BookmarkUndoServiceFactory::GetForProfile(profile_)->undo_manager()-> 185 Redo(); 186 break; 187 } 188 189 case IDC_BOOKMARK_BAR_REMOVE: { 190 content::RecordAction( 191 UserMetricsAction("BookmarkBar_ContextMenu_Remove")); 192 193 for (size_t i = 0; i < selection_.size(); ++i) { 194 int index = selection_[i]->parent()->GetIndexOf(selection_[i]); 195 if (index > -1) 196 model_->Remove(selection_[i]->parent(), index); 197 } 198 selection_.clear(); 199 break; 200 } 201 202 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK: { 203 content::RecordAction( 204 UserMetricsAction("BookmarkBar_ContextMenu_Add")); 205 206 int index; 207 const BookmarkNode* parent = 208 bookmark_utils::GetParentForNewNodes(parent_, selection_, &index); 209 GURL url; 210 base::string16 title; 211 chrome::GetURLAndTitleToBookmark( 212 browser_->tab_strip_model()->GetActiveWebContents(), 213 &url, &title); 214 BookmarkEditor::Show(parent_window_, 215 profile_, 216 BookmarkEditor::EditDetails::AddNodeInFolder( 217 parent, index, url, title), 218 BookmarkEditor::SHOW_TREE); 219 break; 220 } 221 222 case IDC_BOOKMARK_BAR_NEW_FOLDER: { 223 content::RecordAction( 224 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder")); 225 226 int index; 227 const BookmarkNode* parent = 228 bookmark_utils::GetParentForNewNodes(parent_, selection_, &index); 229 BookmarkEditor::Show( 230 parent_window_, 231 profile_, 232 BookmarkEditor::EditDetails::AddFolder(parent, index), 233 BookmarkEditor::SHOW_TREE); 234 break; 235 } 236 237 case IDC_BOOKMARK_BAR_ALWAYS_SHOW: 238 chrome::ToggleBookmarkBarWhenVisible(profile_); 239 break; 240 241 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT: { 242 PrefService* prefs = profile_->GetPrefs(); 243 prefs->SetBoolean( 244 prefs::kShowAppsShortcutInBookmarkBar, 245 !prefs->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar)); 246 break; 247 } 248 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()); 255 else if (parent_) 256 chrome::ShowBookmarkManagerForNode(browser_, parent_->id()); 257 else 258 chrome::ShowBookmarkManager(browser_); 259 break; 260 } 261 262 case IDC_CUT: 263 bookmark_utils::CopyToClipboard(model_, selection_, true); 264 break; 265 266 case IDC_COPY: 267 bookmark_utils::CopyToClipboard(model_, selection_, false); 268 break; 269 270 case IDC_PASTE: { 271 int index; 272 const BookmarkNode* paste_target = 273 bookmark_utils::GetParentForNewNodes(parent_, selection_, &index); 274 if (!paste_target) 275 return; 276 277 bookmark_utils::PasteFromClipboard(model_, paste_target, index); 278 break; 279 } 280 281 default: 282 NOTREACHED(); 283 } 284 285 if (delegate_) 286 delegate_->DidExecuteCommand(id); 287} 288 289bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id) 290 const { 291 return command_id == IDC_BOOKMARK_BAR_UNDO || 292 command_id == IDC_BOOKMARK_BAR_REDO; 293} 294 295base::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(); 300 } 301 if (command_id == IDC_BOOKMARK_BAR_REDO) { 302 return BookmarkUndoServiceFactory::GetForProfile(profile_)-> 303 undo_manager()->GetRedoLabel(); 304 } 305 306 NOTREACHED(); 307 return base::string16(); 308} 309 310bool 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); 314 315 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT, command_id); 316 return prefs->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar); 317} 318 319bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id) const { 320 PrefService* prefs = profile_->GetPrefs(); 321 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; 331 332 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO: 333 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_, profile_) 334 && 335 !profile_->IsOffTheRecord() && 336 incognito_avail != IncognitoModePrefs::DISABLED; 337 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; 343 344 case IDC_BOOKMARK_BAR_RENAME_FOLDER: 345 case IDC_BOOKMARK_BAR_EDIT: 346 return selection_.size() == 1 && !is_root_node && can_edit; 347 348 case IDC_BOOKMARK_BAR_UNDO: 349 return can_edit && 350 BookmarkUndoServiceFactory::GetForProfile(profile_)-> 351 undo_manager()->undo_count() > 0; 352 353 case IDC_BOOKMARK_BAR_REDO: 354 return can_edit && 355 BookmarkUndoServiceFactory::GetForProfile(profile_)-> 356 undo_manager()->redo_count() > 0; 357 358 case IDC_BOOKMARK_BAR_REMOVE: 359 return !selection_.empty() && !is_root_node && can_edit; 360 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; 365 366 case IDC_BOOKMARK_BAR_ALWAYS_SHOW: 367 return !prefs->IsManagedPreference(prefs::kShowBookmarkBar); 368 369 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT: 370 return !prefs->IsManagedPreference(prefs::kShowAppsShortcutInBookmarkBar); 371 372 case IDC_COPY: 373 case IDC_CUT: 374 return !selection_.empty() && !is_root_node && 375 (command_id == IDC_COPY || can_edit); 376 377 case IDC_PASTE: 378 // Paste to selection from the Bookmark Bar, to parent_ everywhere else 379 return can_edit && 380 ((!selection_.empty() && 381 bookmark_utils::CanPasteFromClipboard(selection_[0])) || 382 bookmark_utils::CanPasteFromClipboard(parent_)); 383 } 384 return true; 385} 386 387bool BookmarkContextMenuController::GetAcceleratorForCommandId( 388 int command_id, 389 ui::Accelerator* accelerator) { 390 return false; 391} 392 393void BookmarkContextMenuController::BookmarkModelChanged() { 394 if (delegate_) 395 delegate_->CloseMenu(); 396} 397