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/content_settings/content_setting_image_model.h"
7 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
8 #include "chrome/browser/prerender/prerender_manager.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/grit/generated_resources.h"
11 #include "components/content_settings/core/browser/host_content_settings_map.h"
12 #include "content/public/browser/web_contents.h"
13 #include "grit/theme_resources.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/material_design/material_design_controller.h"
16 #include "ui/base/resource/resource_bundle.h"
18 #if !defined(OS_MACOSX)
19 #include "ui/gfx/paint_vector_icon.h"
20 #include "ui/gfx/vector_icons_public.h"
21 #include "ui/native_theme/common_theme.h"
22 #include "ui/native_theme/native_theme.h"
25 using content::WebContents
;
29 bool UseVectorGraphics() {
30 #if defined(OS_MACOSX)
33 return ui::MaterialDesignController::IsModeMaterial();
37 #if !defined(OS_MACOSX)
38 // Gets a vector icon badged with |badge|.
39 gfx::Image
GetIcon(gfx::VectorIconId id
, gfx::VectorIconId badge
) {
41 ui::CommonThemeGetSystemColor(ui::NativeTheme::kColorId_ChromeIconGrey
,
43 return gfx::Image(gfx::CreateVectorIconWithBadge(id
, 16, icon_color
, badge
));
49 class ContentSettingBlockedImageModel
: public ContentSettingImageModel
{
51 explicit ContentSettingBlockedImageModel(
52 ContentSettingsType content_settings_type
);
54 void UpdateFromWebContents(WebContents
* web_contents
) override
;
57 class ContentSettingGeolocationImageModel
: public ContentSettingImageModel
{
59 ContentSettingGeolocationImageModel();
61 void UpdateFromWebContents(WebContents
* web_contents
) override
;
64 // Image model for displaying media icons in the location bar.
65 class ContentSettingMediaImageModel
: public ContentSettingImageModel
{
67 explicit ContentSettingMediaImageModel(ContentSettingsType type
);
69 void UpdateFromWebContents(WebContents
* web_contents
) override
;
72 class ContentSettingRPHImageModel
: public ContentSettingImageModel
{
74 ContentSettingRPHImageModel();
76 void UpdateFromWebContents(WebContents
* web_contents
) override
;
79 class ContentSettingNotificationsImageModel
: public ContentSettingImageModel
{
81 ContentSettingNotificationsImageModel();
83 void UpdateFromWebContents(WebContents
* web_contents
) override
;
86 class ContentSettingMIDISysExImageModel
: public ContentSettingImageModel
{
88 ContentSettingMIDISysExImageModel();
90 void UpdateFromWebContents(WebContents
* web_contents
) override
;
95 struct ContentSettingsTypeIdEntry
{
96 ContentSettingsType type
;
100 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
102 ContentSettingsType type
) {
103 for (size_t i
= 0; i
< num_entries
; ++i
) {
104 if (entries
[i
].type
== type
)
105 return entries
[i
].id
;
112 ContentSettingBlockedImageModel::ContentSettingBlockedImageModel(
113 ContentSettingsType content_settings_type
)
114 : ContentSettingImageModel(content_settings_type
) {
117 void ContentSettingBlockedImageModel::UpdateFromWebContents(
118 WebContents
* web_contents
) {
123 ContentSettingsType type
= get_content_settings_type();
124 static const ContentSettingsTypeIdEntry kBlockedIconIDs
[] = {
125 {CONTENT_SETTINGS_TYPE_COOKIES
, IDR_BLOCKED_COOKIES
},
126 {CONTENT_SETTINGS_TYPE_IMAGES
, IDR_BLOCKED_IMAGES
},
127 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDR_BLOCKED_JAVASCRIPT
},
128 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDR_BLOCKED_PLUGINS
},
129 {CONTENT_SETTINGS_TYPE_POPUPS
, IDR_BLOCKED_POPUPS
},
130 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDR_BLOCKED_MIXED_CONTENT
},
131 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDR_BLOCKED_PPAPI_BROKER
},
132 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDR_BLOCKED_DOWNLOADS
},
135 GetIdForContentType(kBlockedIconIDs
, arraysize(kBlockedIconIDs
), type
);
137 #if !defined(OS_MACOSX)
138 gfx::VectorIconId vector_icon_id
= gfx::VectorIconId::VECTOR_ICON_NONE
;
140 case CONTENT_SETTINGS_TYPE_COOKIES
:
141 vector_icon_id
= gfx::VectorIconId::COOKIE
;
143 case CONTENT_SETTINGS_TYPE_IMAGES
:
144 vector_icon_id
= gfx::VectorIconId::IMAGE
;
146 case CONTENT_SETTINGS_TYPE_JAVASCRIPT
:
147 vector_icon_id
= gfx::VectorIconId::CODE
;
149 case CONTENT_SETTINGS_TYPE_PLUGINS
:
150 vector_icon_id
= gfx::VectorIconId::EXTENSION
;
152 case CONTENT_SETTINGS_TYPE_POPUPS
:
153 vector_icon_id
= gfx::VectorIconId::WEB
;
155 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
156 vector_icon_id
= gfx::VectorIconId::MIXED_CONTENT
;
158 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER
:
159 vector_icon_id
= gfx::VectorIconId::EXTENSION
;
161 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
162 vector_icon_id
= gfx::VectorIconId::FILE_DOWNLOAD
;
165 // If we didn't find a vector icon ID we shouldn't have found an
167 DCHECK_EQ(0, icon_id
);
172 static const ContentSettingsTypeIdEntry kBlockedTooltipIDs
[] = {
173 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
174 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
175 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
176 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_MESSAGE
},
177 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TOOLTIP
},
178 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
179 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
180 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_TITLE
},
181 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
183 int tooltip_id
= GetIdForContentType(kBlockedTooltipIDs
,
184 arraysize(kBlockedTooltipIDs
), type
);
186 static const ContentSettingsTypeIdEntry kBlockedExplanatoryTextIDs
[] = {
187 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_EXPLANATORY_TEXT
},
188 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGIN_EXPLANATORY_TEXT
},
189 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
,
190 IDS_BLOCKED_DOWNLOADS_EXPLANATION
},
192 int explanation_id
= GetIdForContentType(
193 kBlockedExplanatoryTextIDs
, arraysize(kBlockedExplanatoryTextIDs
), type
);
195 // For plugins, don't show the animated explanation unless the plugin was
196 // blocked despite the user's content settings being set to allow it (e.g.
197 // due to auto-blocking NPAPI plugins).
199 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
200 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
201 if (type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
202 GURL url
= web_contents
->GetURL();
203 if (map
->GetContentSetting(url
, url
, type
, std::string()) !=
204 CONTENT_SETTING_ALLOW
)
208 // If a content type is blocked by default and was accessed, display the
209 // content blocked page action.
210 TabSpecificContentSettings
* content_settings
=
211 TabSpecificContentSettings::FromWebContents(web_contents
);
212 if (!content_settings
)
214 if (!content_settings
->IsContentBlocked(type
)) {
215 if (!content_settings
->IsContentAllowed(type
))
218 // For cookies, only show the cookie blocked page action if cookies are
219 // blocked by default.
220 if (type
== CONTENT_SETTINGS_TYPE_COOKIES
&&
221 (map
->GetDefaultContentSetting(type
, NULL
) != CONTENT_SETTING_BLOCK
))
224 static const ContentSettingsTypeIdEntry kAccessedIconIDs
[] = {
225 {CONTENT_SETTINGS_TYPE_COOKIES
, IDR_ACCESSED_COOKIES
},
226 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDR_BLOCKED_PPAPI_BROKER
},
227 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDR_ALLOWED_DOWNLOADS
},
229 icon_id
= GetIdForContentType(kAccessedIconIDs
, arraysize(kAccessedIconIDs
),
231 static const ContentSettingsTypeIdEntry kAccessedTooltipIDs
[] = {
232 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
233 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
234 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
236 tooltip_id
= GetIdForContentType(
237 kAccessedTooltipIDs
, arraysize(kAccessedTooltipIDs
), type
);
241 if (!UseVectorGraphics()) {
243 SetIconByResourceId(icon_id
);
244 #if !defined(OS_MACOSX)
246 DCHECK(gfx::VectorIconId::VECTOR_ICON_NONE
!= vector_icon_id
);
248 if (type
== CONTENT_SETTINGS_TYPE_PPAPI_BROKER
) {
249 set_icon(GetIcon(vector_icon_id
, gfx::VectorIconId::WARNING_BADGE
));
251 SetIconByVectorId(vector_icon_id
,
252 content_settings
->IsContentBlocked(type
));
256 set_explanatory_string_id(explanation_id
);
258 set_tooltip(l10n_util::GetStringUTF8(tooltip_id
));
261 ContentSettingGeolocationImageModel::ContentSettingGeolocationImageModel()
262 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
265 void ContentSettingGeolocationImageModel::UpdateFromWebContents(
266 WebContents
* web_contents
) {
270 TabSpecificContentSettings
* content_settings
=
271 TabSpecificContentSettings::FromWebContents(web_contents
);
272 if (!content_settings
)
274 const ContentSettingsUsagesState
& usages_state
= content_settings
->
275 geolocation_usages_state();
276 if (usages_state
.state_map().empty())
280 // If any embedded site has access the allowed icon takes priority over the
282 unsigned int state_flags
= 0;
283 usages_state
.GetDetailedInfo(NULL
, &state_flags
);
285 !!(state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED
);
286 if (!UseVectorGraphics())
287 SetIconByResourceId(allowed
? IDR_ALLOWED_LOCATION
: IDR_BLOCKED_LOCATION
);
288 #if !defined(OS_MACOSX)
290 SetIconByVectorId(gfx::VectorIconId::MY_LOCATION
, !allowed
);
292 set_tooltip(l10n_util::GetStringUTF8(allowed
?
293 IDS_GEOLOCATION_ALLOWED_TOOLTIP
: IDS_GEOLOCATION_BLOCKED_TOOLTIP
));
296 ContentSettingMediaImageModel::ContentSettingMediaImageModel(
297 ContentSettingsType type
)
298 : ContentSettingImageModel(type
) {
301 void ContentSettingMediaImageModel::UpdateFromWebContents(
302 WebContents
* web_contents
) {
305 // As long as a single icon is used to display the status of the camera and
306 // microphone usage only display an icon for the
307 // CONTENT_SETTINGS_TYPE_MEDIASTREAM. Don't display anything for
308 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
309 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
310 // FIXME: Remove this hack and either display a two omnibox icons (one for
311 // camera and one for microphone), or don't create one image model per
312 // content type but per icon to display. The later is probably the right
313 // thing to do, bebacuse this also allows to add more content settings type
314 // for which no omnibox icon exists.
315 if (get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
||
316 get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
) {
320 // The ContentSettingMediaImageModel must not be used with a content type
321 // other then: CONTENT_SETTINGS_TYPE_MEDIASTREAM,
322 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
323 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
324 DCHECK_EQ(get_content_settings_type(), CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
329 TabSpecificContentSettings
* content_settings
=
330 TabSpecificContentSettings::FromWebContents(web_contents
);
331 if (!content_settings
)
333 TabSpecificContentSettings::MicrophoneCameraState state
=
334 content_settings
->GetMicrophoneCameraState();
336 // If neither the microphone nor the camera stream was accessed then no icon
337 // is displayed in the omnibox.
338 if (state
== TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
)
341 bool is_mic
= (state
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
342 bool is_cam
= (state
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
343 DCHECK(is_mic
|| is_cam
);
345 int id
= IDS_CAMERA_BLOCKED
;
346 if (state
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
347 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
348 if (!UseVectorGraphics())
349 SetIconByResourceId(IDR_BLOCKED_CAMERA
);
350 #if !defined(OS_MACOSX)
352 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM
, true);
355 id
= is_cam
? IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
357 if (!UseVectorGraphics())
358 SetIconByResourceId(IDR_ALLOWED_CAMERA
);
359 #if !defined(OS_MACOSX)
361 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM
, false);
363 id
= IDS_CAMERA_ACCESSED
;
365 id
= is_cam
? IDS_MICROPHONE_CAMERA_ALLOWED
: IDS_MICROPHONE_ACCESSED
;
367 set_tooltip(l10n_util::GetStringUTF8(id
));
371 ContentSettingRPHImageModel::ContentSettingRPHImageModel()
372 : ContentSettingImageModel(
373 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
374 if (!UseVectorGraphics())
375 SetIconByResourceId(IDR_REGISTER_PROTOCOL_HANDLER
);
376 #if !defined(OS_MACOSX)
378 SetIconByVectorId(gfx::VectorIconId::PROTOCOL_HANDLER
, false);
380 set_tooltip(l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP
));
383 void ContentSettingRPHImageModel::UpdateFromWebContents(
384 WebContents
* web_contents
) {
389 TabSpecificContentSettings
* content_settings
=
390 TabSpecificContentSettings::FromWebContents(web_contents
);
391 if (!content_settings
)
393 if (content_settings
->pending_protocol_handler().IsEmpty())
399 ContentSettingNotificationsImageModel::ContentSettingNotificationsImageModel()
400 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
) {
403 void ContentSettingNotificationsImageModel::UpdateFromWebContents(
404 WebContents
* web_contents
) {
405 // Notifications do not have a bubble.
409 ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
410 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
413 void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
414 WebContents
* web_contents
) {
418 TabSpecificContentSettings
* content_settings
=
419 TabSpecificContentSettings::FromWebContents(web_contents
);
420 if (!content_settings
)
422 const ContentSettingsUsagesState
& usages_state
=
423 content_settings
->midi_usages_state();
424 if (usages_state
.state_map().empty())
428 // If any embedded site has access the allowed icon takes priority over the
430 unsigned int state_flags
= 0;
431 usages_state
.GetDetailedInfo(NULL
, &state_flags
);
433 !!(state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED
);
434 #if defined(OS_MACOSX)
435 SetIconByResourceId(allowed
? IDR_ALLOWED_MIDI_SYSEX
436 : IDR_BLOCKED_MIDI_SYSEX
);
438 SetIconByVectorId(gfx::VectorIconId::MIDI
, !allowed
);
440 set_tooltip(l10n_util::GetStringUTF8(allowed
?
441 IDS_MIDI_SYSEX_ALLOWED_TOOLTIP
: IDS_MIDI_SYSEX_BLOCKED_TOOLTIP
));
444 ContentSettingImageModel::ContentSettingImageModel(
445 ContentSettingsType content_settings_type
)
446 : content_settings_type_(content_settings_type
),
449 explanatory_string_id_(0) {
453 ContentSettingImageModel
*
454 ContentSettingImageModel::CreateContentSettingImageModel(
455 ContentSettingsType content_settings_type
) {
456 switch (content_settings_type
) {
457 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
458 return new ContentSettingGeolocationImageModel();
459 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
460 return new ContentSettingNotificationsImageModel();
461 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
:
462 return new ContentSettingRPHImageModel();
463 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
464 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
465 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
466 return new ContentSettingMediaImageModel(content_settings_type
);
467 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
468 return new ContentSettingMIDISysExImageModel();
470 return new ContentSettingBlockedImageModel(content_settings_type
);
474 void ContentSettingImageModel::SetIconByResourceId(int id
) {
476 icon_
= ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(id
);
479 #if !defined(OS_MACOSX)
480 void ContentSettingImageModel::SetIconByVectorId(gfx::VectorIconId id
,
482 icon_
= GetIcon(id
, blocked
? gfx::VectorIconId::BLOCKED_BADGE
483 : gfx::VectorIconId::VECTOR_ICON_NONE
);