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/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
12 #include "chrome/browser/content_settings/cookie_settings_factory.h"
13 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
14 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
15 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
18 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
23 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/render_messages.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "components/content_settings/content/common/content_settings_messages.h"
29 #include "components/content_settings/core/browser/content_settings_utils.h"
30 #include "components/content_settings/core/browser/cookie_settings.h"
31 #include "components/content_settings/core/common/content_settings.h"
32 #include "components/url_formatter/elide_url.h"
33 #include "content/public/browser/notification_service.h"
34 #include "content/public/browser/render_frame_host.h"
35 #include "content/public/browser/render_process_host.h"
36 #include "content/public/browser/render_view_host.h"
37 #include "content/public/browser/user_metrics.h"
38 #include "content/public/browser/web_contents.h"
39 #include "content/public/browser/web_contents_delegate.h"
40 #include "content/public/common/origin_util.h"
41 #include "grit/components_strings.h"
42 #include "grit/theme_resources.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h"
45 #include "ui/resources/grit/ui_resources.h"
47 using base::UserMetricsAction
;
48 using content::WebContents
;
49 using content_settings::SettingInfo
;
50 using content_settings::SettingSource
;
51 using content_settings::SETTING_SOURCE_USER
;
52 using content_settings::SETTING_SOURCE_NONE
;
56 const int kAllowButtonIndex
= 0;
58 // These states must match the order of appearance of the radio buttons
59 // in the XIB file for the Mac port.
66 struct ContentSettingsTypeIdEntry
{
67 ContentSettingsType type
;
71 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
73 ContentSettingsType type
) {
74 for (size_t i
= 0; i
< num_entries
; ++i
) {
75 if (entries
[i
].type
== type
)
81 const content::MediaStreamDevice
& GetMediaDeviceById(
82 const std::string
& device_id
,
83 const content::MediaStreamDevices
& devices
) {
84 DCHECK(!devices
.empty());
85 for (const content::MediaStreamDevice
& device
: devices
) {
86 if (device
.id
== device_id
)
90 // A device with the |device_id| was not found. It is likely that the device
91 // has been unplugged from the OS. Return the first device as the default
93 return *devices
.begin();
98 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
100 WebContents
* web_contents
,
102 ContentSettingsType content_type
)
103 : ContentSettingBubbleModel(web_contents
, profile
, content_type
),
104 delegate_(delegate
) {
105 // Notifications do not have a bubble.
106 DCHECK_NE(content_type
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
112 void ContentSettingTitleAndLinkModel::SetTitle() {
113 TabSpecificContentSettings
* content_settings
= NULL
;
114 if (web_contents()) {
116 TabSpecificContentSettings::FromWebContents(web_contents());
119 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
120 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
121 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
122 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
123 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_TITLE
},
124 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
125 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
126 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
127 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
128 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
129 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
131 // Fields as for kBlockedTitleIDs, above.
132 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
133 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
134 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
135 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
137 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
138 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
139 if (content_settings
&& content_settings
->IsContentAllowed(content_type()) &&
140 !content_settings
->IsContentBlocked(content_type())) {
141 title_ids
= kAccessedTitleIDs
;
142 num_title_ids
= arraysize(kAccessedTitleIDs
);
145 GetIdForContentType(title_ids
, num_title_ids
, content_type());
147 set_title(l10n_util::GetStringUTF8(title_id
));
150 void ContentSettingTitleAndLinkModel::SetManageLink() {
151 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
152 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
153 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
154 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
155 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
156 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
157 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
158 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
159 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
160 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
161 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
162 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
163 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
165 set_manage_link(l10n_util::GetStringUTF8(
166 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
169 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
171 delegate_
->ShowContentSettingsPage(content_type());
174 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
175 static const ContentSettingsTypeIdEntry kLearnMoreIDs
[] = {
176 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_LEARN_MORE
},
179 GetIdForContentType(kLearnMoreIDs
, arraysize(kLearnMoreIDs
),
182 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id
));
185 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
187 delegate_
->ShowLearnMorePage(content_type());
190 class ContentSettingTitleLinkAndCustomModel
191 : public ContentSettingTitleAndLinkModel
{
193 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
194 WebContents
* web_contents
,
196 ContentSettingsType content_type
);
197 ~ContentSettingTitleLinkAndCustomModel() override
{}
200 void SetCustomLink();
201 void OnCustomLinkClicked() override
{}
204 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
206 WebContents
* web_contents
,
208 ContentSettingsType content_type
)
209 : ContentSettingTitleAndLinkModel(
210 delegate
, web_contents
, profile
, content_type
) {
214 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
215 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
216 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
217 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
218 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
221 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
223 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
226 class ContentSettingSingleRadioGroup
227 : public ContentSettingTitleLinkAndCustomModel
{
229 ContentSettingSingleRadioGroup(Delegate
* delegate
,
230 WebContents
* web_contents
,
232 ContentSettingsType content_type
);
233 ~ContentSettingSingleRadioGroup() override
;
236 bool settings_changed() const;
237 int selected_item() const { return selected_item_
; }
240 void SetRadioGroup();
241 void AddException(ContentSetting setting
);
242 void OnRadioClicked(int radio_index
) override
;
244 ContentSetting block_setting_
;
248 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
250 WebContents
* web_contents
,
252 ContentSettingsType content_type
)
253 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
255 block_setting_(CONTENT_SETTING_BLOCK
),
260 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
261 if (settings_changed()) {
262 ContentSetting setting
=
263 selected_item_
== kAllowButtonIndex
?
264 CONTENT_SETTING_ALLOW
:
266 AddException(setting
);
270 bool ContentSettingSingleRadioGroup::settings_changed() const {
271 return selected_item_
!= bubble_content().radio_group
.default_item
;
274 // Initialize the radio group by setting the appropriate labels for the
275 // content type and setting the default value based on the content setting.
276 void ContentSettingSingleRadioGroup::SetRadioGroup() {
277 GURL url
= web_contents()->GetURL();
278 base::string16 display_host
= url_formatter::FormatUrlForSecurityDisplay(
279 url
, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
));
280 if (display_host
.empty())
281 display_host
= base::ASCIIToUTF16(url
.spec());
283 TabSpecificContentSettings
* content_settings
=
284 TabSpecificContentSettings::FromWebContents(web_contents());
286 !content_settings
->IsContentBlocked(content_type());
288 content_settings
->IsContentAllowed(content_type()));
290 RadioGroup radio_group
;
291 radio_group
.url
= url
;
293 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
294 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
295 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
296 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
297 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
298 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
299 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
300 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
302 // Fields as for kBlockedAllowIDs, above.
303 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
304 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ALLOWED_COOKIES_NO_ACTION
},
305 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
306 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
309 std::string radio_allow_label
;
311 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
312 arraysize(kAllowedAllowIDs
),
314 radio_allow_label
= l10n_util::GetStringUTF8(resource_id
);
316 radio_allow_label
= l10n_util::GetStringFUTF8(
317 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
322 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
323 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
324 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
325 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
326 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
327 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
328 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
329 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
331 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
332 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ALLOWED_COOKIES_BLOCK
},
333 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
334 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
337 std::string radio_block_label
;
339 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
340 arraysize(kAllowedBlockIDs
),
342 radio_block_label
= l10n_util::GetStringFUTF8(resource_id
, display_host
);
344 radio_block_label
= l10n_util::GetStringUTF8(
345 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
349 radio_group
.radio_items
.push_back(radio_allow_label
);
350 radio_group
.radio_items
.push_back(radio_block_label
);
351 ContentSetting setting
;
352 SettingSource setting_source
= SETTING_SOURCE_NONE
;
353 bool setting_is_wildcard
= false;
355 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
356 content_settings::CookieSettings
* cookie_settings
=
357 CookieSettingsFactory::GetForProfile(profile()).get();
358 setting
= cookie_settings
->GetCookieSetting(
359 url
, url
, true, &setting_source
);
362 HostContentSettingsMap
* map
= profile()->GetHostContentSettingsMap();
363 scoped_ptr
<base::Value
> value
=
364 map
->GetWebsiteSetting(url
, url
, content_type(), std::string(), &info
);
365 setting
= content_settings::ValueToContentSetting(value
.get());
366 setting_source
= info
.source
;
367 setting_is_wildcard
=
368 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
369 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
372 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
373 setting
== CONTENT_SETTING_ALLOW
&&
374 setting_is_wildcard
) {
375 // In the corner case of unrecognized plugins (which are now blocked by
376 // default) we indicate the blocked state in the UI and allow the user to
378 radio_group
.default_item
= 1;
379 } else if (setting
== CONTENT_SETTING_ALLOW
) {
380 radio_group
.default_item
= kAllowButtonIndex
;
381 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
383 radio_group
.default_item
= 1;
384 block_setting_
= setting
;
387 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
&&
388 setting
!= CONTENT_SETTING_ASK
);
389 if (setting_source
!= SETTING_SOURCE_USER
) {
390 set_radio_group_enabled(false);
392 set_radio_group_enabled(true);
394 selected_item_
= radio_group
.default_item
;
395 set_radio_group(radio_group
);
398 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
400 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
401 bubble_content().radio_group
.url
,
402 bubble_content().radio_group
.url
,
408 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
409 selected_item_
= radio_index
;
412 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
414 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
415 WebContents
* web_contents
,
418 ~ContentSettingCookiesBubbleModel() override
;
421 void OnCustomLinkClicked() override
;
424 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
426 WebContents
* web_contents
,
428 : ContentSettingSingleRadioGroup(delegate
,
431 CONTENT_SETTINGS_TYPE_COOKIES
) {
432 set_custom_link_enabled(true);
435 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
436 // On some plattforms e.g. MacOS X it is possible to close a tab while the
437 // cookies settings bubble is open. This resets the web contents to NULL.
438 if (settings_changed() && web_contents()) {
439 CollectedCookiesInfoBarDelegate::Create(
440 InfoBarService::FromWebContents(web_contents()));
444 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
447 content::NotificationService::current()->Notify(
448 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
449 content::Source
<TabSpecificContentSettings
>(
450 TabSpecificContentSettings::FromWebContents(web_contents())),
451 content::NotificationService::NoDetails());
452 delegate()->ShowCollectedCookiesDialog(web_contents());
455 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
457 ContentSettingPluginBubbleModel(Delegate
* delegate
,
458 WebContents
* web_contents
,
461 ~ContentSettingPluginBubbleModel() override
;
464 void OnCustomLinkClicked() override
;
467 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
469 WebContents
* web_contents
,
471 : ContentSettingSingleRadioGroup(delegate
,
474 CONTENT_SETTINGS_TYPE_PLUGINS
) {
475 // Disable the "Run all plugins this time" link if the setting is managed and
476 // can't be controlled by the user or if the user already clicked on the link
477 // and ran all plugins.
478 set_custom_link_enabled(!setting_is_managed() &&
480 TabSpecificContentSettings::FromWebContents(
481 web_contents
)->load_plugins_link_enabled());
482 // Build blocked plugin list.
484 TabSpecificContentSettings
* content_settings
=
485 TabSpecificContentSettings::FromWebContents(web_contents
);
487 const std::vector
<base::string16
>& blocked_plugins
=
488 content_settings
->blocked_plugin_names();
489 for (const base::string16
& blocked_plugin
: blocked_plugins
) {
490 ListItem
plugin_item(
491 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
492 IDR_BLOCKED_PLUGINS
),
493 base::UTF16ToUTF8(blocked_plugin
), false, 0);
494 add_list_item(plugin_item
);
499 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
500 if (settings_changed()) {
501 // If the user elected to allow all plugins then run plugins at this time.
502 if (selected_item() == kAllowButtonIndex
)
503 OnCustomLinkClicked();
507 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
508 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
509 // Web contents can be NULL if the tab was closed while the plugins
510 // settings bubble is visible.
513 #if defined(ENABLE_PLUGINS)
514 // TODO(bauerb): We should send the identifiers of blocked plugins here.
515 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
516 web_contents(), true, std::string());
518 set_custom_link_enabled(false);
519 TabSpecificContentSettings::FromWebContents(web_contents())->
520 set_load_plugins_link_enabled(false);
523 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
525 ContentSettingPopupBubbleModel(Delegate
* delegate
,
526 WebContents
* web_contents
,
528 ~ContentSettingPopupBubbleModel() override
{}
531 void OnListItemClicked(int index
) override
;
533 int32
item_id_from_item_index(int index
) const {
534 return bubble_content().list_items
[index
].item_id
;
538 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
540 WebContents
* web_contents
,
542 : ContentSettingSingleRadioGroup(delegate
,
545 CONTENT_SETTINGS_TYPE_POPUPS
) {
547 // Build blocked popup list.
548 std::map
<int32
, GURL
> blocked_popups
=
549 PopupBlockerTabHelper::FromWebContents(web_contents
)
550 ->GetBlockedPopupRequests();
551 for (const std::pair
<int32
, GURL
>& blocked_popup
: blocked_popups
) {
552 std::string
title(blocked_popup
.second
.spec());
553 // The pop-up may not have a valid URL.
555 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
556 ListItem
popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
557 IDR_DEFAULT_FAVICON
),
558 title
, true, blocked_popup
.first
);
559 add_list_item(popup_item
);
564 void ContentSettingPopupBubbleModel::OnListItemClicked(int index
) {
565 if (web_contents()) {
566 PopupBlockerTabHelper::FromWebContents(web_contents())
567 ->ShowBlockedPopup(item_id_from_item_index(index
));
571 // The model of the content settings bubble for media settings.
572 class ContentSettingMediaStreamBubbleModel
573 : public ContentSettingTitleAndLinkModel
{
575 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
576 WebContents
* web_contents
,
579 ~ContentSettingMediaStreamBubbleModel() override
;
581 void OnManageLinkClicked() override
;
584 // Helper functions to check if this bubble was invoked for microphone,
585 // camera, or both devices.
586 bool MicrophoneAccessed() const;
587 bool CameraAccessed() const;
590 // Sets the data for the radio buttons of the bubble.
591 void SetRadioGroup();
592 // Sets the data for the media menus of the bubble.
593 void SetMediaMenus();
594 // Set the settings management link.
595 void SetManageLink();
596 void SetCustomLink();
597 // Updates the camera and microphone setting with the passed |setting|.
598 void UpdateSettings(ContentSetting setting
);
599 // Updates the camera and microphone default device with the passed |type|
601 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
602 const std::string
& device
);
604 // ContentSettingBubbleModel implementation.
605 void OnRadioClicked(int radio_index
) override
;
606 void OnMediaMenuClicked(content::MediaStreamType type
,
607 const std::string
& selected_device
) override
;
609 // The index of the selected radio item.
611 // The content settings that are associated with the individual radio
613 ContentSetting radio_item_setting_
[2];
614 // The state of the microphone and camera access.
615 TabSpecificContentSettings::MicrophoneCameraState state_
;
618 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
620 WebContents
* web_contents
,
622 : ContentSettingTitleAndLinkModel(
623 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
625 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
626 // TODO(msramek): Every bubble is tied to a particular content setting.
627 // The media bubble has three states - mic only, camera only, and both.
628 // However, it is always tied to the deprecated MEDIASTREAM setting. Refactor
629 // this so that it refers to the MIC setting for microphone and CAMERA
630 // setting for camera to reduce the duplication of code in practically every
631 // method. Furthermore, it should be possible not to tie the bubble to any
632 // particular content setting type, as we still need the bubble for both
633 // camera and microphone, but should not use the deprecated MEDIASTREAM
637 // Initialize the content settings associated with the individual radio
639 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
640 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
642 TabSpecificContentSettings
* content_settings
=
643 TabSpecificContentSettings::FromWebContents(web_contents
);
644 state_
= content_settings
->GetMicrophoneCameraState();
645 DCHECK(CameraAccessed() || MicrophoneAccessed());
654 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
655 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
656 // media stream bubble is open. This resets the web contents to NULL.
660 for (const std::pair
<content::MediaStreamType
, MediaMenu
>& media_menu
:
661 bubble_content().media_menus
) {
662 if (media_menu
.second
.selected_device
.id
!=
663 media_menu
.second
.default_device
.id
) {
664 UpdateDefaultDeviceForType(media_menu
.first
,
665 media_menu
.second
.selected_device
.id
);
669 // Update the media settings if the radio button selection was changed.
670 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
671 UpdateSettings(radio_item_setting_
[selected_item_
]);
675 bool ContentSettingMediaStreamBubbleModel::MicrophoneAccessed() const {
676 return (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
679 bool ContentSettingMediaStreamBubbleModel::CameraAccessed() const {
680 return (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
683 void ContentSettingMediaStreamBubbleModel::OnManageLinkClicked() {
687 if (MicrophoneAccessed()) {
688 delegate()->ShowContentSettingsPage(CameraAccessed()
689 ? CONTENT_SETTINGS_TYPE_MEDIASTREAM
690 : CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
);
692 delegate()->ShowContentSettingsPage(
693 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
);
697 void ContentSettingMediaStreamBubbleModel::SetTitle() {
698 DCHECK(CameraAccessed() || MicrophoneAccessed());
700 if (state_
& TabSpecificContentSettings::MICROPHONE_BLOCKED
) {
701 title_id
= (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) ?
702 IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
703 } else if (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) {
704 title_id
= IDS_CAMERA_BLOCKED
;
705 } else if (MicrophoneAccessed()) {
706 title_id
= CameraAccessed() ? IDS_MICROPHONE_CAMERA_ALLOWED
707 : IDS_MICROPHONE_ACCESSED
;
708 } else if (CameraAccessed()) {
709 title_id
= IDS_CAMERA_ACCESSED
;
711 set_title(l10n_util::GetStringUTF8(title_id
));
714 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
715 TabSpecificContentSettings
* content_settings
=
716 TabSpecificContentSettings::FromWebContents(web_contents());
717 GURL url
= content_settings
->media_stream_access_origin();
718 RadioGroup radio_group
;
719 radio_group
.url
= url
;
721 base::string16 display_host_utf16
=
722 url_formatter::FormatUrlForSecurityDisplay(
723 url
, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
));
724 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
725 if (display_host
.empty())
726 display_host
= url
.spec();
728 DCHECK(CameraAccessed() || MicrophoneAccessed());
729 int radio_allow_label_id
= 0;
730 int radio_block_label_id
= 0;
731 if (state_
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
732 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
733 if (content::IsOriginSecure(url
)) {
734 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
735 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
736 if (MicrophoneAccessed())
737 radio_allow_label_id
= CameraAccessed() ?
738 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
:
739 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
741 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
742 if (MicrophoneAccessed())
743 radio_allow_label_id
= CameraAccessed() ?
744 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
:
745 IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
747 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
748 if (MicrophoneAccessed())
749 radio_block_label_id
= CameraAccessed() ?
750 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
:
751 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
753 if (MicrophoneAccessed() && CameraAccessed()) {
754 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
755 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
756 } else if (MicrophoneAccessed()) {
757 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
758 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
760 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
761 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
765 (MicrophoneAccessed() && content_settings
->IsContentBlocked(
766 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
)) ||
767 (CameraAccessed() && content_settings
->IsContentBlocked(
768 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
)) ? 1 : 0;
770 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
771 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
772 std::string radio_block_label
=
773 l10n_util::GetStringUTF8(radio_block_label_id
);
775 radio_group
.default_item
= selected_item_
;
776 radio_group
.radio_items
.push_back(radio_allow_label
);
777 radio_group
.radio_items
.push_back(radio_block_label
);
779 set_radio_group(radio_group
);
780 set_radio_group_enabled(true);
783 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
784 ContentSetting setting
) {
786 HostContentSettingsMap
* content_settings
=
787 profile()->GetHostContentSettingsMap();
788 TabSpecificContentSettings
* tab_content_settings
=
789 TabSpecificContentSettings::FromWebContents(web_contents());
790 // The same patterns must be used as in other places (e.g. the infobar) in
791 // order to override the existing rule. Otherwise a new rule is created.
792 // TODO(markusheintz): Extract to a helper so that there is only a single
794 ContentSettingsPattern primary_pattern
=
795 ContentSettingsPattern::FromURLNoWildcard(
796 tab_content_settings
->media_stream_access_origin());
797 ContentSettingsPattern secondary_pattern
=
798 ContentSettingsPattern::Wildcard();
799 if (MicrophoneAccessed()) {
800 content_settings
->SetContentSetting(
801 primary_pattern
, secondary_pattern
,
802 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
804 if (CameraAccessed()) {
805 content_settings
->SetContentSetting(
806 primary_pattern
, secondary_pattern
,
807 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string(), setting
);
812 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
813 content::MediaStreamType type
,
814 const std::string
& device
) {
815 PrefService
* prefs
= profile()->GetPrefs();
816 if (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
817 prefs
->SetString(prefs::kDefaultAudioCaptureDevice
, device
);
819 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE
, type
);
820 prefs
->SetString(prefs::kDefaultVideoCaptureDevice
, device
);
824 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
825 TabSpecificContentSettings
* content_settings
=
826 TabSpecificContentSettings::FromWebContents(web_contents());
827 const std::string
& requested_microphone
=
828 content_settings
->media_stream_requested_audio_device();
829 const std::string
& requested_camera
=
830 content_settings
->media_stream_requested_video_device();
832 // Add microphone menu.
833 PrefService
* prefs
= profile()->GetPrefs();
834 MediaCaptureDevicesDispatcher
* dispatcher
=
835 MediaCaptureDevicesDispatcher::GetInstance();
836 const content::MediaStreamDevices
& microphones
=
837 dispatcher
->GetAudioCaptureDevices();
839 if (MicrophoneAccessed()) {
841 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
842 if (!microphones
.empty()) {
843 std::string preferred_mic
;
844 if (requested_microphone
.empty()) {
845 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
846 mic_menu
.disabled
= false;
848 // Set the |disabled| to true in order to disable the device selection
849 // menu on the media settings bubble. This must be done if the website
850 // manages the microphone devices itself.
851 preferred_mic
= requested_microphone
;
852 mic_menu
.disabled
= true;
855 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
856 mic_menu
.selected_device
= mic_menu
.default_device
;
858 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
861 if (CameraAccessed()) {
862 const content::MediaStreamDevices
& cameras
=
863 dispatcher
->GetVideoCaptureDevices();
864 MediaMenu camera_menu
;
866 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
867 if (!cameras
.empty()) {
868 std::string preferred_camera
;
869 if (requested_camera
.empty()) {
870 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
871 camera_menu
.disabled
= false;
873 // Disable the menu since the website is managing the camera devices
875 preferred_camera
= requested_camera
;
876 camera_menu
.disabled
= true;
879 camera_menu
.default_device
=
880 GetMediaDeviceById(preferred_camera
, cameras
);
881 camera_menu
.selected_device
= camera_menu
.default_device
;
883 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
887 void ContentSettingMediaStreamBubbleModel::SetManageLink() {
888 // By default, the manage link refers to both media types. We only need
889 // to change the link text if only one media type was accessed.
890 if (CameraAccessed() && MicrophoneAccessed())
893 set_manage_link(l10n_util::GetStringUTF8(MicrophoneAccessed()
894 ? IDS_MEDIASTREAM_MICROPHONE_BUBBLE_MANAGE_LINK
895 : IDS_MEDIASTREAM_CAMERA_BUBBLE_MANAGE_LINK
));
898 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
899 TabSpecificContentSettings
* content_settings
=
900 TabSpecificContentSettings::FromWebContents(web_contents());
901 if (content_settings
->IsMicrophoneCameraStateChanged()) {
902 set_custom_link(l10n_util::GetStringUTF8(
903 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE
));
907 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
908 selected_item_
= radio_index
;
911 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
912 content::MediaStreamType type
,
913 const std::string
& selected_device_id
) {
914 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
915 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
916 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
917 MediaCaptureDevicesDispatcher
* dispatcher
=
918 MediaCaptureDevicesDispatcher::GetInstance();
919 const content::MediaStreamDevices
& devices
=
920 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
921 dispatcher
->GetAudioCaptureDevices() :
922 dispatcher
->GetVideoCaptureDevices();
923 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
926 class ContentSettingDomainListBubbleModel
927 : public ContentSettingTitleAndLinkModel
{
929 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
930 WebContents
* web_contents
,
932 ContentSettingsType content_type
);
933 ~ContentSettingDomainListBubbleModel() override
{}
936 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
937 void SetDomainsAndCustomLink();
938 void OnCustomLinkClicked() override
;
941 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
943 WebContents
* web_contents
,
945 ContentSettingsType content_type
)
946 : ContentSettingTitleAndLinkModel(
947 delegate
, web_contents
, profile
, content_type
) {
948 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
949 "SetDomains currently only supports geolocation content type";
950 SetDomainsAndCustomLink();
953 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
954 const std::set
<std::string
>& hosts
, int title_id
) {
955 if (!hosts
.empty()) {
956 DomainList domain_list
;
957 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
958 domain_list
.hosts
= hosts
;
959 add_domain_list(domain_list
);
963 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
964 TabSpecificContentSettings
* content_settings
=
965 TabSpecificContentSettings::FromWebContents(web_contents());
966 const ContentSettingsUsagesState
& usages
=
967 content_settings
->geolocation_usages_state();
968 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
969 unsigned int tab_state_flags
= 0;
970 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
971 // Divide the tab's current geolocation users into sets according to their
973 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
974 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
976 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
977 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
979 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
980 set_custom_link(l10n_util::GetStringUTF8(
981 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
982 set_custom_link_enabled(true);
983 } else if (tab_state_flags
&
984 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
985 set_custom_link(l10n_util::GetStringUTF8(
986 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
990 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
993 // Reset this embedder's entry to default for each of the requesting
994 // origins currently on the page.
995 const GURL
& embedder_url
= web_contents()->GetURL();
996 TabSpecificContentSettings
* content_settings
=
997 TabSpecificContentSettings::FromWebContents(web_contents());
998 const ContentSettingsUsagesState::StateMap
& state_map
=
999 content_settings
->geolocation_usages_state().state_map();
1000 HostContentSettingsMap
* settings_map
=
1001 profile()->GetHostContentSettingsMap();
1003 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
1004 settings_map
->SetContentSetting(
1005 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
1006 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1007 CONTENT_SETTINGS_TYPE_GEOLOCATION
, std::string(),
1008 CONTENT_SETTING_DEFAULT
);
1012 class ContentSettingMixedScriptBubbleModel
1013 : public ContentSettingTitleLinkAndCustomModel
{
1015 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
1016 WebContents
* web_contents
,
1019 ~ContentSettingMixedScriptBubbleModel() override
{}
1022 void OnCustomLinkClicked() override
;
1025 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
1027 WebContents
* web_contents
,
1029 : ContentSettingTitleLinkAndCustomModel(delegate
,
1032 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1033 content_settings::RecordMixedScriptAction(
1034 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE
);
1035 set_custom_link_enabled(true);
1038 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
1039 DCHECK(web_contents());
1040 web_contents()->SendToAllFrames(
1041 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE
, true));
1042 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1043 web_contents()->GetMainFrame()->GetRoutingID()));
1045 content_settings::RecordMixedScriptAction(
1046 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
);
1047 content_settings::RecordMixedScriptActionWithRAPPOR(
1048 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
,
1049 web_contents()->GetLastCommittedURL());
1052 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1054 WebContents
* web_contents
,
1056 ProtocolHandlerRegistry
* registry
)
1057 : ContentSettingTitleAndLinkModel(delegate
,
1060 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
),
1062 registry_(registry
),
1063 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1064 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1065 TabSpecificContentSettings
* content_settings
=
1066 TabSpecificContentSettings::FromWebContents(web_contents
);
1067 pending_handler_
= content_settings
->pending_protocol_handler();
1068 previous_handler_
= content_settings
->previous_protocol_handler();
1070 base::string16 protocol
;
1071 if (pending_handler_
.protocol() == "mailto") {
1072 protocol
= l10n_util::GetStringUTF16(
1073 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1074 } else if (pending_handler_
.protocol() == "webcal") {
1075 protocol
= l10n_util::GetStringUTF16(
1076 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1078 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1081 // Note that we ignore the |title| parameter.
1082 if (previous_handler_
.IsEmpty()) {
1083 set_title(l10n_util::GetStringFUTF8(
1084 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1085 base::UTF8ToUTF16(pending_handler_
.url().host()),
1088 set_title(l10n_util::GetStringFUTF8(
1089 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1090 base::UTF8ToUTF16(pending_handler_
.url().host()),
1092 base::UTF8ToUTF16(previous_handler_
.url().host())));
1095 std::string radio_allow_label
=
1096 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
);
1097 std::string radio_deny_label
=
1098 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY
);
1099 std::string radio_ignore_label
=
1100 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE
);
1102 GURL url
= web_contents
->GetURL();
1103 RadioGroup radio_group
;
1104 radio_group
.url
= url
;
1106 radio_group
.radio_items
.push_back(radio_allow_label
);
1107 radio_group
.radio_items
.push_back(radio_deny_label
);
1108 radio_group
.radio_items
.push_back(radio_ignore_label
);
1109 ContentSetting setting
=
1110 content_settings
->pending_protocol_handler_setting();
1111 if (setting
== CONTENT_SETTING_ALLOW
)
1112 radio_group
.default_item
= RPH_ALLOW
;
1113 else if (setting
== CONTENT_SETTING_BLOCK
)
1114 radio_group
.default_item
= RPH_BLOCK
;
1116 radio_group
.default_item
= RPH_IGNORE
;
1118 selected_item_
= radio_group
.default_item
;
1119 set_radio_group_enabled(true);
1120 set_radio_group(radio_group
);
1123 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index
) {
1124 if (selected_item_
== radio_index
)
1127 selected_item_
= radio_index
;
1129 if (radio_index
== RPH_ALLOW
)
1130 RegisterProtocolHandler();
1131 else if (radio_index
== RPH_BLOCK
)
1132 UnregisterProtocolHandler();
1133 else if (radio_index
== RPH_IGNORE
)
1134 IgnoreProtocolHandler();
1139 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1140 // The user has one chance to deal with the RPH content setting UI,
1141 // then we remove it.
1142 TabSpecificContentSettings::FromWebContents(web_contents())->
1143 ClearPendingProtocolHandler();
1144 content::NotificationService::current()->Notify(
1145 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
1146 content::Source
<WebContents
>(web_contents()),
1147 content::NotificationService::NoDetails());
1150 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1151 // A no-op if the handler hasn't been ignored, but needed in case the user
1152 // selects sequences like register/ignore/register.
1153 registry_
->RemoveIgnoredHandler(pending_handler_
);
1155 registry_
->OnAcceptRegisterProtocolHandler(pending_handler_
);
1156 TabSpecificContentSettings::FromWebContents(web_contents())->
1157 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW
);
1160 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1161 registry_
->OnDenyRegisterProtocolHandler(pending_handler_
);
1162 TabSpecificContentSettings::FromWebContents(web_contents())->
1163 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK
);
1164 ClearOrSetPreviousHandler();
1167 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1168 registry_
->OnIgnoreRegisterProtocolHandler(pending_handler_
);
1169 TabSpecificContentSettings::FromWebContents(web_contents())->
1170 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT
);
1171 ClearOrSetPreviousHandler();
1174 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1175 if (previous_handler_
.IsEmpty()) {
1176 registry_
->ClearDefault(pending_handler_
.protocol());
1178 registry_
->OnAcceptRegisterProtocolHandler(previous_handler_
);
1182 class ContentSettingMidiSysExBubbleModel
1183 : public ContentSettingTitleAndLinkModel
{
1185 ContentSettingMidiSysExBubbleModel(Delegate
* delegate
,
1186 WebContents
* web_contents
,
1188 ~ContentSettingMidiSysExBubbleModel() override
{}
1191 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1192 void SetDomainsAndCustomLink();
1193 void OnCustomLinkClicked() override
;
1196 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1198 WebContents
* web_contents
,
1200 : ContentSettingTitleAndLinkModel(delegate
,
1203 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1204 SetDomainsAndCustomLink();
1207 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1208 const std::set
<std::string
>& hosts
, int title_id
) {
1209 if (!hosts
.empty()) {
1210 DomainList domain_list
;
1211 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
1212 domain_list
.hosts
= hosts
;
1213 add_domain_list(domain_list
);
1217 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1218 TabSpecificContentSettings
* content_settings
=
1219 TabSpecificContentSettings::FromWebContents(web_contents());
1220 const ContentSettingsUsagesState
& usages_state
=
1221 content_settings
->midi_usages_state();
1222 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
1223 unsigned int tab_state_flags
= 0;
1224 usages_state
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
1225 // Divide the tab's current MIDI sysex users into sets according to their
1226 // permission state.
1227 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
1228 IDS_MIDI_SYSEX_BUBBLE_ALLOWED
);
1230 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
1231 IDS_MIDI_SYSEX_BUBBLE_DENIED
);
1233 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1234 set_custom_link(l10n_util::GetStringUTF8(
1235 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK
));
1236 set_custom_link_enabled(true);
1237 } else if (tab_state_flags
&
1238 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1239 set_custom_link(l10n_util::GetStringUTF8(
1240 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1244 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1245 if (!web_contents())
1247 // Reset this embedder's entry to default for each of the requesting
1248 // origins currently on the page.
1249 const GURL
& embedder_url
= web_contents()->GetURL();
1250 TabSpecificContentSettings
* content_settings
=
1251 TabSpecificContentSettings::FromWebContents(web_contents());
1252 const ContentSettingsUsagesState::StateMap
& state_map
=
1253 content_settings
->midi_usages_state().state_map();
1254 HostContentSettingsMap
* settings_map
=
1255 profile()->GetHostContentSettingsMap();
1257 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
1258 settings_map
->SetContentSetting(
1259 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
1260 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1261 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, std::string(),
1262 CONTENT_SETTING_DEFAULT
);
1267 ContentSettingBubbleModel
*
1268 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1270 WebContents
* web_contents
,
1272 ContentSettingsType content_type
) {
1273 if (content_type
== CONTENT_SETTINGS_TYPE_COOKIES
) {
1274 return new ContentSettingCookiesBubbleModel(delegate
, web_contents
,
1277 if (content_type
== CONTENT_SETTINGS_TYPE_POPUPS
) {
1278 return new ContentSettingPopupBubbleModel(delegate
, web_contents
, profile
);
1280 if (content_type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
1281 return new ContentSettingDomainListBubbleModel(delegate
, web_contents
,
1282 profile
, content_type
);
1284 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
1285 return new ContentSettingMediaStreamBubbleModel(delegate
, web_contents
,
1288 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
1289 return new ContentSettingPluginBubbleModel(delegate
, web_contents
, profile
);
1291 if (content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1292 return new ContentSettingMixedScriptBubbleModel(delegate
, web_contents
,
1295 if (content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
1296 ProtocolHandlerRegistry
* registry
=
1297 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile
);
1298 return new ContentSettingRPHBubbleModel(delegate
, web_contents
, profile
,
1301 if (content_type
== CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1302 return new ContentSettingMidiSysExBubbleModel(delegate
, web_contents
,
1305 return new ContentSettingSingleRadioGroup(delegate
, web_contents
, profile
,
1309 ContentSettingBubbleModel::ContentSettingBubbleModel(
1310 WebContents
* web_contents
,
1312 ContentSettingsType content_type
)
1313 : web_contents_(web_contents
),
1315 content_type_(content_type
),
1316 setting_is_managed_(false) {
1317 registrar_
.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1318 content::Source
<WebContents
>(web_contents
));
1319 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
1320 content::Source
<Profile
>(profile_
));
1323 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1326 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1328 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1330 ContentSettingBubbleModel::DomainList::DomainList() {}
1332 ContentSettingBubbleModel::DomainList::~DomainList() {}
1334 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1336 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1338 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1339 : radio_group_enabled(false),
1340 custom_link_enabled(false) {
1343 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1345 void ContentSettingBubbleModel::Observe(
1347 const content::NotificationSource
& source
,
1348 const content::NotificationDetails
& details
) {
1349 if (type
== content::NOTIFICATION_WEB_CONTENTS_DESTROYED
) {
1350 DCHECK_EQ(web_contents_
,
1351 content::Source
<WebContents
>(source
).ptr());
1352 web_contents_
= NULL
;
1354 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
1355 DCHECK_EQ(profile_
, content::Source
<Profile
>(source
).ptr());