Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_image_model.cc
blobaa695c98d31afb7c26b99fd2089bd45f1841bd62
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/host_content_settings_map_factory.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 "chrome/grit/generated_resources.h"
12 #include "components/content_settings/core/browser/host_content_settings_map.h"
13 #include "content/public/browser/web_contents.h"
14 #include "grit/theme_resources.h"
15 #include "ui/base/l10n/l10n_util.h"
16 #include "ui/base/resource/material_design/material_design_controller.h"
17 #include "ui/base/resource/resource_bundle.h"
19 #if !defined(OS_MACOSX)
20 #include "ui/gfx/paint_vector_icon.h"
21 #include "ui/gfx/vector_icons_public.h"
22 #include "ui/native_theme/common_theme.h"
23 #include "ui/native_theme/native_theme.h"
24 #endif
26 using content::WebContents;
28 namespace {
30 bool UseVectorGraphics() {
31 #if defined(OS_MACOSX)
32 return false;
33 #else
34 return ui::MaterialDesignController::IsModeMaterial();
35 #endif
38 #if !defined(OS_MACOSX)
39 // Gets a vector icon badged with |badge|.
40 gfx::Image GetIcon(gfx::VectorIconId id, gfx::VectorIconId badge) {
41 SkColor icon_color;
42 ui::CommonThemeGetSystemColor(ui::NativeTheme::kColorId_ChromeIconGrey,
43 &icon_color);
44 return gfx::Image(gfx::CreateVectorIconWithBadge(id, 16, icon_color, badge));
46 #endif
48 } // namespace
50 class ContentSettingBlockedImageModel : public ContentSettingImageModel {
51 public:
52 explicit ContentSettingBlockedImageModel(
53 ContentSettingsType content_settings_type);
55 void UpdateFromWebContents(WebContents* web_contents) override;
58 class ContentSettingGeolocationImageModel : public ContentSettingImageModel {
59 public:
60 ContentSettingGeolocationImageModel();
62 void UpdateFromWebContents(WebContents* web_contents) override;
65 // Image model for displaying media icons in the location bar.
66 class ContentSettingMediaImageModel : public ContentSettingImageModel {
67 public:
68 explicit ContentSettingMediaImageModel(ContentSettingsType type);
70 void UpdateFromWebContents(WebContents* web_contents) override;
73 class ContentSettingRPHImageModel : public ContentSettingImageModel {
74 public:
75 ContentSettingRPHImageModel();
77 void UpdateFromWebContents(WebContents* web_contents) override;
80 class ContentSettingNotificationsImageModel : public ContentSettingImageModel {
81 public:
82 ContentSettingNotificationsImageModel();
84 void UpdateFromWebContents(WebContents* web_contents) override;
87 class ContentSettingMIDISysExImageModel : public ContentSettingImageModel {
88 public:
89 ContentSettingMIDISysExImageModel();
91 void UpdateFromWebContents(WebContents* web_contents) override;
94 namespace {
96 struct ContentSettingsTypeIdEntry {
97 ContentSettingsType type;
98 int id;
101 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
102 size_t num_entries,
103 ContentSettingsType type) {
104 for (size_t i = 0; i < num_entries; ++i) {
105 if (entries[i].type == type)
106 return entries[i].id;
108 return 0;
111 } // namespace
113 ContentSettingBlockedImageModel::ContentSettingBlockedImageModel(
114 ContentSettingsType content_settings_type)
115 : ContentSettingImageModel(content_settings_type) {
118 void ContentSettingBlockedImageModel::UpdateFromWebContents(
119 WebContents* web_contents) {
120 set_visible(false);
121 if (!web_contents)
122 return;
124 ContentSettingsType type = get_content_settings_type();
125 static const ContentSettingsTypeIdEntry kBlockedIconIDs[] = {
126 {CONTENT_SETTINGS_TYPE_COOKIES, IDR_BLOCKED_COOKIES},
127 {CONTENT_SETTINGS_TYPE_IMAGES, IDR_BLOCKED_IMAGES},
128 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDR_BLOCKED_JAVASCRIPT},
129 {CONTENT_SETTINGS_TYPE_PLUGINS, IDR_BLOCKED_PLUGINS},
130 {CONTENT_SETTINGS_TYPE_POPUPS, IDR_BLOCKED_POPUPS},
131 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDR_BLOCKED_MIXED_CONTENT},
132 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDR_BLOCKED_PPAPI_BROKER},
133 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDR_BLOCKED_DOWNLOADS},
135 int icon_id =
136 GetIdForContentType(kBlockedIconIDs, arraysize(kBlockedIconIDs), type);
138 #if !defined(OS_MACOSX)
139 gfx::VectorIconId vector_icon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
140 switch (type) {
141 case CONTENT_SETTINGS_TYPE_COOKIES:
142 vector_icon_id = gfx::VectorIconId::COOKIE;
143 break;
144 case CONTENT_SETTINGS_TYPE_IMAGES:
145 vector_icon_id = gfx::VectorIconId::IMAGE;
146 break;
147 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
148 vector_icon_id = gfx::VectorIconId::CODE;
149 break;
150 case CONTENT_SETTINGS_TYPE_PLUGINS:
151 vector_icon_id = gfx::VectorIconId::EXTENSION;
152 break;
153 case CONTENT_SETTINGS_TYPE_POPUPS:
154 vector_icon_id = gfx::VectorIconId::WEB;
155 break;
156 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
157 vector_icon_id = gfx::VectorIconId::MIXED_CONTENT;
158 break;
159 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
160 vector_icon_id = gfx::VectorIconId::EXTENSION;
161 break;
162 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
163 vector_icon_id = gfx::VectorIconId::FILE_DOWNLOAD;
164 break;
165 default:
166 // If we didn't find a vector icon ID we shouldn't have found an
167 // asset ID either.
168 DCHECK_EQ(0, icon_id);
169 break;
171 #endif
173 static const ContentSettingsTypeIdEntry kBlockedTooltipIDs[] = {
174 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
175 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
176 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
177 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
178 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TOOLTIP},
179 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
180 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
181 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_TITLE},
182 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
184 int tooltip_id = GetIdForContentType(kBlockedTooltipIDs,
185 arraysize(kBlockedTooltipIDs), type);
187 static const ContentSettingsTypeIdEntry kBlockedExplanatoryTextIDs[] = {
188 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_EXPLANATORY_TEXT},
189 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGIN_EXPLANATORY_TEXT},
190 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
191 IDS_BLOCKED_DOWNLOADS_EXPLANATION},
193 int explanation_id = GetIdForContentType(
194 kBlockedExplanatoryTextIDs, arraysize(kBlockedExplanatoryTextIDs), type);
196 // For plugins, don't show the animated explanation unless the plugin was
197 // blocked despite the user's content settings being set to allow it (e.g.
198 // due to auto-blocking NPAPI plugins).
199 Profile* profile =
200 Profile::FromBrowserContext(web_contents->GetBrowserContext());
201 HostContentSettingsMap* map =
202 HostContentSettingsMapFactory::GetForProfile(profile);
203 if (type == CONTENT_SETTINGS_TYPE_PLUGINS) {
204 GURL url = web_contents->GetURL();
205 if (map->GetContentSetting(url, url, type, std::string()) !=
206 CONTENT_SETTING_ALLOW)
207 explanation_id = 0;
210 // If a content type is blocked by default and was accessed, display the
211 // content blocked page action.
212 TabSpecificContentSettings* content_settings =
213 TabSpecificContentSettings::FromWebContents(web_contents);
214 if (!content_settings)
215 return;
216 if (!content_settings->IsContentBlocked(type)) {
217 if (!content_settings->IsContentAllowed(type))
218 return;
220 // For cookies, only show the cookie blocked page action if cookies are
221 // blocked by default.
222 if (type == CONTENT_SETTINGS_TYPE_COOKIES &&
223 (map->GetDefaultContentSetting(type, NULL) != CONTENT_SETTING_BLOCK))
224 return;
226 static const ContentSettingsTypeIdEntry kAccessedIconIDs[] = {
227 {CONTENT_SETTINGS_TYPE_COOKIES, IDR_ACCESSED_COOKIES},
228 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDR_BLOCKED_PPAPI_BROKER},
229 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDR_ALLOWED_DOWNLOADS},
231 icon_id = GetIdForContentType(kAccessedIconIDs, arraysize(kAccessedIconIDs),
232 type);
233 static const ContentSettingsTypeIdEntry kAccessedTooltipIDs[] = {
234 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
235 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
236 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
238 tooltip_id = GetIdForContentType(
239 kAccessedTooltipIDs, arraysize(kAccessedTooltipIDs), type);
240 explanation_id = 0;
242 set_visible(true);
243 if (!UseVectorGraphics()) {
244 DCHECK(icon_id);
245 SetIconByResourceId(icon_id);
246 #if !defined(OS_MACOSX)
247 } else {
248 DCHECK(gfx::VectorIconId::VECTOR_ICON_NONE != vector_icon_id);
250 if (type == CONTENT_SETTINGS_TYPE_PPAPI_BROKER) {
251 set_icon(GetIcon(vector_icon_id, gfx::VectorIconId::WARNING_BADGE));
252 } else {
253 SetIconByVectorId(vector_icon_id,
254 content_settings->IsContentBlocked(type));
256 #endif
258 set_explanatory_string_id(explanation_id);
259 DCHECK(tooltip_id);
260 set_tooltip(l10n_util::GetStringUTF8(tooltip_id));
263 ContentSettingGeolocationImageModel::ContentSettingGeolocationImageModel()
264 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_GEOLOCATION) {
267 void ContentSettingGeolocationImageModel::UpdateFromWebContents(
268 WebContents* web_contents) {
269 set_visible(false);
270 if (!web_contents)
271 return;
272 TabSpecificContentSettings* content_settings =
273 TabSpecificContentSettings::FromWebContents(web_contents);
274 if (!content_settings)
275 return;
276 const ContentSettingsUsagesState& usages_state = content_settings->
277 geolocation_usages_state();
278 if (usages_state.state_map().empty())
279 return;
280 set_visible(true);
282 // If any embedded site has access the allowed icon takes priority over the
283 // blocked icon.
284 unsigned int state_flags = 0;
285 usages_state.GetDetailedInfo(NULL, &state_flags);
286 bool allowed =
287 !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED);
288 if (!UseVectorGraphics())
289 SetIconByResourceId(allowed ? IDR_ALLOWED_LOCATION : IDR_BLOCKED_LOCATION);
290 #if !defined(OS_MACOSX)
291 else
292 SetIconByVectorId(gfx::VectorIconId::MY_LOCATION, !allowed);
293 #endif
294 set_tooltip(l10n_util::GetStringUTF8(allowed ?
295 IDS_GEOLOCATION_ALLOWED_TOOLTIP : IDS_GEOLOCATION_BLOCKED_TOOLTIP));
298 ContentSettingMediaImageModel::ContentSettingMediaImageModel(
299 ContentSettingsType type)
300 : ContentSettingImageModel(type) {
303 void ContentSettingMediaImageModel::UpdateFromWebContents(
304 WebContents* web_contents) {
305 set_visible(false);
307 // As long as a single icon is used to display the status of the camera and
308 // microphone usage only display an icon for the
309 // CONTENT_SETTINGS_TYPE_MEDIASTREAM. Don't display anything for
310 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
311 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
312 // FIXME: Remove this hack and either display a two omnibox icons (one for
313 // camera and one for microphone), or don't create one image model per
314 // content type but per icon to display. The later is probably the right
315 // thing to do, bebacuse this also allows to add more content settings type
316 // for which no omnibox icon exists.
317 if (get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
318 get_content_settings_type() == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
319 return;
322 // The ContentSettingMediaImageModel must not be used with a content type
323 // other then: CONTENT_SETTINGS_TYPE_MEDIASTREAM,
324 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
325 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
326 DCHECK_EQ(get_content_settings_type(), CONTENT_SETTINGS_TYPE_MEDIASTREAM);
328 if (!web_contents)
329 return;
331 TabSpecificContentSettings* content_settings =
332 TabSpecificContentSettings::FromWebContents(web_contents);
333 if (!content_settings)
334 return;
335 TabSpecificContentSettings::MicrophoneCameraState state =
336 content_settings->GetMicrophoneCameraState();
338 // If neither the microphone nor the camera stream was accessed then no icon
339 // is displayed in the omnibox.
340 if (state == TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED)
341 return;
343 bool is_mic = (state & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
344 bool is_cam = (state & TabSpecificContentSettings::CAMERA_ACCESSED) != 0;
345 DCHECK(is_mic || is_cam);
347 int id = IDS_CAMERA_BLOCKED;
348 if (state & (TabSpecificContentSettings::MICROPHONE_BLOCKED |
349 TabSpecificContentSettings::CAMERA_BLOCKED)) {
350 if (!UseVectorGraphics())
351 SetIconByResourceId(IDR_BLOCKED_CAMERA);
352 #if !defined(OS_MACOSX)
353 else
354 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM, true);
355 #endif
356 if (is_mic)
357 id = is_cam ? IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
358 } else {
359 if (!UseVectorGraphics())
360 SetIconByResourceId(IDR_ALLOWED_CAMERA);
361 #if !defined(OS_MACOSX)
362 else
363 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM, false);
364 #endif
365 id = IDS_CAMERA_ACCESSED;
366 if (is_mic)
367 id = is_cam ? IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
369 set_tooltip(l10n_util::GetStringUTF8(id));
370 set_visible(true);
373 ContentSettingRPHImageModel::ContentSettingRPHImageModel()
374 : ContentSettingImageModel(
375 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
376 if (!UseVectorGraphics())
377 SetIconByResourceId(IDR_REGISTER_PROTOCOL_HANDLER);
378 #if !defined(OS_MACOSX)
379 else
380 SetIconByVectorId(gfx::VectorIconId::PROTOCOL_HANDLER, false);
381 #endif
382 set_tooltip(l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP));
385 void ContentSettingRPHImageModel::UpdateFromWebContents(
386 WebContents* web_contents) {
387 set_visible(false);
388 if (!web_contents)
389 return;
391 TabSpecificContentSettings* content_settings =
392 TabSpecificContentSettings::FromWebContents(web_contents);
393 if (!content_settings)
394 return;
395 if (content_settings->pending_protocol_handler().IsEmpty())
396 return;
398 set_visible(true);
401 ContentSettingNotificationsImageModel::ContentSettingNotificationsImageModel()
402 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
405 void ContentSettingNotificationsImageModel::UpdateFromWebContents(
406 WebContents* web_contents) {
407 // Notifications do not have a bubble.
408 set_visible(false);
411 ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
412 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
415 void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
416 WebContents* web_contents) {
417 set_visible(false);
418 if (!web_contents)
419 return;
420 TabSpecificContentSettings* content_settings =
421 TabSpecificContentSettings::FromWebContents(web_contents);
422 if (!content_settings)
423 return;
424 const ContentSettingsUsagesState& usages_state =
425 content_settings->midi_usages_state();
426 if (usages_state.state_map().empty())
427 return;
428 set_visible(true);
430 // If any embedded site has access the allowed icon takes priority over the
431 // blocked icon.
432 unsigned int state_flags = 0;
433 usages_state.GetDetailedInfo(NULL, &state_flags);
434 bool allowed =
435 !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED);
436 #if defined(OS_MACOSX)
437 SetIconByResourceId(allowed ? IDR_ALLOWED_MIDI_SYSEX
438 : IDR_BLOCKED_MIDI_SYSEX);
439 #else
440 SetIconByVectorId(gfx::VectorIconId::MIDI, !allowed);
441 #endif
442 set_tooltip(l10n_util::GetStringUTF8(allowed ?
443 IDS_MIDI_SYSEX_ALLOWED_TOOLTIP : IDS_MIDI_SYSEX_BLOCKED_TOOLTIP));
446 ContentSettingImageModel::ContentSettingImageModel(
447 ContentSettingsType content_settings_type)
448 : content_settings_type_(content_settings_type),
449 is_visible_(false),
450 icon_id_(0),
451 explanatory_string_id_(0) {
454 // static
455 ContentSettingImageModel*
456 ContentSettingImageModel::CreateContentSettingImageModel(
457 ContentSettingsType content_settings_type) {
458 switch (content_settings_type) {
459 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
460 return new ContentSettingGeolocationImageModel();
461 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
462 return new ContentSettingNotificationsImageModel();
463 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
464 return new ContentSettingRPHImageModel();
465 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
466 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
467 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
468 return new ContentSettingMediaImageModel(content_settings_type);
469 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
470 return new ContentSettingMIDISysExImageModel();
471 default:
472 return new ContentSettingBlockedImageModel(content_settings_type);
476 void ContentSettingImageModel::SetIconByResourceId(int id) {
477 icon_id_ = id;
478 icon_ = ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(id);
481 #if !defined(OS_MACOSX)
482 void ContentSettingImageModel::SetIconByVectorId(gfx::VectorIconId id,
483 bool blocked) {
484 icon_ = GetIcon(id, blocked ? gfx::VectorIconId::BLOCKED_BADGE
485 : gfx::VectorIconId::VECTOR_ICON_NONE);
487 #endif