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/content_settings/content_setting_image_model.h" 6 7 #include "chrome/browser/content_settings/host_content_settings_map.h" 8 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 9 #include "chrome/browser/prerender/prerender_manager.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "content/public/browser/web_contents.h" 12 #include "grit/generated_resources.h" 13 #include "grit/theme_resources.h" 14 #include "ui/base/l10n/l10n_util.h" 15 16 using content::WebContents; 17 18 class ContentSettingBlockedImageModel : public ContentSettingImageModel { 19 public: 20 explicit ContentSettingBlockedImageModel( 21 ContentSettingsType content_settings_type); 22 23 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 24 }; 25 26 class ContentSettingGeolocationImageModel : public ContentSettingImageModel { 27 public: 28 ContentSettingGeolocationImageModel(); 29 30 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 31 }; 32 33 // Image model for displaying media icons in the location bar. 34 class ContentSettingMediaImageModel : public ContentSettingImageModel { 35 public: 36 explicit ContentSettingMediaImageModel(ContentSettingsType type); 37 38 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 39 }; 40 41 class ContentSettingRPHImageModel : public ContentSettingImageModel { 42 public: 43 ContentSettingRPHImageModel(); 44 45 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 46 }; 47 48 class ContentSettingNotificationsImageModel : public ContentSettingImageModel { 49 public: 50 ContentSettingNotificationsImageModel(); 51 52 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 53 }; 54 55 class ContentSettingMIDISysExImageModel : public ContentSettingImageModel { 56 public: 57 ContentSettingMIDISysExImageModel(); 58 59 virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE; 60 }; 61 62 namespace { 63 64 struct ContentSettingsTypeIdEntry { 65 ContentSettingsType type; 66 int id; 67 }; 68 69 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries, 70 size_t num_entries, 71 ContentSettingsType type) { 72 for (size_t i = 0; i < num_entries; ++i) { 73 if (entries[i].type == type) 74 return entries[i].id; 75 } 76 return 0; 77 } 78 79 } // namespace 80 81 ContentSettingBlockedImageModel::ContentSettingBlockedImageModel( 82 ContentSettingsType content_settings_type) 83 : ContentSettingImageModel(content_settings_type) { 84 } 85 86 void ContentSettingBlockedImageModel::UpdateFromWebContents( 87 WebContents* web_contents) { 88 set_visible(false); 89 if (!web_contents) 90 return; 91 92 static const ContentSettingsTypeIdEntry kBlockedIconIDs[] = { 93 {CONTENT_SETTINGS_TYPE_COOKIES, IDR_BLOCKED_COOKIES}, 94 {CONTENT_SETTINGS_TYPE_IMAGES, IDR_BLOCKED_IMAGES}, 95 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDR_BLOCKED_JAVASCRIPT}, 96 {CONTENT_SETTINGS_TYPE_PLUGINS, IDR_BLOCKED_PLUGINS}, 97 {CONTENT_SETTINGS_TYPE_POPUPS, IDR_BLOCKED_POPUPS}, 98 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDR_BLOCKED_MIXED_CONTENT}, 99 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDR_BLOCKED_PPAPI_BROKER}, 100 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDR_BLOCKED_DOWNLOADS}, 101 }; 102 static const ContentSettingsTypeIdEntry kBlockedTooltipIDs[] = { 103 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE}, 104 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE}, 105 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE}, 106 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE}, 107 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TOOLTIP}, 108 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, 109 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT}, 110 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_TITLE}, 111 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE}, 112 }; 113 static const ContentSettingsTypeIdEntry kBlockedExplanatoryTextIDs[] = { 114 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_EXPLANATORY_TEXT}, 115 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, 116 IDS_BLOCKED_DOWNLOADS_EXPLANATION}, 117 }; 118 119 ContentSettingsType type = get_content_settings_type(); 120 int icon_id = GetIdForContentType( 121 kBlockedIconIDs, arraysize(kBlockedIconIDs), type); 122 int tooltip_id = GetIdForContentType( 123 kBlockedTooltipIDs, arraysize(kBlockedTooltipIDs), type); 124 int explanation_id = GetIdForContentType( 125 kBlockedExplanatoryTextIDs, arraysize(kBlockedExplanatoryTextIDs), type); 126 127 // If a content type is blocked by default and was accessed, display the 128 // accessed icon. 129 TabSpecificContentSettings* content_settings = 130 TabSpecificContentSettings::FromWebContents(web_contents); 131 if (!content_settings) 132 return; 133 Profile* profile = 134 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 135 if (!content_settings->IsContentBlocked(get_content_settings_type())) { 136 if (!content_settings->IsContentAllowed(get_content_settings_type())) 137 return; 138 139 // For cookies, only show the accessed bubble if cookies are blocked by 140 // default. 141 if (get_content_settings_type() == CONTENT_SETTINGS_TYPE_COOKIES && 142 (profile->GetHostContentSettingsMap()-> 143 GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES, NULL) != 144 CONTENT_SETTING_BLOCK)) 145 return; 146 147 static const ContentSettingsTypeIdEntry kAccessedIconIDs[] = { 148 {CONTENT_SETTINGS_TYPE_COOKIES, IDR_ACCESSED_COOKIES}, 149 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDR_BLOCKED_PPAPI_BROKER}, 150 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDR_ALLOWED_DOWNLOADS}, 151 }; 152 static const ContentSettingsTypeIdEntry kAccessedTooltipIDs[] = { 153 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE}, 154 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE}, 155 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE}, 156 }; 157 icon_id = GetIdForContentType( 158 kAccessedIconIDs, arraysize(kAccessedIconIDs), type); 159 tooltip_id = GetIdForContentType( 160 kAccessedTooltipIDs, arraysize(kAccessedTooltipIDs), type); 161 explanation_id = 0; 162 } 163 set_visible(true); 164 DCHECK(icon_id); 165 set_icon(icon_id); 166 set_explanatory_string_id(explanation_id); 167 DCHECK(tooltip_id); 168 set_tooltip(l10n_util::GetStringUTF8(tooltip_id)); 169 } 170 171 ContentSettingGeolocationImageModel::ContentSettingGeolocationImageModel() 172 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_GEOLOCATION) { 173 } 174 175 void ContentSettingGeolocationImageModel::UpdateFromWebContents( 176 WebContents* web_contents) { 177 set_visible(false); 178 if (!web_contents) 179 return; 180 TabSpecificContentSettings* content_settings = 181 TabSpecificContentSettings::FromWebContents(web_contents); 182 if (!content_settings) 183 return; 184 const ContentSettingsUsagesState& usages_state = content_settings-> 185 geolocation_usages_state(); 186 if (usages_state.state_map().empty()) 187 return; 188 set_visible(true); 189 190 // If any embedded site has access the allowed icon takes priority over the 191 // blocked icon. 192 unsigned int state_flags = 0; 193 usages_state.GetDetailedInfo(NULL, &state_flags); 194 bool allowed = 195 !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED); 196 set_icon(allowed ? IDR_ALLOWED_LOCATION : IDR_BLOCKED_LOCATION); 197 set_tooltip(l10n_util::GetStringUTF8(allowed ? 198 IDS_GEOLOCATION_ALLOWED_TOOLTIP : IDS_GEOLOCATION_BLOCKED_TOOLTIP)); 199 } 200 201 ContentSettingMediaImageModel::ContentSettingMediaImageModel( 202 ContentSettingsType type) 203 : ContentSettingImageModel(type) { 204 } 205 206 void ContentSettingMediaImageModel::UpdateFromWebContents( 207 WebContents* web_contents) { 208 set_visible(false); 209 210 // As long as a single icon is used to display the status of the camera and 211 // microphone usage only display an icon for the 212 // CONTENT_SETTINGS_TYPE_MEDIASTREAM. Don't display anything for 213 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 214 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA. 215 // FIXME: Remove this hack and either display a two omnibox icons (one for 216 // camera and one for microphone), or don't create one image model per 217 // content type but per icon to display. The later is probably the right 218 // thing to do, bebacuse this also allows to add more content settings type 219 // for which no omnibox icon exists. 220 if (get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC || 221 get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) { 222 return; 223 } 224 225 // The ContentSettingMediaImageModel must not be used with a content type 226 // other then: CONTENT_SETTINGS_TYPE_MEDIASTREAM, 227 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 228 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA. 229 DCHECK_EQ(get_content_settings_type(), CONTENT_SETTINGS_TYPE_MEDIASTREAM); 230 231 if (!web_contents) 232 return; 233 234 TabSpecificContentSettings* content_settings = 235 TabSpecificContentSettings::FromWebContents(web_contents); 236 if (!content_settings) 237 return; 238 TabSpecificContentSettings::MicrophoneCameraState state = 239 content_settings->GetMicrophoneCameraState(); 240 241 switch (state) { 242 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED: 243 // If neither the microphone nor the camera stream was accessed then no 244 // icon is displayed in the omnibox. 245 return; 246 case TabSpecificContentSettings::MICROPHONE_ACCESSED: 247 set_icon(IDR_ASK_MEDIA); 248 set_tooltip(l10n_util::GetStringUTF8(IDS_MICROPHONE_ACCESSED)); 249 break; 250 case TabSpecificContentSettings::CAMERA_ACCESSED: 251 set_icon(IDR_ASK_MEDIA); 252 set_tooltip(l10n_util::GetStringUTF8(IDS_CAMERA_ACCESSED)); 253 break; 254 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED: 255 set_icon(IDR_ASK_MEDIA); 256 set_tooltip(l10n_util::GetStringUTF8(IDS_MICROPHONE_CAMERA_ALLOWED)); 257 break; 258 case TabSpecificContentSettings::MICROPHONE_BLOCKED: 259 set_icon(IDR_BLOCKED_MEDIA); 260 set_tooltip(l10n_util::GetStringUTF8(IDS_MICROPHONE_BLOCKED)); 261 break; 262 case TabSpecificContentSettings::CAMERA_BLOCKED: 263 set_icon(IDR_BLOCKED_MEDIA); 264 set_tooltip(l10n_util::GetStringUTF8(IDS_CAMERA_BLOCKED)); 265 break; 266 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED: 267 set_icon(IDR_BLOCKED_MEDIA); 268 set_tooltip(l10n_util::GetStringUTF8(IDS_MICROPHONE_CAMERA_BLOCKED)); 269 break; 270 } 271 set_visible(true); 272 } 273 274 ContentSettingRPHImageModel::ContentSettingRPHImageModel() 275 : ContentSettingImageModel( 276 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) { 277 set_icon(IDR_REGISTER_PROTOCOL_HANDLER); 278 set_tooltip(l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP)); 279 } 280 281 void ContentSettingRPHImageModel::UpdateFromWebContents( 282 WebContents* web_contents) { 283 set_visible(false); 284 if (!web_contents) 285 return; 286 287 TabSpecificContentSettings* content_settings = 288 TabSpecificContentSettings::FromWebContents(web_contents); 289 if (!content_settings) 290 return; 291 if (content_settings->pending_protocol_handler().IsEmpty()) 292 return; 293 294 set_visible(true); 295 } 296 297 ContentSettingNotificationsImageModel::ContentSettingNotificationsImageModel() 298 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 299 } 300 301 void ContentSettingNotificationsImageModel::UpdateFromWebContents( 302 WebContents* web_contents) { 303 // Notifications do not have a bubble. 304 set_visible(false); 305 } 306 307 ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel() 308 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 309 } 310 311 void ContentSettingMIDISysExImageModel::UpdateFromWebContents( 312 WebContents* web_contents) { 313 set_visible(false); 314 if (!web_contents) 315 return; 316 TabSpecificContentSettings* content_settings = 317 TabSpecificContentSettings::FromWebContents(web_contents); 318 if (!content_settings) 319 return; 320 const ContentSettingsUsagesState& usages_state = 321 content_settings->midi_usages_state(); 322 if (usages_state.state_map().empty()) 323 return; 324 set_visible(true); 325 326 // If any embedded site has access the allowed icon takes priority over the 327 // blocked icon. 328 unsigned int state_flags = 0; 329 usages_state.GetDetailedInfo(NULL, &state_flags); 330 bool allowed = 331 !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED); 332 set_icon(allowed ? IDR_ALLOWED_MIDI_SYSEX : IDR_BLOCKED_MIDI_SYSEX); 333 set_tooltip(l10n_util::GetStringUTF8(allowed ? 334 IDS_MIDI_SYSEX_ALLOWED_TOOLTIP : IDS_MIDI_SYSEX_BLOCKED_TOOLTIP)); 335 } 336 337 ContentSettingImageModel::ContentSettingImageModel( 338 ContentSettingsType content_settings_type) 339 : content_settings_type_(content_settings_type), 340 is_visible_(false), 341 icon_(0), 342 explanatory_string_id_(0) { 343 } 344 345 // static 346 ContentSettingImageModel* 347 ContentSettingImageModel::CreateContentSettingImageModel( 348 ContentSettingsType content_settings_type) { 349 switch (content_settings_type) { 350 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 351 return new ContentSettingGeolocationImageModel(); 352 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 353 return new ContentSettingNotificationsImageModel(); 354 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS: 355 return new ContentSettingRPHImageModel(); 356 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 357 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 358 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 359 return new ContentSettingMediaImageModel(content_settings_type); 360 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 361 return new ContentSettingMIDISysExImageModel(); 362 default: 363 return new ContentSettingBlockedImageModel(content_settings_type); 364 } 365 } 366