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/notifications/notification_options_menu_model.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/logging.h" 9 #include "base/utf_string_conversions.h" 10 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/notifications/balloon_collection.h" 13 #include "chrome/browser/notifications/desktop_notification_service.h" 14 #include "chrome/browser/notifications/desktop_notification_service_factory.h" 15 #include "chrome/browser/notifications/notification.h" 16 #include "chrome/browser/notifications/notification_ui_manager.h" 17 #include "chrome/browser/notifications/notifications_prefs_cache.h" 18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/content_settings_types.h" 22 #include "chrome/common/extensions/extension.h" 23 #include "chrome/common/url_constants.h" 24 #include "content/browser/tab_contents/tab_contents_delegate.h" 25 #include "grit/generated_resources.h" 26 #include "ui/base/l10n/l10n_util.h" 27 28 // Menu commands 29 const int kTogglePermissionCommand = 0; 30 const int kToggleExtensionCommand = 1; 31 const int kOpenContentSettingsCommand = 2; 32 const int kCornerSelectionSubMenu = 3; 33 34 const int kCornerGroupId = 10; 35 const int kCornerUpperLeft = 11; 36 const int kCornerUpperRight = 12; 37 const int kCornerLowerLeft = 13; 38 const int kCornerLowerRight = 14; 39 const int kCornerDefault = 20; 40 41 CornerSelectionMenuModel::CornerSelectionMenuModel(Balloon* balloon) 42 : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), 43 balloon_(balloon) { 44 AddRadioItem(kCornerDefault, 45 l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_DEFAULT), 46 kCornerGroupId); 47 AddSeparator(); 48 AddRadioItem(kCornerUpperLeft, 49 l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_UPPER_LEFT), 50 kCornerGroupId); 51 AddRadioItem(kCornerUpperRight, 52 l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_UPPER_RIGHT), 53 kCornerGroupId); 54 AddRadioItem(kCornerLowerLeft, 55 l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_LOWER_LEFT), 56 kCornerGroupId); 57 AddRadioItem(kCornerLowerRight, 58 l10n_util::GetStringUTF16(IDS_NOTIFICATION_POSITION_LOWER_RIGHT), 59 kCornerGroupId); 60 } 61 62 CornerSelectionMenuModel::~CornerSelectionMenuModel() { 63 } 64 65 bool CornerSelectionMenuModel::IsCommandIdChecked(int command_id) const { 66 NotificationUIManager* ui = g_browser_process->notification_ui_manager(); 67 BalloonCollection::PositionPreference current = ui->GetPositionPreference(); 68 69 if (command_id == kCornerUpperLeft) 70 return (current == BalloonCollection::UPPER_LEFT); 71 else if (command_id == kCornerUpperRight) 72 return (current == BalloonCollection::UPPER_RIGHT); 73 else if (command_id == kCornerLowerLeft) 74 return (current == BalloonCollection::LOWER_LEFT); 75 else if (command_id == kCornerLowerRight) 76 return (current == BalloonCollection::LOWER_RIGHT); 77 else if (command_id == kCornerDefault) 78 return (current == BalloonCollection::DEFAULT_POSITION); 79 80 NOTREACHED(); 81 return false; 82 } 83 84 bool CornerSelectionMenuModel::IsCommandIdEnabled(int command_id) const { 85 // All the menu options are always enabled. 86 return true; 87 } 88 89 bool CornerSelectionMenuModel::GetAcceleratorForCommandId( 90 int command_id, ui::Accelerator* accelerator) { 91 // Currently no accelerators. 92 return false; 93 } 94 95 void CornerSelectionMenuModel::ExecuteCommand(int command_id) { 96 NotificationUIManager* ui = g_browser_process->notification_ui_manager(); 97 98 if (command_id == kCornerUpperLeft) 99 ui->SetPositionPreference(BalloonCollection::UPPER_LEFT); 100 else if (command_id == kCornerUpperRight) 101 ui->SetPositionPreference(BalloonCollection::UPPER_RIGHT); 102 else if (command_id == kCornerLowerLeft) 103 ui->SetPositionPreference(BalloonCollection::LOWER_LEFT); 104 else if (command_id == kCornerLowerRight) 105 ui->SetPositionPreference(BalloonCollection::LOWER_RIGHT); 106 else if (command_id == kCornerDefault) 107 ui->SetPositionPreference(BalloonCollection::DEFAULT_POSITION); 108 else 109 NOTREACHED(); 110 } 111 112 NotificationOptionsMenuModel::NotificationOptionsMenuModel(Balloon* balloon) 113 : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), 114 balloon_(balloon) { 115 const Notification& notification = balloon->notification(); 116 const GURL& origin = notification.origin_url(); 117 118 if (origin.SchemeIs(chrome::kExtensionScheme)) { 119 ExtensionService* ext_service = 120 balloon_->profile()->GetExtensionService(); 121 const Extension* extension = ext_service->GetExtensionByURL(origin); 122 // We get back no extension here when we show the notification after 123 // the extension has crashed. 124 if (extension) { 125 const string16 disable_label = l10n_util::GetStringUTF16( 126 IDS_EXTENSIONS_DISABLE); 127 AddItem(kToggleExtensionCommand, disable_label); 128 } 129 } else { 130 const string16 disable_label = l10n_util::GetStringFUTF16( 131 IDS_NOTIFICATION_BALLOON_REVOKE_MESSAGE, 132 notification.display_source()); 133 AddItem(kTogglePermissionCommand, disable_label); 134 } 135 136 const string16 settings_label = l10n_util::GetStringUTF16( 137 IDS_NOTIFICATIONS_SETTINGS_BUTTON); 138 AddItem(kOpenContentSettingsCommand, settings_label); 139 140 corner_menu_model_.reset(new CornerSelectionMenuModel(balloon)); 141 AddSubMenu(kCornerSelectionSubMenu, 142 l10n_util::GetStringUTF16(IDS_NOTIFICATION_CHOOSE_POSITION), 143 corner_menu_model_.get()); 144 } 145 146 NotificationOptionsMenuModel::~NotificationOptionsMenuModel() { 147 } 148 149 bool NotificationOptionsMenuModel::IsItemForCommandIdDynamic(int command_id) 150 const { 151 return command_id == kTogglePermissionCommand || 152 command_id == kToggleExtensionCommand; 153 } 154 155 string16 NotificationOptionsMenuModel::GetLabelForCommandId(int command_id) 156 const { 157 // TODO(tfarina,johnnyg): Remove this code if we decide to close notifications 158 // after permissions are revoked. 159 if (command_id == kTogglePermissionCommand || 160 command_id == kToggleExtensionCommand) { 161 const Notification& notification = balloon_->notification(); 162 const GURL& origin = notification.origin_url(); 163 164 DesktopNotificationService* service = 165 DesktopNotificationServiceFactory::GetForProfile(balloon_->profile()); 166 if (origin.SchemeIs(chrome::kExtensionScheme)) { 167 ExtensionService* ext_service = 168 balloon_->profile()->GetExtensionService(); 169 const Extension* extension = ext_service->GetExtensionByURL(origin); 170 if (extension) { 171 ExtensionPrefs* extension_prefs = ext_service->extension_prefs(); 172 const std::string& id = extension->id(); 173 if (extension_prefs->GetExtensionState(id) == Extension::ENABLED) 174 return l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE); 175 else 176 return l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE); 177 } 178 } else { 179 if (service->GetContentSetting(origin) == CONTENT_SETTING_ALLOW) { 180 return l10n_util::GetStringFUTF16( 181 IDS_NOTIFICATION_BALLOON_REVOKE_MESSAGE, 182 notification.display_source()); 183 } else { 184 return l10n_util::GetStringFUTF16( 185 IDS_NOTIFICATION_BALLOON_ENABLE_MESSAGE, 186 notification.display_source()); 187 } 188 } 189 } else if (command_id == kOpenContentSettingsCommand) { 190 return l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_SETTINGS_BUTTON); 191 } 192 return string16(); 193 } 194 195 bool NotificationOptionsMenuModel::IsCommandIdChecked(int /* command_id */) 196 const { 197 // Nothing in the menu is checked. 198 return false; 199 } 200 201 bool NotificationOptionsMenuModel::IsCommandIdEnabled(int /* command_id */) 202 const { 203 // All the menu options are always enabled. 204 return true; 205 } 206 207 bool NotificationOptionsMenuModel::GetAcceleratorForCommandId( 208 int /* command_id */, ui::Accelerator* /* accelerator */) { 209 // Currently no accelerators. 210 return false; 211 } 212 213 void NotificationOptionsMenuModel::ExecuteCommand(int command_id) { 214 DesktopNotificationService* service = 215 DesktopNotificationServiceFactory::GetForProfile(balloon_->profile()); 216 ExtensionService* ext_service = 217 balloon_->profile()->GetExtensionService(); 218 const GURL& origin = balloon_->notification().origin_url(); 219 switch (command_id) { 220 case kTogglePermissionCommand: 221 if (service->GetContentSetting(origin) == CONTENT_SETTING_ALLOW) 222 service->DenyPermission(origin); 223 else 224 service->GrantPermission(origin); 225 break; 226 case kToggleExtensionCommand: { 227 const Extension* extension = ext_service->GetExtensionByURL(origin); 228 if (extension) { 229 ExtensionPrefs* extension_prefs = ext_service->extension_prefs(); 230 const std::string& id = extension->id(); 231 if (extension_prefs->GetExtensionState(id) == Extension::ENABLED) 232 ext_service->DisableExtension(id); 233 else 234 ext_service->EnableExtension(id); 235 } 236 break; 237 } 238 case kOpenContentSettingsCommand: { 239 Browser* browser = 240 BrowserList::GetLastActiveWithProfile(balloon_->profile()); 241 if (!browser) { 242 // It is possible that there is no browser window (e.g. when there are 243 // background pages, or for a chrome frame process on windows). 244 browser = Browser::Create(balloon_->profile()); 245 } 246 static_cast<TabContentsDelegate*>(browser)->ShowContentSettingsPage( 247 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 248 break; 249 } 250 default: 251 NOTREACHED(); 252 break; 253 } 254 } 255