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();
39 class ContentSettingBlockedImageModel
: public ContentSettingImageModel
{
41 explicit ContentSettingBlockedImageModel(
42 ContentSettingsType content_settings_type
);
44 void UpdateFromWebContents(WebContents
* web_contents
) override
;
47 class ContentSettingGeolocationImageModel
: public ContentSettingImageModel
{
49 ContentSettingGeolocationImageModel();
51 void UpdateFromWebContents(WebContents
* web_contents
) override
;
54 // Image model for displaying media icons in the location bar.
55 class ContentSettingMediaImageModel
: public ContentSettingImageModel
{
57 explicit ContentSettingMediaImageModel(ContentSettingsType type
);
59 void UpdateFromWebContents(WebContents
* web_contents
) override
;
62 class ContentSettingRPHImageModel
: public ContentSettingImageModel
{
64 ContentSettingRPHImageModel();
66 void UpdateFromWebContents(WebContents
* web_contents
) override
;
69 class ContentSettingNotificationsImageModel
: public ContentSettingImageModel
{
71 ContentSettingNotificationsImageModel();
73 void UpdateFromWebContents(WebContents
* web_contents
) override
;
76 class ContentSettingMIDISysExImageModel
: public ContentSettingImageModel
{
78 ContentSettingMIDISysExImageModel();
80 void UpdateFromWebContents(WebContents
* web_contents
) override
;
85 struct ContentSettingsTypeIdEntry
{
86 ContentSettingsType type
;
90 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
92 ContentSettingsType type
) {
93 for (size_t i
= 0; i
< num_entries
; ++i
) {
94 if (entries
[i
].type
== type
)
102 ContentSettingBlockedImageModel::ContentSettingBlockedImageModel(
103 ContentSettingsType content_settings_type
)
104 : ContentSettingImageModel(content_settings_type
) {
107 void ContentSettingBlockedImageModel::UpdateFromWebContents(
108 WebContents
* web_contents
) {
113 ContentSettingsType type
= get_content_settings_type();
114 static const ContentSettingsTypeIdEntry kBlockedIconIDs
[] = {
115 {CONTENT_SETTINGS_TYPE_COOKIES
, IDR_BLOCKED_COOKIES
},
116 {CONTENT_SETTINGS_TYPE_IMAGES
, IDR_BLOCKED_IMAGES
},
117 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDR_BLOCKED_JAVASCRIPT
},
118 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDR_BLOCKED_PLUGINS
},
119 {CONTENT_SETTINGS_TYPE_POPUPS
, IDR_BLOCKED_POPUPS
},
120 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDR_BLOCKED_MIXED_CONTENT
},
121 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDR_BLOCKED_PPAPI_BROKER
},
122 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDR_BLOCKED_DOWNLOADS
},
125 GetIdForContentType(kBlockedIconIDs
, arraysize(kBlockedIconIDs
), type
);
127 #if !defined(OS_MACOSX)
128 gfx::VectorIconId vector_icon_id
= gfx::VectorIconId::VECTOR_ICON_NONE
;
130 case CONTENT_SETTINGS_TYPE_COOKIES
:
131 vector_icon_id
= gfx::VectorIconId::COOKIE
;
133 case CONTENT_SETTINGS_TYPE_IMAGES
:
134 vector_icon_id
= gfx::VectorIconId::IMAGE
;
136 case CONTENT_SETTINGS_TYPE_JAVASCRIPT
:
137 vector_icon_id
= gfx::VectorIconId::CODE
;
139 case CONTENT_SETTINGS_TYPE_PLUGINS
:
140 vector_icon_id
= gfx::VectorIconId::EXTENSION
;
142 case CONTENT_SETTINGS_TYPE_POPUPS
:
143 vector_icon_id
= gfx::VectorIconId::WEB
;
145 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
146 vector_icon_id
= gfx::VectorIconId::MIXED_CONTENT
;
148 // TODO(estade): change this one?
149 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER
:
150 vector_icon_id
= gfx::VectorIconId::EXTENSION
;
152 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
153 vector_icon_id
= gfx::VectorIconId::FILE_DOWNLOAD
;
156 // If we didn't find a vector icon ID we shouldn't have found an
158 DCHECK_EQ(0, icon_id
);
163 static const ContentSettingsTypeIdEntry kBlockedTooltipIDs
[] = {
164 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
165 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
166 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
167 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_MESSAGE
},
168 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TOOLTIP
},
169 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
170 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
171 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_TITLE
},
172 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
174 int tooltip_id
= GetIdForContentType(kBlockedTooltipIDs
,
175 arraysize(kBlockedTooltipIDs
), type
);
177 static const ContentSettingsTypeIdEntry kBlockedExplanatoryTextIDs
[] = {
178 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_EXPLANATORY_TEXT
},
179 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGIN_EXPLANATORY_TEXT
},
180 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
,
181 IDS_BLOCKED_DOWNLOADS_EXPLANATION
},
183 int explanation_id
= GetIdForContentType(
184 kBlockedExplanatoryTextIDs
, arraysize(kBlockedExplanatoryTextIDs
), type
);
186 // For plugins, don't show the animated explanation unless the plugin was
187 // blocked despite the user's content settings being set to allow it (e.g.
188 // due to auto-blocking NPAPI plugins).
190 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
191 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
192 if (type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
193 GURL url
= web_contents
->GetURL();
194 if (map
->GetContentSetting(url
, url
, type
, std::string()) !=
195 CONTENT_SETTING_ALLOW
)
199 // If a content type is blocked by default and was accessed, display the
200 // content blocked page action.
201 TabSpecificContentSettings
* content_settings
=
202 TabSpecificContentSettings::FromWebContents(web_contents
);
203 if (!content_settings
)
205 if (!content_settings
->IsContentBlocked(type
)) {
206 if (!content_settings
->IsContentAllowed(type
))
209 // For cookies, only show the cookie blocked page action if cookies are
210 // blocked by default.
211 if (type
== CONTENT_SETTINGS_TYPE_COOKIES
&&
212 (map
->GetDefaultContentSetting(type
, NULL
) != CONTENT_SETTING_BLOCK
))
215 static const ContentSettingsTypeIdEntry kAccessedIconIDs
[] = {
216 {CONTENT_SETTINGS_TYPE_COOKIES
, IDR_ACCESSED_COOKIES
},
217 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDR_BLOCKED_PPAPI_BROKER
},
218 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDR_ALLOWED_DOWNLOADS
},
220 icon_id
= GetIdForContentType(kAccessedIconIDs
, arraysize(kAccessedIconIDs
),
222 static const ContentSettingsTypeIdEntry kAccessedTooltipIDs
[] = {
223 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
224 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
225 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
227 tooltip_id
= GetIdForContentType(
228 kAccessedTooltipIDs
, arraysize(kAccessedTooltipIDs
), type
);
232 if (!UseVectorGraphics()) {
234 SetIconByResourceId(icon_id
);
235 #if !defined(OS_MACOSX)
237 DCHECK(gfx::VectorIconId::VECTOR_ICON_NONE
!= vector_icon_id
);
238 SetIconByVectorId(vector_icon_id
, content_settings
->IsContentBlocked(type
));
241 set_explanatory_string_id(explanation_id
);
243 set_tooltip(l10n_util::GetStringUTF8(tooltip_id
));
246 ContentSettingGeolocationImageModel::ContentSettingGeolocationImageModel()
247 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
250 void ContentSettingGeolocationImageModel::UpdateFromWebContents(
251 WebContents
* web_contents
) {
255 TabSpecificContentSettings
* content_settings
=
256 TabSpecificContentSettings::FromWebContents(web_contents
);
257 if (!content_settings
)
259 const ContentSettingsUsagesState
& usages_state
= content_settings
->
260 geolocation_usages_state();
261 if (usages_state
.state_map().empty())
265 // If any embedded site has access the allowed icon takes priority over the
267 unsigned int state_flags
= 0;
268 usages_state
.GetDetailedInfo(NULL
, &state_flags
);
270 !!(state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED
);
271 if (!UseVectorGraphics())
272 SetIconByResourceId(allowed
? IDR_ALLOWED_LOCATION
: IDR_BLOCKED_LOCATION
);
273 #if !defined(OS_MACOSX)
275 SetIconByVectorId(gfx::VectorIconId::MY_LOCATION
, !allowed
);
277 set_tooltip(l10n_util::GetStringUTF8(allowed
?
278 IDS_GEOLOCATION_ALLOWED_TOOLTIP
: IDS_GEOLOCATION_BLOCKED_TOOLTIP
));
281 ContentSettingMediaImageModel::ContentSettingMediaImageModel(
282 ContentSettingsType type
)
283 : ContentSettingImageModel(type
) {
286 void ContentSettingMediaImageModel::UpdateFromWebContents(
287 WebContents
* web_contents
) {
290 // As long as a single icon is used to display the status of the camera and
291 // microphone usage only display an icon for the
292 // CONTENT_SETTINGS_TYPE_MEDIASTREAM. Don't display anything for
293 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
294 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
295 // FIXME: Remove this hack and either display a two omnibox icons (one for
296 // camera and one for microphone), or don't create one image model per
297 // content type but per icon to display. The later is probably the right
298 // thing to do, bebacuse this also allows to add more content settings type
299 // for which no omnibox icon exists.
300 if (get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
||
301 get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
) {
305 // The ContentSettingMediaImageModel must not be used with a content type
306 // other then: CONTENT_SETTINGS_TYPE_MEDIASTREAM,
307 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
308 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
309 DCHECK_EQ(get_content_settings_type(), CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
314 TabSpecificContentSettings
* content_settings
=
315 TabSpecificContentSettings::FromWebContents(web_contents
);
316 if (!content_settings
)
318 TabSpecificContentSettings::MicrophoneCameraState state
=
319 content_settings
->GetMicrophoneCameraState();
321 // If neither the microphone nor the camera stream was accessed then no icon
322 // is displayed in the omnibox.
323 if (state
== TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
)
326 bool is_mic
= (state
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
327 bool is_cam
= (state
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
328 DCHECK(is_mic
|| is_cam
);
330 int id
= IDS_CAMERA_BLOCKED
;
331 if (state
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
332 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
333 if (!UseVectorGraphics())
334 SetIconByResourceId(IDR_BLOCKED_CAMERA
);
335 #if !defined(OS_MACOSX)
337 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM
, true);
340 id
= is_cam
? IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
342 if (!UseVectorGraphics())
343 SetIconByResourceId(IDR_ALLOWED_CAMERA
);
344 #if !defined(OS_MACOSX)
346 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM
, false);
348 id
= IDS_CAMERA_ACCESSED
;
350 id
= is_cam
? IDS_MICROPHONE_CAMERA_ALLOWED
: IDS_MICROPHONE_ACCESSED
;
352 set_tooltip(l10n_util::GetStringUTF8(id
));
356 ContentSettingRPHImageModel::ContentSettingRPHImageModel()
357 : ContentSettingImageModel(
358 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
359 // TODO(estade): get an MD icon for this one.
360 SetIconByResourceId(IDR_REGISTER_PROTOCOL_HANDLER
);
361 set_tooltip(l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP
));
364 void ContentSettingRPHImageModel::UpdateFromWebContents(
365 WebContents
* web_contents
) {
370 TabSpecificContentSettings
* content_settings
=
371 TabSpecificContentSettings::FromWebContents(web_contents
);
372 if (!content_settings
)
374 if (content_settings
->pending_protocol_handler().IsEmpty())
380 ContentSettingNotificationsImageModel::ContentSettingNotificationsImageModel()
381 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
) {
384 void ContentSettingNotificationsImageModel::UpdateFromWebContents(
385 WebContents
* web_contents
) {
386 // Notifications do not have a bubble.
390 ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
391 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
394 void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
395 WebContents
* web_contents
) {
399 TabSpecificContentSettings
* content_settings
=
400 TabSpecificContentSettings::FromWebContents(web_contents
);
401 if (!content_settings
)
403 const ContentSettingsUsagesState
& usages_state
=
404 content_settings
->midi_usages_state();
405 if (usages_state
.state_map().empty())
409 // If any embedded site has access the allowed icon takes priority over the
411 unsigned int state_flags
= 0;
412 usages_state
.GetDetailedInfo(NULL
, &state_flags
);
414 !!(state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED
);
415 #if defined(OS_MACOSX)
416 SetIconByResourceId(allowed
? IDR_ALLOWED_MIDI_SYSEX
417 : IDR_BLOCKED_MIDI_SYSEX
);
419 SetIconByVectorId(gfx::VectorIconId::MIDI
, !allowed
);
421 set_tooltip(l10n_util::GetStringUTF8(allowed
?
422 IDS_MIDI_SYSEX_ALLOWED_TOOLTIP
: IDS_MIDI_SYSEX_BLOCKED_TOOLTIP
));
425 ContentSettingImageModel::ContentSettingImageModel(
426 ContentSettingsType content_settings_type
)
427 : content_settings_type_(content_settings_type
),
430 explanatory_string_id_(0) {
434 ContentSettingImageModel
*
435 ContentSettingImageModel::CreateContentSettingImageModel(
436 ContentSettingsType content_settings_type
) {
437 switch (content_settings_type
) {
438 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
439 return new ContentSettingGeolocationImageModel();
440 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
441 return new ContentSettingNotificationsImageModel();
442 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
:
443 return new ContentSettingRPHImageModel();
444 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
445 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
446 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
447 return new ContentSettingMediaImageModel(content_settings_type
);
448 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
449 return new ContentSettingMIDISysExImageModel();
451 return new ContentSettingBlockedImageModel(content_settings_type
);
455 void ContentSettingImageModel::SetIconByResourceId(int id
) {
457 icon_
= ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(id
);
460 #if !defined(OS_MACOSX)
461 void ContentSettingImageModel::SetIconByVectorId(gfx::VectorIconId id
,
464 ui::CommonThemeGetSystemColor(ui::NativeTheme::kColorId_ChromeIconGrey
,
466 icon_
= gfx::Image(gfx::CreateVectorIconWithBadge(
467 id
, 16, icon_color
, blocked
? gfx::VectorIconId::BLOCKED_BADGE
468 : gfx::VectorIconId::VECTOR_ICON_NONE
));