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_bubble_model.h"
7 #include "base/command_line.h"
8 #include "base/macros.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
14 #include "chrome/browser/content_settings/cookie_settings_factory.h"
15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
16 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
17 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
18 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
19 #include "chrome/browser/infobars/infobar_service.h"
20 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
21 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
24 #include "chrome/browser/ui/browser_navigator.h"
25 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
26 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/common/render_messages.h"
30 #include "chrome/grit/generated_resources.h"
31 #include "components/content_settings/content/common/content_settings_messages.h"
32 #include "components/content_settings/core/browser/content_settings_utils.h"
33 #include "components/content_settings/core/browser/cookie_settings.h"
34 #include "components/content_settings/core/common/content_settings.h"
35 #include "components/url_formatter/elide_url.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/render_frame_host.h"
38 #include "content/public/browser/render_process_host.h"
39 #include "content/public/browser/render_view_host.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/browser/web_contents_delegate.h"
43 #include "content/public/common/origin_util.h"
44 #include "grit/components_strings.h"
45 #include "grit/theme_resources.h"
46 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/base/resource/resource_bundle.h"
48 #include "ui/resources/grit/ui_resources.h"
50 using base::UserMetricsAction
;
51 using content::WebContents
;
52 using content_settings::SettingInfo
;
53 using content_settings::SettingSource
;
54 using content_settings::SETTING_SOURCE_USER
;
55 using content_settings::SETTING_SOURCE_NONE
;
59 const int kAllowButtonIndex
= 0;
62 const ContentSettingsType kSupportedBubbleTypes
[] = {
63 CONTENT_SETTINGS_TYPE_COOKIES
,
64 CONTENT_SETTINGS_TYPE_IMAGES
,
65 CONTENT_SETTINGS_TYPE_JAVASCRIPT
,
66 CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
67 CONTENT_SETTINGS_TYPE_PLUGINS
,
68 CONTENT_SETTINGS_TYPE_POPUPS
,
69 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
70 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
71 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
,
72 CONTENT_SETTINGS_TYPE_MEDIASTREAM
,
73 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
,
74 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
,
77 // These states must match the order of appearance of the radio buttons
78 // in the XIB file for the Mac port.
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
)
100 const content::MediaStreamDevice
& GetMediaDeviceById(
101 const std::string
& device_id
,
102 const content::MediaStreamDevices
& devices
) {
103 DCHECK(!devices
.empty());
104 for (const content::MediaStreamDevice
& device
: devices
) {
105 if (device
.id
== device_id
)
109 // A device with the |device_id| was not found. It is likely that the device
110 // has been unplugged from the OS. Return the first device as the default
112 return *devices
.begin();
117 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
119 WebContents
* web_contents
,
121 ContentSettingsType content_type
)
122 : ContentSettingBubbleModel(web_contents
, profile
, content_type
),
123 delegate_(delegate
) {
124 // Notifications do not have a bubble.
125 DCHECK_NE(content_type
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
131 void ContentSettingTitleAndLinkModel::SetTitle() {
132 TabSpecificContentSettings
* content_settings
= NULL
;
133 if (web_contents()) {
135 TabSpecificContentSettings::FromWebContents(web_contents());
138 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
139 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
140 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
141 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
142 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_TITLE
},
143 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
144 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
145 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
146 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
147 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
148 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
150 // Fields as for kBlockedTitleIDs, above.
151 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
152 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
153 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
154 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
156 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
157 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
158 if (content_settings
&& content_settings
->IsContentAllowed(content_type()) &&
159 !content_settings
->IsContentBlocked(content_type())) {
160 title_ids
= kAccessedTitleIDs
;
161 num_title_ids
= arraysize(kAccessedTitleIDs
);
164 GetIdForContentType(title_ids
, num_title_ids
, content_type());
166 set_title(l10n_util::GetStringUTF8(title_id
));
169 void ContentSettingTitleAndLinkModel::SetManageLink() {
170 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
171 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
172 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
173 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
174 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
175 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
176 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
177 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
178 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
179 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
180 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
181 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
182 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
184 set_manage_link(l10n_util::GetStringUTF8(
185 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
188 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
190 delegate_
->ShowContentSettingsPage(content_type());
193 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
194 static const ContentSettingsTypeIdEntry kLearnMoreIDs
[] = {
195 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_LEARN_MORE
},
198 GetIdForContentType(kLearnMoreIDs
, arraysize(kLearnMoreIDs
),
201 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id
));
204 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
206 delegate_
->ShowLearnMorePage(content_type());
209 class ContentSettingTitleLinkAndCustomModel
210 : public ContentSettingTitleAndLinkModel
{
212 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
213 WebContents
* web_contents
,
215 ContentSettingsType content_type
);
216 ~ContentSettingTitleLinkAndCustomModel() override
{}
219 void SetCustomLink();
220 void OnCustomLinkClicked() override
{}
223 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
225 WebContents
* web_contents
,
227 ContentSettingsType content_type
)
228 : ContentSettingTitleAndLinkModel(
229 delegate
, web_contents
, profile
, content_type
) {
233 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
234 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
235 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
236 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
237 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
240 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
242 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
245 class ContentSettingSingleRadioGroup
246 : public ContentSettingTitleLinkAndCustomModel
{
248 ContentSettingSingleRadioGroup(Delegate
* delegate
,
249 WebContents
* web_contents
,
251 ContentSettingsType content_type
);
252 ~ContentSettingSingleRadioGroup() override
;
255 bool settings_changed() const;
256 int selected_item() const { return selected_item_
; }
259 void SetRadioGroup();
260 void AddException(ContentSetting setting
);
261 void OnRadioClicked(int radio_index
) override
;
263 ContentSetting block_setting_
;
267 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
269 WebContents
* web_contents
,
271 ContentSettingsType content_type
)
272 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
274 block_setting_(CONTENT_SETTING_BLOCK
),
279 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
280 if (settings_changed()) {
281 ContentSetting setting
=
282 selected_item_
== kAllowButtonIndex
?
283 CONTENT_SETTING_ALLOW
:
285 AddException(setting
);
289 bool ContentSettingSingleRadioGroup::settings_changed() const {
290 return selected_item_
!= bubble_content().radio_group
.default_item
;
293 // Initialize the radio group by setting the appropriate labels for the
294 // content type and setting the default value based on the content setting.
295 void ContentSettingSingleRadioGroup::SetRadioGroup() {
296 GURL url
= web_contents()->GetURL();
297 base::string16 display_host
= url_formatter::FormatUrlForSecurityDisplay(
298 url
, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
));
299 if (display_host
.empty())
300 display_host
= base::ASCIIToUTF16(url
.spec());
302 TabSpecificContentSettings
* content_settings
=
303 TabSpecificContentSettings::FromWebContents(web_contents());
305 !content_settings
->IsContentBlocked(content_type());
307 content_settings
->IsContentAllowed(content_type()));
309 RadioGroup radio_group
;
310 radio_group
.url
= url
;
312 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
313 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
314 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
315 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
316 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
317 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
318 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
319 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
321 // Fields as for kBlockedAllowIDs, above.
322 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
323 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ALLOWED_COOKIES_NO_ACTION
},
324 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
325 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
328 std::string radio_allow_label
;
330 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
331 arraysize(kAllowedAllowIDs
),
333 radio_allow_label
= l10n_util::GetStringUTF8(resource_id
);
335 radio_allow_label
= l10n_util::GetStringFUTF8(
336 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
341 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
342 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
343 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
344 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
345 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
346 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
347 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
348 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
350 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
351 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ALLOWED_COOKIES_BLOCK
},
352 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
353 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
356 std::string radio_block_label
;
358 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
359 arraysize(kAllowedBlockIDs
),
361 radio_block_label
= l10n_util::GetStringFUTF8(resource_id
, display_host
);
363 radio_block_label
= l10n_util::GetStringUTF8(
364 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
368 radio_group
.radio_items
.push_back(radio_allow_label
);
369 radio_group
.radio_items
.push_back(radio_block_label
);
370 ContentSetting setting
;
371 SettingSource setting_source
= SETTING_SOURCE_NONE
;
372 bool setting_is_wildcard
= false;
374 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
375 content_settings::CookieSettings
* cookie_settings
=
376 CookieSettingsFactory::GetForProfile(profile()).get();
377 setting
= cookie_settings
->GetCookieSetting(
378 url
, url
, true, &setting_source
);
381 HostContentSettingsMap
* map
=
382 HostContentSettingsMapFactory::GetForProfile(profile());
383 scoped_ptr
<base::Value
> value
=
384 map
->GetWebsiteSetting(url
, url
, content_type(), std::string(), &info
);
385 setting
= content_settings::ValueToContentSetting(value
.get());
386 setting_source
= info
.source
;
387 setting_is_wildcard
=
388 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
389 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
392 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
393 setting
== CONTENT_SETTING_ALLOW
&&
394 setting_is_wildcard
) {
395 // In the corner case of unrecognized plugins (which are now blocked by
396 // default) we indicate the blocked state in the UI and allow the user to
398 radio_group
.default_item
= 1;
399 } else if (setting
== CONTENT_SETTING_ALLOW
) {
400 radio_group
.default_item
= kAllowButtonIndex
;
401 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
403 radio_group
.default_item
= 1;
404 block_setting_
= setting
;
407 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
&&
408 setting
!= CONTENT_SETTING_ASK
);
409 if (setting_source
!= SETTING_SOURCE_USER
) {
410 set_radio_group_enabled(false);
412 set_radio_group_enabled(true);
414 selected_item_
= radio_group
.default_item
;
415 set_radio_group(radio_group
);
418 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
420 HostContentSettingsMapFactory::GetForProfile(profile())->AddExceptionForURL(
421 bubble_content().radio_group
.url
,
422 bubble_content().radio_group
.url
,
428 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
429 selected_item_
= radio_index
;
432 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
434 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
435 WebContents
* web_contents
,
438 ~ContentSettingCookiesBubbleModel() override
;
441 void OnCustomLinkClicked() override
;
444 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
446 WebContents
* web_contents
,
448 : ContentSettingSingleRadioGroup(delegate
,
451 CONTENT_SETTINGS_TYPE_COOKIES
) {
452 set_custom_link_enabled(true);
455 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
456 // On some plattforms e.g. MacOS X it is possible to close a tab while the
457 // cookies settings bubble is open. This resets the web contents to NULL.
458 if (settings_changed() && web_contents()) {
459 CollectedCookiesInfoBarDelegate::Create(
460 InfoBarService::FromWebContents(web_contents()));
464 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
467 content::NotificationService::current()->Notify(
468 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
469 content::Source
<TabSpecificContentSettings
>(
470 TabSpecificContentSettings::FromWebContents(web_contents())),
471 content::NotificationService::NoDetails());
472 delegate()->ShowCollectedCookiesDialog(web_contents());
475 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
477 ContentSettingPluginBubbleModel(Delegate
* delegate
,
478 WebContents
* web_contents
,
481 ~ContentSettingPluginBubbleModel() override
;
484 void OnCustomLinkClicked() override
;
487 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
489 WebContents
* web_contents
,
491 : ContentSettingSingleRadioGroup(delegate
,
494 CONTENT_SETTINGS_TYPE_PLUGINS
) {
495 // Disable the "Run all plugins this time" link if the setting is managed and
496 // can't be controlled by the user or if the user already clicked on the link
497 // and ran all plugins.
498 set_custom_link_enabled(!setting_is_managed() &&
500 TabSpecificContentSettings::FromWebContents(
501 web_contents
)->load_plugins_link_enabled());
502 // Build blocked plugin list.
504 TabSpecificContentSettings
* content_settings
=
505 TabSpecificContentSettings::FromWebContents(web_contents
);
507 const std::vector
<base::string16
>& blocked_plugins
=
508 content_settings
->blocked_plugin_names();
509 for (const base::string16
& blocked_plugin
: blocked_plugins
) {
510 ListItem
plugin_item(
511 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
512 IDR_BLOCKED_PLUGINS
),
513 base::UTF16ToUTF8(blocked_plugin
), false, 0);
514 add_list_item(plugin_item
);
519 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
520 if (settings_changed()) {
521 // If the user elected to allow all plugins then run plugins at this time.
522 if (selected_item() == kAllowButtonIndex
)
523 OnCustomLinkClicked();
527 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
528 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
529 // Web contents can be NULL if the tab was closed while the plugins
530 // settings bubble is visible.
533 #if defined(ENABLE_PLUGINS)
534 // TODO(bauerb): We should send the identifiers of blocked plugins here.
535 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
536 web_contents(), true, std::string());
538 set_custom_link_enabled(false);
539 TabSpecificContentSettings::FromWebContents(web_contents())->
540 set_load_plugins_link_enabled(false);
543 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
545 ContentSettingPopupBubbleModel(Delegate
* delegate
,
546 WebContents
* web_contents
,
548 ~ContentSettingPopupBubbleModel() override
{}
551 void OnListItemClicked(int index
) override
;
553 int32
item_id_from_item_index(int index
) const {
554 return bubble_content().list_items
[index
].item_id
;
558 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
560 WebContents
* web_contents
,
562 : ContentSettingSingleRadioGroup(delegate
,
565 CONTENT_SETTINGS_TYPE_POPUPS
) {
567 // Build blocked popup list.
568 std::map
<int32
, GURL
> blocked_popups
=
569 PopupBlockerTabHelper::FromWebContents(web_contents
)
570 ->GetBlockedPopupRequests();
571 for (const std::pair
<int32
, GURL
>& blocked_popup
: blocked_popups
) {
572 std::string
title(blocked_popup
.second
.spec());
573 // The pop-up may not have a valid URL.
575 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
576 ListItem
popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
577 IDR_DEFAULT_FAVICON
),
578 title
, true, blocked_popup
.first
);
579 add_list_item(popup_item
);
584 void ContentSettingPopupBubbleModel::OnListItemClicked(int index
) {
585 if (web_contents()) {
586 PopupBlockerTabHelper::FromWebContents(web_contents())
587 ->ShowBlockedPopup(item_id_from_item_index(index
));
591 // The model of the content settings bubble for media settings.
592 class ContentSettingMediaStreamBubbleModel
593 : public ContentSettingTitleAndLinkModel
{
595 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
596 WebContents
* web_contents
,
599 ~ContentSettingMediaStreamBubbleModel() override
;
601 void OnManageLinkClicked() override
;
604 // Helper functions to check if this bubble was invoked for microphone,
605 // camera, or both devices.
606 bool MicrophoneAccessed() const;
607 bool CameraAccessed() const;
610 // Sets the data for the radio buttons of the bubble.
611 void SetRadioGroup();
612 // Sets the data for the media menus of the bubble.
613 void SetMediaMenus();
614 // Set the settings management link.
615 void SetManageLink();
616 void SetCustomLink();
617 // Updates the camera and microphone setting with the passed |setting|.
618 void UpdateSettings(ContentSetting setting
);
619 // Updates the camera and microphone default device with the passed |type|
621 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
622 const std::string
& device
);
624 // ContentSettingBubbleModel implementation.
625 void OnRadioClicked(int radio_index
) override
;
626 void OnMediaMenuClicked(content::MediaStreamType type
,
627 const std::string
& selected_device
) override
;
629 // The index of the selected radio item.
631 // The content settings that are associated with the individual radio
633 ContentSetting radio_item_setting_
[2];
634 // The state of the microphone and camera access.
635 TabSpecificContentSettings::MicrophoneCameraState state_
;
638 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
640 WebContents
* web_contents
,
642 : ContentSettingTitleAndLinkModel(
643 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
645 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
646 // TODO(msramek): Every bubble is tied to a particular content setting.
647 // The media bubble has three states - mic only, camera only, and both.
648 // However, it is always tied to the deprecated MEDIASTREAM setting. Refactor
649 // this so that it refers to the MIC setting for microphone and CAMERA
650 // setting for camera to reduce the duplication of code in practically every
651 // method. Furthermore, it should be possible not to tie the bubble to any
652 // particular content setting type, as we still need the bubble for both
653 // camera and microphone, but should not use the deprecated MEDIASTREAM
657 // Initialize the content settings associated with the individual radio
659 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
660 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
662 TabSpecificContentSettings
* content_settings
=
663 TabSpecificContentSettings::FromWebContents(web_contents
);
664 state_
= content_settings
->GetMicrophoneCameraState();
665 DCHECK(CameraAccessed() || MicrophoneAccessed());
674 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
675 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
676 // media stream bubble is open. This resets the web contents to NULL.
680 for (const std::pair
<content::MediaStreamType
, MediaMenu
>& media_menu
:
681 bubble_content().media_menus
) {
682 if (media_menu
.second
.selected_device
.id
!=
683 media_menu
.second
.default_device
.id
) {
684 UpdateDefaultDeviceForType(media_menu
.first
,
685 media_menu
.second
.selected_device
.id
);
689 // Update the media settings if the radio button selection was changed.
690 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
691 UpdateSettings(radio_item_setting_
[selected_item_
]);
695 bool ContentSettingMediaStreamBubbleModel::MicrophoneAccessed() const {
696 return (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
699 bool ContentSettingMediaStreamBubbleModel::CameraAccessed() const {
700 return (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
703 void ContentSettingMediaStreamBubbleModel::OnManageLinkClicked() {
707 if (MicrophoneAccessed()) {
708 delegate()->ShowContentSettingsPage(CameraAccessed()
709 ? CONTENT_SETTINGS_TYPE_MEDIASTREAM
710 : CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
);
712 delegate()->ShowContentSettingsPage(
713 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
);
717 void ContentSettingMediaStreamBubbleModel::SetTitle() {
718 DCHECK(CameraAccessed() || MicrophoneAccessed());
720 if (state_
& TabSpecificContentSettings::MICROPHONE_BLOCKED
) {
721 title_id
= (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) ?
722 IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
723 } else if (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) {
724 title_id
= IDS_CAMERA_BLOCKED
;
725 } else if (MicrophoneAccessed()) {
726 title_id
= CameraAccessed() ? IDS_MICROPHONE_CAMERA_ALLOWED
727 : IDS_MICROPHONE_ACCESSED
;
728 } else if (CameraAccessed()) {
729 title_id
= IDS_CAMERA_ACCESSED
;
731 set_title(l10n_util::GetStringUTF8(title_id
));
734 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
735 TabSpecificContentSettings
* content_settings
=
736 TabSpecificContentSettings::FromWebContents(web_contents());
737 GURL url
= content_settings
->media_stream_access_origin();
738 RadioGroup radio_group
;
739 radio_group
.url
= url
;
741 base::string16 display_host_utf16
=
742 url_formatter::FormatUrlForSecurityDisplay(
743 url
, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
));
744 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
745 if (display_host
.empty())
746 display_host
= url
.spec();
748 DCHECK(CameraAccessed() || MicrophoneAccessed());
749 int radio_allow_label_id
= 0;
750 int radio_block_label_id
= 0;
751 if (state_
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
752 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
753 if (content::IsOriginSecure(url
)) {
754 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
755 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
756 if (MicrophoneAccessed())
757 radio_allow_label_id
= CameraAccessed() ?
758 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
:
759 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
761 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
762 if (MicrophoneAccessed())
763 radio_allow_label_id
= CameraAccessed() ?
764 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
:
765 IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
767 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
768 if (MicrophoneAccessed())
769 radio_block_label_id
= CameraAccessed() ?
770 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
:
771 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
773 if (MicrophoneAccessed() && CameraAccessed()) {
774 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
775 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
776 } else if (MicrophoneAccessed()) {
777 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
778 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
780 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
781 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
785 (MicrophoneAccessed() && content_settings
->IsContentBlocked(
786 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
)) ||
787 (CameraAccessed() && content_settings
->IsContentBlocked(
788 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
)) ? 1 : 0;
790 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
791 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
792 std::string radio_block_label
=
793 l10n_util::GetStringUTF8(radio_block_label_id
);
795 radio_group
.default_item
= selected_item_
;
796 radio_group
.radio_items
.push_back(radio_allow_label
);
797 radio_group
.radio_items
.push_back(radio_block_label
);
799 set_radio_group(radio_group
);
800 set_radio_group_enabled(true);
803 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
804 ContentSetting setting
) {
806 HostContentSettingsMap
* content_settings
=
807 HostContentSettingsMapFactory::GetForProfile(profile());
808 TabSpecificContentSettings
* tab_content_settings
=
809 TabSpecificContentSettings::FromWebContents(web_contents());
810 // The same patterns must be used as in other places (e.g. the infobar) in
811 // order to override the existing rule. Otherwise a new rule is created.
812 // TODO(markusheintz): Extract to a helper so that there is only a single
814 ContentSettingsPattern primary_pattern
=
815 ContentSettingsPattern::FromURLNoWildcard(
816 tab_content_settings
->media_stream_access_origin());
817 ContentSettingsPattern secondary_pattern
=
818 ContentSettingsPattern::Wildcard();
819 if (MicrophoneAccessed()) {
820 content_settings
->SetContentSetting(
821 primary_pattern
, secondary_pattern
,
822 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
824 if (CameraAccessed()) {
825 content_settings
->SetContentSetting(
826 primary_pattern
, secondary_pattern
,
827 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string(), setting
);
832 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
833 content::MediaStreamType type
,
834 const std::string
& device
) {
835 PrefService
* prefs
= profile()->GetPrefs();
836 if (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
837 prefs
->SetString(prefs::kDefaultAudioCaptureDevice
, device
);
839 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE
, type
);
840 prefs
->SetString(prefs::kDefaultVideoCaptureDevice
, device
);
844 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
845 TabSpecificContentSettings
* content_settings
=
846 TabSpecificContentSettings::FromWebContents(web_contents());
847 const std::string
& requested_microphone
=
848 content_settings
->media_stream_requested_audio_device();
849 const std::string
& requested_camera
=
850 content_settings
->media_stream_requested_video_device();
852 // Add microphone menu.
853 PrefService
* prefs
= profile()->GetPrefs();
854 MediaCaptureDevicesDispatcher
* dispatcher
=
855 MediaCaptureDevicesDispatcher::GetInstance();
856 const content::MediaStreamDevices
& microphones
=
857 dispatcher
->GetAudioCaptureDevices();
859 if (MicrophoneAccessed()) {
861 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
862 if (!microphones
.empty()) {
863 std::string preferred_mic
;
864 if (requested_microphone
.empty()) {
865 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
866 mic_menu
.disabled
= false;
868 // Set the |disabled| to true in order to disable the device selection
869 // menu on the media settings bubble. This must be done if the website
870 // manages the microphone devices itself.
871 preferred_mic
= requested_microphone
;
872 mic_menu
.disabled
= true;
875 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
876 mic_menu
.selected_device
= mic_menu
.default_device
;
878 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
881 if (CameraAccessed()) {
882 const content::MediaStreamDevices
& cameras
=
883 dispatcher
->GetVideoCaptureDevices();
884 MediaMenu camera_menu
;
886 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
887 if (!cameras
.empty()) {
888 std::string preferred_camera
;
889 if (requested_camera
.empty()) {
890 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
891 camera_menu
.disabled
= false;
893 // Disable the menu since the website is managing the camera devices
895 preferred_camera
= requested_camera
;
896 camera_menu
.disabled
= true;
899 camera_menu
.default_device
=
900 GetMediaDeviceById(preferred_camera
, cameras
);
901 camera_menu
.selected_device
= camera_menu
.default_device
;
903 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
907 void ContentSettingMediaStreamBubbleModel::SetManageLink() {
908 // By default, the manage link refers to both media types. We only need
909 // to change the link text if only one media type was accessed.
910 if (CameraAccessed() && MicrophoneAccessed())
913 set_manage_link(l10n_util::GetStringUTF8(MicrophoneAccessed()
914 ? IDS_MEDIASTREAM_MICROPHONE_BUBBLE_MANAGE_LINK
915 : IDS_MEDIASTREAM_CAMERA_BUBBLE_MANAGE_LINK
));
918 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
919 TabSpecificContentSettings
* content_settings
=
920 TabSpecificContentSettings::FromWebContents(web_contents());
921 if (content_settings
->IsMicrophoneCameraStateChanged()) {
922 set_custom_link(l10n_util::GetStringUTF8(
923 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE
));
927 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
928 selected_item_
= radio_index
;
931 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
932 content::MediaStreamType type
,
933 const std::string
& selected_device_id
) {
934 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
935 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
936 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
937 MediaCaptureDevicesDispatcher
* dispatcher
=
938 MediaCaptureDevicesDispatcher::GetInstance();
939 const content::MediaStreamDevices
& devices
=
940 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
941 dispatcher
->GetAudioCaptureDevices() :
942 dispatcher
->GetVideoCaptureDevices();
943 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
946 class ContentSettingDomainListBubbleModel
947 : public ContentSettingTitleAndLinkModel
{
949 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
950 WebContents
* web_contents
,
952 ContentSettingsType content_type
);
953 ~ContentSettingDomainListBubbleModel() override
{}
956 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
957 void SetDomainsAndCustomLink();
958 void OnCustomLinkClicked() override
;
961 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
963 WebContents
* web_contents
,
965 ContentSettingsType content_type
)
966 : ContentSettingTitleAndLinkModel(
967 delegate
, web_contents
, profile
, content_type
) {
968 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
969 "SetDomains currently only supports geolocation content type";
970 SetDomainsAndCustomLink();
973 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
974 const std::set
<std::string
>& hosts
, int title_id
) {
975 if (!hosts
.empty()) {
976 DomainList domain_list
;
977 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
978 domain_list
.hosts
= hosts
;
979 add_domain_list(domain_list
);
983 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
984 TabSpecificContentSettings
* content_settings
=
985 TabSpecificContentSettings::FromWebContents(web_contents());
986 const ContentSettingsUsagesState
& usages
=
987 content_settings
->geolocation_usages_state();
988 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
989 unsigned int tab_state_flags
= 0;
990 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
991 // Divide the tab's current geolocation users into sets according to their
993 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
994 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
996 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
997 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
999 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1000 set_custom_link(l10n_util::GetStringUTF8(
1001 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
1002 set_custom_link_enabled(true);
1003 } else if (tab_state_flags
&
1004 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1005 set_custom_link(l10n_util::GetStringUTF8(
1006 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1010 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
1011 if (!web_contents())
1013 // Reset this embedder's entry to default for each of the requesting
1014 // origins currently on the page.
1015 const GURL
& embedder_url
= web_contents()->GetURL();
1016 TabSpecificContentSettings
* content_settings
=
1017 TabSpecificContentSettings::FromWebContents(web_contents());
1018 const ContentSettingsUsagesState::StateMap
& state_map
=
1019 content_settings
->geolocation_usages_state().state_map();
1020 HostContentSettingsMap
* settings_map
=
1021 HostContentSettingsMapFactory::GetForProfile(profile());
1023 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
1024 settings_map
->SetContentSetting(
1025 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
1026 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1027 CONTENT_SETTINGS_TYPE_GEOLOCATION
, std::string(),
1028 CONTENT_SETTING_DEFAULT
);
1032 class ContentSettingMixedScriptBubbleModel
1033 : public ContentSettingTitleLinkAndCustomModel
{
1035 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
1036 WebContents
* web_contents
,
1039 ~ContentSettingMixedScriptBubbleModel() override
{}
1042 void OnCustomLinkClicked() override
;
1045 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
1047 WebContents
* web_contents
,
1049 : ContentSettingTitleLinkAndCustomModel(delegate
,
1052 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1053 content_settings::RecordMixedScriptAction(
1054 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE
);
1055 set_custom_link_enabled(true);
1058 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
1059 DCHECK(web_contents());
1060 web_contents()->SendToAllFrames(
1061 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE
, true));
1062 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1063 web_contents()->GetMainFrame()->GetRoutingID()));
1065 content_settings::RecordMixedScriptAction(
1066 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
);
1067 content_settings::RecordMixedScriptActionWithRAPPOR(
1068 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
,
1069 web_contents()->GetLastCommittedURL());
1072 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1074 WebContents
* web_contents
,
1076 ProtocolHandlerRegistry
* registry
)
1077 : ContentSettingTitleAndLinkModel(delegate
,
1080 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
),
1082 registry_(registry
),
1083 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1084 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1085 TabSpecificContentSettings
* content_settings
=
1086 TabSpecificContentSettings::FromWebContents(web_contents
);
1087 pending_handler_
= content_settings
->pending_protocol_handler();
1088 previous_handler_
= content_settings
->previous_protocol_handler();
1090 base::string16 protocol
;
1091 if (pending_handler_
.protocol() == "mailto") {
1092 protocol
= l10n_util::GetStringUTF16(
1093 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1094 } else if (pending_handler_
.protocol() == "webcal") {
1095 protocol
= l10n_util::GetStringUTF16(
1096 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1098 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1101 // Note that we ignore the |title| parameter.
1102 if (previous_handler_
.IsEmpty()) {
1103 set_title(l10n_util::GetStringFUTF8(
1104 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1105 base::UTF8ToUTF16(pending_handler_
.url().host()),
1108 set_title(l10n_util::GetStringFUTF8(
1109 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1110 base::UTF8ToUTF16(pending_handler_
.url().host()),
1112 base::UTF8ToUTF16(previous_handler_
.url().host())));
1115 std::string radio_allow_label
=
1116 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
);
1117 std::string radio_deny_label
=
1118 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY
);
1119 std::string radio_ignore_label
=
1120 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE
);
1122 GURL url
= web_contents
->GetURL();
1123 RadioGroup radio_group
;
1124 radio_group
.url
= url
;
1126 radio_group
.radio_items
.push_back(radio_allow_label
);
1127 radio_group
.radio_items
.push_back(radio_deny_label
);
1128 radio_group
.radio_items
.push_back(radio_ignore_label
);
1129 ContentSetting setting
=
1130 content_settings
->pending_protocol_handler_setting();
1131 if (setting
== CONTENT_SETTING_ALLOW
)
1132 radio_group
.default_item
= RPH_ALLOW
;
1133 else if (setting
== CONTENT_SETTING_BLOCK
)
1134 radio_group
.default_item
= RPH_BLOCK
;
1136 radio_group
.default_item
= RPH_IGNORE
;
1138 selected_item_
= radio_group
.default_item
;
1139 set_radio_group_enabled(true);
1140 set_radio_group(radio_group
);
1143 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index
) {
1144 if (selected_item_
== radio_index
)
1147 selected_item_
= radio_index
;
1149 if (radio_index
== RPH_ALLOW
)
1150 RegisterProtocolHandler();
1151 else if (radio_index
== RPH_BLOCK
)
1152 UnregisterProtocolHandler();
1153 else if (radio_index
== RPH_IGNORE
)
1154 IgnoreProtocolHandler();
1159 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1160 // The user has one chance to deal with the RPH content setting UI,
1161 // then we remove it.
1162 TabSpecificContentSettings::FromWebContents(web_contents())->
1163 ClearPendingProtocolHandler();
1164 content::NotificationService::current()->Notify(
1165 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
1166 content::Source
<WebContents
>(web_contents()),
1167 content::NotificationService::NoDetails());
1170 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1171 // A no-op if the handler hasn't been ignored, but needed in case the user
1172 // selects sequences like register/ignore/register.
1173 registry_
->RemoveIgnoredHandler(pending_handler_
);
1175 registry_
->OnAcceptRegisterProtocolHandler(pending_handler_
);
1176 TabSpecificContentSettings::FromWebContents(web_contents())->
1177 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW
);
1180 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1181 registry_
->OnDenyRegisterProtocolHandler(pending_handler_
);
1182 TabSpecificContentSettings::FromWebContents(web_contents())->
1183 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK
);
1184 ClearOrSetPreviousHandler();
1187 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1188 registry_
->OnIgnoreRegisterProtocolHandler(pending_handler_
);
1189 TabSpecificContentSettings::FromWebContents(web_contents())->
1190 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT
);
1191 ClearOrSetPreviousHandler();
1194 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1195 if (previous_handler_
.IsEmpty()) {
1196 registry_
->ClearDefault(pending_handler_
.protocol());
1198 registry_
->OnAcceptRegisterProtocolHandler(previous_handler_
);
1202 class ContentSettingMidiSysExBubbleModel
1203 : public ContentSettingTitleAndLinkModel
{
1205 ContentSettingMidiSysExBubbleModel(Delegate
* delegate
,
1206 WebContents
* web_contents
,
1208 ~ContentSettingMidiSysExBubbleModel() override
{}
1211 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1212 void SetDomainsAndCustomLink();
1213 void OnCustomLinkClicked() override
;
1216 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1218 WebContents
* web_contents
,
1220 : ContentSettingTitleAndLinkModel(delegate
,
1223 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1224 SetDomainsAndCustomLink();
1227 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1228 const std::set
<std::string
>& hosts
, int title_id
) {
1229 if (!hosts
.empty()) {
1230 DomainList domain_list
;
1231 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
1232 domain_list
.hosts
= hosts
;
1233 add_domain_list(domain_list
);
1237 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1238 TabSpecificContentSettings
* content_settings
=
1239 TabSpecificContentSettings::FromWebContents(web_contents());
1240 const ContentSettingsUsagesState
& usages_state
=
1241 content_settings
->midi_usages_state();
1242 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
1243 unsigned int tab_state_flags
= 0;
1244 usages_state
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
1245 // Divide the tab's current MIDI sysex users into sets according to their
1246 // permission state.
1247 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
1248 IDS_MIDI_SYSEX_BUBBLE_ALLOWED
);
1250 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
1251 IDS_MIDI_SYSEX_BUBBLE_DENIED
);
1253 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1254 set_custom_link(l10n_util::GetStringUTF8(
1255 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK
));
1256 set_custom_link_enabled(true);
1257 } else if (tab_state_flags
&
1258 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1259 set_custom_link(l10n_util::GetStringUTF8(
1260 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1264 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1265 if (!web_contents())
1267 // Reset this embedder's entry to default for each of the requesting
1268 // origins currently on the page.
1269 const GURL
& embedder_url
= web_contents()->GetURL();
1270 TabSpecificContentSettings
* content_settings
=
1271 TabSpecificContentSettings::FromWebContents(web_contents());
1272 const ContentSettingsUsagesState::StateMap
& state_map
=
1273 content_settings
->midi_usages_state().state_map();
1274 HostContentSettingsMap
* settings_map
=
1275 HostContentSettingsMapFactory::GetForProfile(profile());
1277 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
1278 settings_map
->SetContentSetting(
1279 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
1280 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1281 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, std::string(),
1282 CONTENT_SETTING_DEFAULT
);
1287 const std::set
<ContentSettingsType
>&
1288 ContentSettingBubbleModel::GetSupportedBubbleTypes() {
1289 CR_DEFINE_STATIC_LOCAL(
1290 const std::set
<ContentSettingsType
>, supported_bubble_types
,
1291 (kSupportedBubbleTypes
,
1292 kSupportedBubbleTypes
+ arraysize(kSupportedBubbleTypes
)));
1293 return supported_bubble_types
;
1297 ContentSettingBubbleModel
*
1298 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1300 WebContents
* web_contents
,
1302 ContentSettingsType content_type
) {
1303 DCHECK(ContainsKey(GetSupportedBubbleTypes(), content_type
));
1304 if (content_type
== CONTENT_SETTINGS_TYPE_COOKIES
) {
1305 return new ContentSettingCookiesBubbleModel(delegate
, web_contents
,
1308 if (content_type
== CONTENT_SETTINGS_TYPE_POPUPS
) {
1309 return new ContentSettingPopupBubbleModel(delegate
, web_contents
, profile
);
1311 if (content_type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
1312 return new ContentSettingDomainListBubbleModel(delegate
, web_contents
,
1313 profile
, content_type
);
1315 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
1316 return new ContentSettingMediaStreamBubbleModel(delegate
, web_contents
,
1319 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
1320 return new ContentSettingPluginBubbleModel(delegate
, web_contents
, profile
);
1322 if (content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1323 return new ContentSettingMixedScriptBubbleModel(delegate
, web_contents
,
1326 if (content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
1327 ProtocolHandlerRegistry
* registry
=
1328 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile
);
1329 return new ContentSettingRPHBubbleModel(delegate
, web_contents
, profile
,
1332 if (content_type
== CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1333 return new ContentSettingMidiSysExBubbleModel(delegate
, web_contents
,
1336 return new ContentSettingSingleRadioGroup(delegate
, web_contents
, profile
,
1340 ContentSettingBubbleModel::ContentSettingBubbleModel(
1341 WebContents
* web_contents
,
1343 ContentSettingsType content_type
)
1344 : web_contents_(web_contents
),
1346 content_type_(content_type
),
1347 setting_is_managed_(false) {
1348 registrar_
.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1349 content::Source
<WebContents
>(web_contents
));
1350 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
1351 content::Source
<Profile
>(profile_
));
1354 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1357 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1359 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1361 ContentSettingBubbleModel::DomainList::DomainList() {}
1363 ContentSettingBubbleModel::DomainList::~DomainList() {}
1365 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1367 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1369 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1370 : radio_group_enabled(false),
1371 custom_link_enabled(false) {
1374 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1376 void ContentSettingBubbleModel::Observe(
1378 const content::NotificationSource
& source
,
1379 const content::NotificationDetails
& details
) {
1380 if (type
== content::NOTIFICATION_WEB_CONTENTS_DESTROYED
) {
1381 DCHECK_EQ(web_contents_
,
1382 content::Source
<WebContents
>(source
).ptr());
1383 web_contents_
= NULL
;
1385 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
1386 DCHECK_EQ(profile_
, content::Source
<Profile
>(source
).ptr());