Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_image_model.cc
blob25709468eb164b3d321954704e6a0e73abe965ea
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"
23 #endif
25 using content::WebContents;
27 namespace {
29 bool UseVectorGraphics() {
30 #if defined(OS_MACOSX)
31 return false;
32 #else
33 return ui::MaterialDesignController::IsModeMaterial();
34 #endif
37 #if !defined(OS_MACOSX)
38 // Gets a vector icon badged with |badge|.
39 gfx::Image GetIcon(gfx::VectorIconId id, gfx::VectorIconId badge) {
40 SkColor icon_color;
41 ui::CommonThemeGetSystemColor(ui::NativeTheme::kColorId_ChromeIconGrey,
42 &icon_color);
43 return gfx::Image(gfx::CreateVectorIconWithBadge(id, 16, icon_color, badge));
45 #endif
47 } // namespace
49 class ContentSettingBlockedImageModel : public ContentSettingImageModel {
50 public:
51 explicit ContentSettingBlockedImageModel(
52 ContentSettingsType content_settings_type);
54 void UpdateFromWebContents(WebContents* web_contents) override;
57 class ContentSettingGeolocationImageModel : public ContentSettingImageModel {
58 public:
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 {
66 public:
67 explicit ContentSettingMediaImageModel(ContentSettingsType type);
69 void UpdateFromWebContents(WebContents* web_contents) override;
72 class ContentSettingRPHImageModel : public ContentSettingImageModel {
73 public:
74 ContentSettingRPHImageModel();
76 void UpdateFromWebContents(WebContents* web_contents) override;
79 class ContentSettingNotificationsImageModel : public ContentSettingImageModel {
80 public:
81 ContentSettingNotificationsImageModel();
83 void UpdateFromWebContents(WebContents* web_contents) override;
86 class ContentSettingMIDISysExImageModel : public ContentSettingImageModel {
87 public:
88 ContentSettingMIDISysExImageModel();
90 void UpdateFromWebContents(WebContents* web_contents) override;
93 namespace {
95 struct ContentSettingsTypeIdEntry {
96 ContentSettingsType type;
97 int id;
100 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
101 size_t num_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;
107 return 0;
110 } // namespace
112 ContentSettingBlockedImageModel::ContentSettingBlockedImageModel(
113 ContentSettingsType content_settings_type)
114 : ContentSettingImageModel(content_settings_type) {
117 void ContentSettingBlockedImageModel::UpdateFromWebContents(
118 WebContents* web_contents) {
119 set_visible(false);
120 if (!web_contents)
121 return;
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},
134 int icon_id =
135 GetIdForContentType(kBlockedIconIDs, arraysize(kBlockedIconIDs), type);
137 #if !defined(OS_MACOSX)
138 gfx::VectorIconId vector_icon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
139 switch (type) {
140 case CONTENT_SETTINGS_TYPE_COOKIES:
141 vector_icon_id = gfx::VectorIconId::COOKIE;
142 break;
143 case CONTENT_SETTINGS_TYPE_IMAGES:
144 vector_icon_id = gfx::VectorIconId::IMAGE;
145 break;
146 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
147 vector_icon_id = gfx::VectorIconId::CODE;
148 break;
149 case CONTENT_SETTINGS_TYPE_PLUGINS:
150 vector_icon_id = gfx::VectorIconId::EXTENSION;
151 break;
152 case CONTENT_SETTINGS_TYPE_POPUPS:
153 vector_icon_id = gfx::VectorIconId::WEB;
154 break;
155 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
156 vector_icon_id = gfx::VectorIconId::MIXED_CONTENT;
157 break;
158 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
159 vector_icon_id = gfx::VectorIconId::EXTENSION;
160 break;
161 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
162 vector_icon_id = gfx::VectorIconId::FILE_DOWNLOAD;
163 break;
164 default:
165 // If we didn't find a vector icon ID we shouldn't have found an
166 // asset ID either.
167 DCHECK_EQ(0, icon_id);
168 break;
170 #endif
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).
198 Profile* profile =
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)
205 explanation_id = 0;
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)
213 return;
214 if (!content_settings->IsContentBlocked(type)) {
215 if (!content_settings->IsContentAllowed(type))
216 return;
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))
222 return;
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),
230 type);
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);
238 explanation_id = 0;
240 set_visible(true);
241 if (!UseVectorGraphics()) {
242 DCHECK(icon_id);
243 SetIconByResourceId(icon_id);
244 #if !defined(OS_MACOSX)
245 } else {
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));
250 } else {
251 SetIconByVectorId(vector_icon_id,
252 content_settings->IsContentBlocked(type));
254 #endif
256 set_explanatory_string_id(explanation_id);
257 DCHECK(tooltip_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) {
267 set_visible(false);
268 if (!web_contents)
269 return;
270 TabSpecificContentSettings* content_settings =
271 TabSpecificContentSettings::FromWebContents(web_contents);
272 if (!content_settings)
273 return;
274 const ContentSettingsUsagesState& usages_state = content_settings->
275 geolocation_usages_state();
276 if (usages_state.state_map().empty())
277 return;
278 set_visible(true);
280 // If any embedded site has access the allowed icon takes priority over the
281 // blocked icon.
282 unsigned int state_flags = 0;
283 usages_state.GetDetailedInfo(NULL, &state_flags);
284 bool allowed =
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)
289 else
290 SetIconByVectorId(gfx::VectorIconId::MY_LOCATION, !allowed);
291 #endif
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) {
303 set_visible(false);
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) {
317 return;
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);
326 if (!web_contents)
327 return;
329 TabSpecificContentSettings* content_settings =
330 TabSpecificContentSettings::FromWebContents(web_contents);
331 if (!content_settings)
332 return;
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)
339 return;
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)
351 else
352 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM, true);
353 #endif
354 if (is_mic)
355 id = is_cam ? IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
356 } else {
357 if (!UseVectorGraphics())
358 SetIconByResourceId(IDR_ALLOWED_CAMERA);
359 #if !defined(OS_MACOSX)
360 else
361 SetIconByVectorId(gfx::VectorIconId::VIDEOCAM, false);
362 #endif
363 id = IDS_CAMERA_ACCESSED;
364 if (is_mic)
365 id = is_cam ? IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
367 set_tooltip(l10n_util::GetStringUTF8(id));
368 set_visible(true);
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)
377 else
378 SetIconByVectorId(gfx::VectorIconId::PROTOCOL_HANDLER, false);
379 #endif
380 set_tooltip(l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP));
383 void ContentSettingRPHImageModel::UpdateFromWebContents(
384 WebContents* web_contents) {
385 set_visible(false);
386 if (!web_contents)
387 return;
389 TabSpecificContentSettings* content_settings =
390 TabSpecificContentSettings::FromWebContents(web_contents);
391 if (!content_settings)
392 return;
393 if (content_settings->pending_protocol_handler().IsEmpty())
394 return;
396 set_visible(true);
399 ContentSettingNotificationsImageModel::ContentSettingNotificationsImageModel()
400 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
403 void ContentSettingNotificationsImageModel::UpdateFromWebContents(
404 WebContents* web_contents) {
405 // Notifications do not have a bubble.
406 set_visible(false);
409 ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
410 : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
413 void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
414 WebContents* web_contents) {
415 set_visible(false);
416 if (!web_contents)
417 return;
418 TabSpecificContentSettings* content_settings =
419 TabSpecificContentSettings::FromWebContents(web_contents);
420 if (!content_settings)
421 return;
422 const ContentSettingsUsagesState& usages_state =
423 content_settings->midi_usages_state();
424 if (usages_state.state_map().empty())
425 return;
426 set_visible(true);
428 // If any embedded site has access the allowed icon takes priority over the
429 // blocked icon.
430 unsigned int state_flags = 0;
431 usages_state.GetDetailedInfo(NULL, &state_flags);
432 bool allowed =
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);
437 #else
438 SetIconByVectorId(gfx::VectorIconId::MIDI, !allowed);
439 #endif
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),
447 is_visible_(false),
448 icon_id_(0),
449 explanatory_string_id_(0) {
452 // static
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();
469 default:
470 return new ContentSettingBlockedImageModel(content_settings_type);
474 void ContentSettingImageModel::SetIconByResourceId(int id) {
475 icon_id_ = id;
476 icon_ = ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(id);
479 #if !defined(OS_MACOSX)
480 void ContentSettingImageModel::SetIconByVectorId(gfx::VectorIconId id,
481 bool blocked) {
482 icon_ = GetIcon(id, blocked ? gfx::VectorIconId::BLOCKED_BADGE
483 : gfx::VectorIconId::VECTOR_ICON_NONE);
485 #endif