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.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/favicon/favicon_tab_helper.h"
17 #include "chrome/browser/infobars/infobar_service.h"
18 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
19 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
22 #include "chrome/browser/ui/browser_navigator.h"
23 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
24 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/render_messages.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "components/content_settings/core/browser/content_settings_utils.h"
30 #include "components/content_settings/core/common/content_settings.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/render_frame_host.h"
33 #include "content/public/browser/render_process_host.h"
34 #include "content/public/browser/render_view_host.h"
35 #include "content/public/browser/user_metrics.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_delegate.h"
38 #include "grit/components_strings.h"
39 #include "grit/theme_resources.h"
40 #include "net/base/net_util.h"
41 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/resource/resource_bundle.h"
43 #include "ui/resources/grit/ui_resources.h"
45 using base::UserMetricsAction
;
46 using content::WebContents
;
47 using content_settings::SettingInfo
;
48 using content_settings::SettingSource
;
49 using content_settings::SETTING_SOURCE_USER
;
50 using content_settings::SETTING_SOURCE_NONE
;
54 const int kAllowButtonIndex
= 0;
56 // These states must match the order of appearance of the radio buttons
57 // in the XIB file for the Mac port.
64 struct ContentSettingsTypeIdEntry
{
65 ContentSettingsType type
;
69 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
71 ContentSettingsType type
) {
72 for (size_t i
= 0; i
< num_entries
; ++i
) {
73 if (entries
[i
].type
== type
)
79 const content::MediaStreamDevice
& GetMediaDeviceById(
80 const std::string
& device_id
,
81 const content::MediaStreamDevices
& devices
) {
82 DCHECK(!devices
.empty());
83 for (const content::MediaStreamDevice
& device
: devices
) {
84 if (device
.id
== device_id
)
88 // A device with the |device_id| was not found. It is likely that the device
89 // has been unplugged from the OS. Return the first device as the default
91 return *devices
.begin();
96 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
98 WebContents
* web_contents
,
100 ContentSettingsType content_type
)
101 : ContentSettingBubbleModel(web_contents
, profile
, content_type
),
102 delegate_(delegate
) {
103 // Notifications do not have a bubble.
104 DCHECK_NE(content_type
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
110 void ContentSettingTitleAndLinkModel::SetTitle() {
111 TabSpecificContentSettings
* content_settings
= NULL
;
112 if (web_contents()) {
114 TabSpecificContentSettings::FromWebContents(web_contents());
117 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
118 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
119 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
120 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
121 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_TITLE
},
122 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
123 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
124 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
125 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
126 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
127 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
129 // Fields as for kBlockedTitleIDs, above.
130 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
131 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
132 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
133 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
135 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
136 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
137 if (content_settings
&& content_settings
->IsContentAllowed(content_type()) &&
138 !content_settings
->IsContentBlocked(content_type())) {
139 title_ids
= kAccessedTitleIDs
;
140 num_title_ids
= arraysize(kAccessedTitleIDs
);
143 GetIdForContentType(title_ids
, num_title_ids
, content_type());
145 set_title(l10n_util::GetStringUTF8(title_id
));
148 void ContentSettingTitleAndLinkModel::SetManageLink() {
149 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
150 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
151 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
152 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
153 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
154 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
155 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
156 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
157 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
158 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
159 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
160 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
161 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
163 set_manage_link(l10n_util::GetStringUTF8(
164 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
167 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
169 delegate_
->ShowContentSettingsPage(content_type());
172 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
173 static const ContentSettingsTypeIdEntry kLearnMoreIDs
[] = {
174 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_LEARN_MORE
},
177 GetIdForContentType(kLearnMoreIDs
, arraysize(kLearnMoreIDs
),
180 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id
));
183 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
185 delegate_
->ShowLearnMorePage(content_type());
188 class ContentSettingTitleLinkAndCustomModel
189 : public ContentSettingTitleAndLinkModel
{
191 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
192 WebContents
* web_contents
,
194 ContentSettingsType content_type
);
195 ~ContentSettingTitleLinkAndCustomModel() override
{}
198 void SetCustomLink();
199 void OnCustomLinkClicked() override
{}
202 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
204 WebContents
* web_contents
,
206 ContentSettingsType content_type
)
207 : ContentSettingTitleAndLinkModel(
208 delegate
, web_contents
, profile
, content_type
) {
212 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
213 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
214 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
215 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
216 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
219 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
221 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
224 class ContentSettingSingleRadioGroup
225 : public ContentSettingTitleLinkAndCustomModel
{
227 ContentSettingSingleRadioGroup(Delegate
* delegate
,
228 WebContents
* web_contents
,
230 ContentSettingsType content_type
);
231 ~ContentSettingSingleRadioGroup() override
;
234 bool settings_changed() const;
235 int selected_item() const { return selected_item_
; }
238 void SetRadioGroup();
239 void AddException(ContentSetting setting
);
240 void OnRadioClicked(int radio_index
) override
;
242 ContentSetting block_setting_
;
246 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
248 WebContents
* web_contents
,
250 ContentSettingsType content_type
)
251 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
253 block_setting_(CONTENT_SETTING_BLOCK
),
258 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
259 if (settings_changed()) {
260 ContentSetting setting
=
261 selected_item_
== kAllowButtonIndex
?
262 CONTENT_SETTING_ALLOW
:
264 AddException(setting
);
268 bool ContentSettingSingleRadioGroup::settings_changed() const {
269 return selected_item_
!= bubble_content().radio_group
.default_item
;
272 // Initialize the radio group by setting the appropriate labels for the
273 // content type and setting the default value based on the content setting.
274 void ContentSettingSingleRadioGroup::SetRadioGroup() {
275 GURL url
= web_contents()->GetURL();
276 base::string16 display_host
;
277 net::AppendFormattedHost(
279 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
282 if (display_host
.empty())
283 display_host
= base::ASCIIToUTF16(url
.spec());
285 TabSpecificContentSettings
* content_settings
=
286 TabSpecificContentSettings::FromWebContents(web_contents());
288 !content_settings
->IsContentBlocked(content_type());
290 content_settings
->IsContentAllowed(content_type()));
292 RadioGroup radio_group
;
293 radio_group
.url
= url
;
295 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
296 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
297 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
298 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
299 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
300 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
301 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
302 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
304 // Fields as for kBlockedAllowIDs, above.
305 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
306 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
307 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
308 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
309 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
312 std::string radio_allow_label
;
314 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
315 arraysize(kAllowedAllowIDs
),
317 radio_allow_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
318 l10n_util::GetStringFUTF8(resource_id
, display_host
) :
319 l10n_util::GetStringUTF8(resource_id
);
321 radio_allow_label
= l10n_util::GetStringFUTF8(
322 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
327 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
328 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
329 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
330 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
331 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
332 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
333 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
334 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
336 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
337 // TODO(bauerb): The string should say "block".
338 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
339 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
340 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
343 std::string radio_block_label
;
345 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
346 arraysize(kAllowedBlockIDs
),
348 radio_block_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
349 l10n_util::GetStringUTF8(resource_id
) :
350 l10n_util::GetStringFUTF8(resource_id
, display_host
);
352 radio_block_label
= l10n_util::GetStringUTF8(
353 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
357 radio_group
.radio_items
.push_back(radio_allow_label
);
358 radio_group
.radio_items
.push_back(radio_block_label
);
359 ContentSetting setting
;
360 SettingSource setting_source
= SETTING_SOURCE_NONE
;
361 bool setting_is_wildcard
= false;
363 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
364 CookieSettings
* cookie_settings
=
365 CookieSettings::Factory::GetForProfile(profile()).get();
366 setting
= cookie_settings
->GetCookieSetting(
367 url
, url
, true, &setting_source
);
370 HostContentSettingsMap
* map
= profile()->GetHostContentSettingsMap();
371 scoped_ptr
<base::Value
> value
=
372 map
->GetWebsiteSetting(url
, url
, content_type(), std::string(), &info
);
373 setting
= content_settings::ValueToContentSetting(value
.get());
374 setting_source
= info
.source
;
375 setting_is_wildcard
=
376 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
377 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
380 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
381 setting
== CONTENT_SETTING_ALLOW
&&
382 setting_is_wildcard
) {
383 // In the corner case of unrecognized plugins (which are now blocked by
384 // default) we indicate the blocked state in the UI and allow the user to
386 radio_group
.default_item
= 1;
387 } else if (setting
== CONTENT_SETTING_ALLOW
) {
388 radio_group
.default_item
= kAllowButtonIndex
;
389 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
391 radio_group
.default_item
= 1;
392 block_setting_
= setting
;
395 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
);
396 if (setting_source
!= SETTING_SOURCE_USER
) {
397 set_radio_group_enabled(false);
399 set_radio_group_enabled(true);
401 selected_item_
= radio_group
.default_item
;
402 set_radio_group(radio_group
);
405 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
407 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
408 bubble_content().radio_group
.url
,
409 bubble_content().radio_group
.url
,
415 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
416 selected_item_
= radio_index
;
419 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
421 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
422 WebContents
* web_contents
,
425 ~ContentSettingCookiesBubbleModel() override
;
428 void OnCustomLinkClicked() override
;
431 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
433 WebContents
* web_contents
,
435 : ContentSettingSingleRadioGroup(delegate
,
438 CONTENT_SETTINGS_TYPE_COOKIES
) {
439 set_custom_link_enabled(true);
442 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
443 // On some plattforms e.g. MacOS X it is possible to close a tab while the
444 // cookies settings bubble is open. This resets the web contents to NULL.
445 if (settings_changed() && web_contents()) {
446 CollectedCookiesInfoBarDelegate::Create(
447 InfoBarService::FromWebContents(web_contents()));
451 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
454 content::NotificationService::current()->Notify(
455 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
456 content::Source
<TabSpecificContentSettings
>(
457 TabSpecificContentSettings::FromWebContents(web_contents())),
458 content::NotificationService::NoDetails());
459 delegate()->ShowCollectedCookiesDialog(web_contents());
462 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
464 ContentSettingPluginBubbleModel(Delegate
* delegate
,
465 WebContents
* web_contents
,
468 ~ContentSettingPluginBubbleModel() override
;
471 void OnCustomLinkClicked() override
;
474 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
476 WebContents
* web_contents
,
478 : ContentSettingSingleRadioGroup(delegate
,
481 CONTENT_SETTINGS_TYPE_PLUGINS
) {
482 // Disable the "Run all plugins this time" link if the setting is managed and
483 // can't be controlled by the user or if the user already clicked on the link
484 // and ran all plugins.
485 set_custom_link_enabled(!setting_is_managed() &&
487 TabSpecificContentSettings::FromWebContents(
488 web_contents
)->load_plugins_link_enabled());
489 // Build blocked plugin list.
491 TabSpecificContentSettings
* content_settings
=
492 TabSpecificContentSettings::FromWebContents(web_contents
);
494 const std::vector
<base::string16
>& blocked_plugins
=
495 content_settings
->blocked_plugin_names();
496 for (const base::string16
& blocked_plugin
: blocked_plugins
) {
497 ListItem
plugin_item(
498 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
499 IDR_BLOCKED_PLUGINS
),
500 base::UTF16ToUTF8(blocked_plugin
), false, 0);
501 add_list_item(plugin_item
);
506 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
507 if (settings_changed()) {
508 // If the user elected to allow all plugins then run plugins at this time.
509 if (selected_item() == kAllowButtonIndex
)
510 OnCustomLinkClicked();
514 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
515 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
516 // Web contents can be NULL if the tab was closed while the plugins
517 // settings bubble is visible.
520 #if defined(ENABLE_PLUGINS)
521 // TODO(bauerb): We should send the identifiers of blocked plugins here.
522 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
523 web_contents(), true, std::string());
525 set_custom_link_enabled(false);
526 TabSpecificContentSettings::FromWebContents(web_contents())->
527 set_load_plugins_link_enabled(false);
530 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
532 ContentSettingPopupBubbleModel(Delegate
* delegate
,
533 WebContents
* web_contents
,
535 ~ContentSettingPopupBubbleModel() override
{}
538 void OnListItemClicked(int index
) override
;
540 int32
item_id_from_item_index(int index
) const {
541 return bubble_content().list_items
[index
].item_id
;
545 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
547 WebContents
* web_contents
,
549 : ContentSettingSingleRadioGroup(delegate
,
552 CONTENT_SETTINGS_TYPE_POPUPS
) {
554 // Build blocked popup list.
555 std::map
<int32
, GURL
> blocked_popups
=
556 PopupBlockerTabHelper::FromWebContents(web_contents
)
557 ->GetBlockedPopupRequests();
558 for (const std::pair
<int32
, GURL
>& blocked_popup
: blocked_popups
) {
559 std::string
title(blocked_popup
.second
.spec());
560 // The popup may not have a valid URL.
562 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
563 ListItem
popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
564 IDR_DEFAULT_FAVICON
),
565 title
, true, blocked_popup
.first
);
566 add_list_item(popup_item
);
571 void ContentSettingPopupBubbleModel::OnListItemClicked(int index
) {
572 if (web_contents()) {
573 PopupBlockerTabHelper::FromWebContents(web_contents())
574 ->ShowBlockedPopup(item_id_from_item_index(index
));
578 // The model of the content settings bubble for media settings.
579 class ContentSettingMediaStreamBubbleModel
580 : public ContentSettingTitleAndLinkModel
{
582 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
583 WebContents
* web_contents
,
586 ~ContentSettingMediaStreamBubbleModel() override
;
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 void SetCustomLink();
595 // Updates the camera and microphone setting with the passed |setting|.
596 void UpdateSettings(ContentSetting setting
);
597 // Updates the camera and microphone default device with the passed |type|
599 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
600 const std::string
& device
);
602 // ContentSettingBubbleModel implementation.
603 void OnRadioClicked(int radio_index
) override
;
604 void OnMediaMenuClicked(content::MediaStreamType type
,
605 const std::string
& selected_device
) override
;
607 // The index of the selected radio item.
609 // The content settings that are associated with the individual radio
611 ContentSetting radio_item_setting_
[2];
612 // The state of the microphone and camera access.
613 TabSpecificContentSettings::MicrophoneCameraState state_
;
616 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
618 WebContents
* web_contents
,
620 : ContentSettingTitleAndLinkModel(
621 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
623 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
625 // Initialize the content settings associated with the individual radio
627 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
628 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
630 TabSpecificContentSettings
* content_settings
=
631 TabSpecificContentSettings::FromWebContents(web_contents
);
632 state_
= content_settings
->GetMicrophoneCameraState();
633 DCHECK(state_
& (TabSpecificContentSettings::MICROPHONE_ACCESSED
|
634 TabSpecificContentSettings::CAMERA_ACCESSED
));
642 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
643 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
644 // media stream bubble is open. This resets the web contents to NULL.
648 for (const std::pair
<content::MediaStreamType
, MediaMenu
>& media_menu
:
649 bubble_content().media_menus
) {
650 if (media_menu
.second
.selected_device
.id
!=
651 media_menu
.second
.default_device
.id
) {
652 UpdateDefaultDeviceForType(media_menu
.first
,
653 media_menu
.second
.selected_device
.id
);
657 // Update the media settings if the radio button selection was changed.
658 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
659 UpdateSettings(radio_item_setting_
[selected_item_
]);
663 void ContentSettingMediaStreamBubbleModel::SetTitle() {
664 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
, state_
);
666 if (state_
& TabSpecificContentSettings::MICROPHONE_BLOCKED
) {
667 title_id
= (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) ?
668 IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
669 } else if (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) {
670 title_id
= IDS_CAMERA_BLOCKED
;
671 } else if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
672 title_id
= (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) ?
673 IDS_MICROPHONE_CAMERA_ALLOWED
: IDS_MICROPHONE_ACCESSED
;
674 } else if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
675 title_id
= IDS_CAMERA_ACCESSED
;
677 set_title(l10n_util::GetStringUTF8(title_id
));
680 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
681 TabSpecificContentSettings
* content_settings
=
682 TabSpecificContentSettings::FromWebContents(web_contents());
683 GURL url
= content_settings
->media_stream_access_origin();
684 RadioGroup radio_group
;
685 radio_group
.url
= url
;
687 base::string16 display_host_utf16
;
688 net::AppendFormattedHost(
690 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
691 &display_host_utf16
);
692 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
693 if (display_host
.empty())
694 display_host
= url
.spec();
696 bool is_mic
= (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
697 bool is_cam
= (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
698 DCHECK(is_mic
|| is_cam
);
699 int radio_allow_label_id
= 0;
700 int radio_block_label_id
= 0;
701 if (state_
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
702 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
703 if (url
.SchemeIsSecure()) {
704 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
705 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
707 radio_allow_label_id
= is_cam
?
708 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
:
709 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
711 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
713 radio_allow_label_id
= is_cam
?
714 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
:
715 IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
717 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
719 radio_block_label_id
= is_cam
?
720 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
:
721 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
723 if (is_mic
&& is_cam
) {
724 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
725 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
727 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
728 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
730 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
731 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
735 (is_mic
&& content_settings
->IsContentBlocked(
736 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
)) ||
737 (is_cam
&& content_settings
->IsContentBlocked(
738 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
)) ? 1 : 0;
740 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
741 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
742 std::string radio_block_label
=
743 l10n_util::GetStringUTF8(radio_block_label_id
);
745 radio_group
.default_item
= selected_item_
;
746 radio_group
.radio_items
.push_back(radio_allow_label
);
747 radio_group
.radio_items
.push_back(radio_block_label
);
749 set_radio_group(radio_group
);
750 set_radio_group_enabled(true);
753 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
754 ContentSetting setting
) {
756 HostContentSettingsMap
* content_settings
=
757 profile()->GetHostContentSettingsMap();
758 TabSpecificContentSettings
* tab_content_settings
=
759 TabSpecificContentSettings::FromWebContents(web_contents());
760 // The same patterns must be used as in other places (e.g. the infobar) in
761 // order to override the existing rule. Otherwise a new rule is created.
762 // TODO(markusheintz): Extract to a helper so that there is only a single
764 ContentSettingsPattern primary_pattern
=
765 ContentSettingsPattern::FromURLNoWildcard(
766 tab_content_settings
->media_stream_access_origin());
767 ContentSettingsPattern secondary_pattern
=
768 ContentSettingsPattern::Wildcard();
769 if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
770 content_settings
->SetContentSetting(
771 primary_pattern
, secondary_pattern
,
772 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
774 if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
775 content_settings
->SetContentSetting(
776 primary_pattern
, secondary_pattern
,
777 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string(), setting
);
782 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
783 content::MediaStreamType type
,
784 const std::string
& device
) {
785 PrefService
* prefs
= profile()->GetPrefs();
786 if (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
787 prefs
->SetString(prefs::kDefaultAudioCaptureDevice
, device
);
789 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE
, type
);
790 prefs
->SetString(prefs::kDefaultVideoCaptureDevice
, device
);
794 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
795 TabSpecificContentSettings
* content_settings
=
796 TabSpecificContentSettings::FromWebContents(web_contents());
797 const std::string
& requested_microphone
=
798 content_settings
->media_stream_requested_audio_device();
799 const std::string
& requested_camera
=
800 content_settings
->media_stream_requested_video_device();
802 // Add microphone menu.
803 PrefService
* prefs
= profile()->GetPrefs();
804 MediaCaptureDevicesDispatcher
* dispatcher
=
805 MediaCaptureDevicesDispatcher::GetInstance();
806 const content::MediaStreamDevices
& microphones
=
807 dispatcher
->GetAudioCaptureDevices();
809 if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
811 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
812 if (!microphones
.empty()) {
813 std::string preferred_mic
;
814 if (requested_microphone
.empty()) {
815 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
816 mic_menu
.disabled
= false;
818 // Set the |disabled| to true in order to disable the device selection
819 // menu on the media settings bubble. This must be done if the website
820 // manages the microphone devices itself.
821 preferred_mic
= requested_microphone
;
822 mic_menu
.disabled
= true;
825 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
826 mic_menu
.selected_device
= mic_menu
.default_device
;
828 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
831 if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
832 const content::MediaStreamDevices
& cameras
=
833 dispatcher
->GetVideoCaptureDevices();
834 MediaMenu camera_menu
;
836 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
837 if (!cameras
.empty()) {
838 std::string preferred_camera
;
839 if (requested_camera
.empty()) {
840 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
841 camera_menu
.disabled
= false;
843 // Disable the menu since the website is managing the camera devices
845 preferred_camera
= requested_camera
;
846 camera_menu
.disabled
= true;
849 camera_menu
.default_device
=
850 GetMediaDeviceById(preferred_camera
, cameras
);
851 camera_menu
.selected_device
= camera_menu
.default_device
;
853 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
857 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
858 TabSpecificContentSettings
* content_settings
=
859 TabSpecificContentSettings::FromWebContents(web_contents());
860 if (content_settings
->IsMicrophoneCameraStateChanged()) {
861 set_custom_link(l10n_util::GetStringUTF8(
862 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE
));
866 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
867 selected_item_
= radio_index
;
870 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
871 content::MediaStreamType type
,
872 const std::string
& selected_device_id
) {
873 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
874 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
875 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
876 MediaCaptureDevicesDispatcher
* dispatcher
=
877 MediaCaptureDevicesDispatcher::GetInstance();
878 const content::MediaStreamDevices
& devices
=
879 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
880 dispatcher
->GetAudioCaptureDevices() :
881 dispatcher
->GetVideoCaptureDevices();
882 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
885 class ContentSettingDomainListBubbleModel
886 : public ContentSettingTitleAndLinkModel
{
888 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
889 WebContents
* web_contents
,
891 ContentSettingsType content_type
);
892 ~ContentSettingDomainListBubbleModel() override
{}
895 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
896 void SetDomainsAndCustomLink();
897 void OnCustomLinkClicked() override
;
900 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
902 WebContents
* web_contents
,
904 ContentSettingsType content_type
)
905 : ContentSettingTitleAndLinkModel(
906 delegate
, web_contents
, profile
, content_type
) {
907 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
908 "SetDomains currently only supports geolocation content type";
909 SetDomainsAndCustomLink();
912 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
913 const std::set
<std::string
>& hosts
, int title_id
) {
914 if (!hosts
.empty()) {
915 DomainList domain_list
;
916 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
917 domain_list
.hosts
= hosts
;
918 add_domain_list(domain_list
);
922 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
923 TabSpecificContentSettings
* content_settings
=
924 TabSpecificContentSettings::FromWebContents(web_contents());
925 const ContentSettingsUsagesState
& usages
=
926 content_settings
->geolocation_usages_state();
927 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
928 unsigned int tab_state_flags
= 0;
929 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
930 // Divide the tab's current geolocation users into sets according to their
932 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
933 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
935 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
936 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
938 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
939 set_custom_link(l10n_util::GetStringUTF8(
940 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
941 set_custom_link_enabled(true);
942 } else if (tab_state_flags
&
943 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
944 set_custom_link(l10n_util::GetStringUTF8(
945 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
949 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
952 // Reset this embedder's entry to default for each of the requesting
953 // origins currently on the page.
954 const GURL
& embedder_url
= web_contents()->GetURL();
955 TabSpecificContentSettings
* content_settings
=
956 TabSpecificContentSettings::FromWebContents(web_contents());
957 const ContentSettingsUsagesState::StateMap
& state_map
=
958 content_settings
->geolocation_usages_state().state_map();
959 HostContentSettingsMap
* settings_map
=
960 profile()->GetHostContentSettingsMap();
962 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
963 settings_map
->SetContentSetting(
964 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
965 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
966 CONTENT_SETTINGS_TYPE_GEOLOCATION
, std::string(),
967 CONTENT_SETTING_DEFAULT
);
971 class ContentSettingMixedScriptBubbleModel
972 : public ContentSettingTitleLinkAndCustomModel
{
974 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
975 WebContents
* web_contents
,
978 ~ContentSettingMixedScriptBubbleModel() override
{}
981 void OnCustomLinkClicked() override
;
984 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
986 WebContents
* web_contents
,
988 : ContentSettingTitleLinkAndCustomModel(delegate
,
991 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
992 content_settings::RecordMixedScriptAction(
993 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE
);
994 set_custom_link_enabled(true);
997 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
998 content_settings::RecordMixedScriptAction(
999 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
);
1000 DCHECK(web_contents());
1001 web_contents()->SendToAllFrames(
1002 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE
, true));
1003 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1004 web_contents()->GetMainFrame()->GetRoutingID()));
1007 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1009 WebContents
* web_contents
,
1011 ProtocolHandlerRegistry
* registry
)
1012 : ContentSettingTitleAndLinkModel(delegate
,
1015 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
),
1017 registry_(registry
),
1018 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1019 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1020 TabSpecificContentSettings
* content_settings
=
1021 TabSpecificContentSettings::FromWebContents(web_contents
);
1022 pending_handler_
= content_settings
->pending_protocol_handler();
1023 previous_handler_
= content_settings
->previous_protocol_handler();
1025 base::string16 protocol
;
1026 if (pending_handler_
.protocol() == "mailto") {
1027 protocol
= l10n_util::GetStringUTF16(
1028 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1029 } else if (pending_handler_
.protocol() == "webcal") {
1030 protocol
= l10n_util::GetStringUTF16(
1031 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1033 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1036 // Note that we ignore the |title| parameter.
1037 if (previous_handler_
.IsEmpty()) {
1038 set_title(l10n_util::GetStringFUTF8(
1039 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1040 base::UTF8ToUTF16(pending_handler_
.url().host()),
1043 set_title(l10n_util::GetStringFUTF8(
1044 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1045 base::UTF8ToUTF16(pending_handler_
.url().host()),
1047 base::UTF8ToUTF16(previous_handler_
.url().host())));
1050 std::string radio_allow_label
=
1051 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
);
1052 std::string radio_deny_label
=
1053 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY
);
1054 std::string radio_ignore_label
=
1055 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE
);
1057 GURL url
= web_contents
->GetURL();
1058 RadioGroup radio_group
;
1059 radio_group
.url
= url
;
1061 radio_group
.radio_items
.push_back(radio_allow_label
);
1062 radio_group
.radio_items
.push_back(radio_deny_label
);
1063 radio_group
.radio_items
.push_back(radio_ignore_label
);
1064 ContentSetting setting
=
1065 content_settings
->pending_protocol_handler_setting();
1066 if (setting
== CONTENT_SETTING_ALLOW
)
1067 radio_group
.default_item
= RPH_ALLOW
;
1068 else if (setting
== CONTENT_SETTING_BLOCK
)
1069 radio_group
.default_item
= RPH_BLOCK
;
1071 radio_group
.default_item
= RPH_IGNORE
;
1073 selected_item_
= radio_group
.default_item
;
1074 set_radio_group_enabled(true);
1075 set_radio_group(radio_group
);
1078 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index
) {
1079 if (selected_item_
== radio_index
)
1082 selected_item_
= radio_index
;
1084 if (radio_index
== RPH_ALLOW
)
1085 RegisterProtocolHandler();
1086 else if (radio_index
== RPH_BLOCK
)
1087 UnregisterProtocolHandler();
1088 else if (radio_index
== RPH_IGNORE
)
1089 IgnoreProtocolHandler();
1094 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1095 // The user has one chance to deal with the RPH content setting UI,
1096 // then we remove it.
1097 TabSpecificContentSettings::FromWebContents(web_contents())->
1098 ClearPendingProtocolHandler();
1099 content::NotificationService::current()->Notify(
1100 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
1101 content::Source
<WebContents
>(web_contents()),
1102 content::NotificationService::NoDetails());
1105 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1106 // A no-op if the handler hasn't been ignored, but needed in case the user
1107 // selects sequences like register/ignore/register.
1108 registry_
->RemoveIgnoredHandler(pending_handler_
);
1110 registry_
->OnAcceptRegisterProtocolHandler(pending_handler_
);
1111 TabSpecificContentSettings::FromWebContents(web_contents())->
1112 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW
);
1115 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1116 registry_
->OnDenyRegisterProtocolHandler(pending_handler_
);
1117 TabSpecificContentSettings::FromWebContents(web_contents())->
1118 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK
);
1119 ClearOrSetPreviousHandler();
1122 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1123 registry_
->OnIgnoreRegisterProtocolHandler(pending_handler_
);
1124 TabSpecificContentSettings::FromWebContents(web_contents())->
1125 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT
);
1126 ClearOrSetPreviousHandler();
1129 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1130 if (previous_handler_
.IsEmpty()) {
1131 registry_
->ClearDefault(pending_handler_
.protocol());
1133 registry_
->OnAcceptRegisterProtocolHandler(previous_handler_
);
1137 class ContentSettingMidiSysExBubbleModel
1138 : public ContentSettingTitleAndLinkModel
{
1140 ContentSettingMidiSysExBubbleModel(Delegate
* delegate
,
1141 WebContents
* web_contents
,
1143 ~ContentSettingMidiSysExBubbleModel() override
{}
1146 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1147 void SetDomainsAndCustomLink();
1148 void OnCustomLinkClicked() override
;
1151 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1153 WebContents
* web_contents
,
1155 : ContentSettingTitleAndLinkModel(delegate
,
1158 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1159 SetDomainsAndCustomLink();
1162 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1163 const std::set
<std::string
>& hosts
, int title_id
) {
1164 if (!hosts
.empty()) {
1165 DomainList domain_list
;
1166 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
1167 domain_list
.hosts
= hosts
;
1168 add_domain_list(domain_list
);
1172 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1173 TabSpecificContentSettings
* content_settings
=
1174 TabSpecificContentSettings::FromWebContents(web_contents());
1175 const ContentSettingsUsagesState
& usages_state
=
1176 content_settings
->midi_usages_state();
1177 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
1178 unsigned int tab_state_flags
= 0;
1179 usages_state
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
1180 // Divide the tab's current MIDI sysex users into sets according to their
1181 // permission state.
1182 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
1183 IDS_MIDI_SYSEX_BUBBLE_ALLOWED
);
1185 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
1186 IDS_MIDI_SYSEX_BUBBLE_DENIED
);
1188 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1189 set_custom_link(l10n_util::GetStringUTF8(
1190 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK
));
1191 set_custom_link_enabled(true);
1192 } else if (tab_state_flags
&
1193 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1194 set_custom_link(l10n_util::GetStringUTF8(
1195 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1199 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1200 if (!web_contents())
1202 // Reset this embedder's entry to default for each of the requesting
1203 // origins currently on the page.
1204 const GURL
& embedder_url
= web_contents()->GetURL();
1205 TabSpecificContentSettings
* content_settings
=
1206 TabSpecificContentSettings::FromWebContents(web_contents());
1207 const ContentSettingsUsagesState::StateMap
& state_map
=
1208 content_settings
->midi_usages_state().state_map();
1209 HostContentSettingsMap
* settings_map
=
1210 profile()->GetHostContentSettingsMap();
1212 for (const std::pair
<GURL
, ContentSetting
>& map_entry
: state_map
) {
1213 settings_map
->SetContentSetting(
1214 ContentSettingsPattern::FromURLNoWildcard(map_entry
.first
),
1215 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1216 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, std::string(),
1217 CONTENT_SETTING_DEFAULT
);
1222 ContentSettingBubbleModel
*
1223 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1225 WebContents
* web_contents
,
1227 ContentSettingsType content_type
) {
1228 if (content_type
== CONTENT_SETTINGS_TYPE_COOKIES
) {
1229 return new ContentSettingCookiesBubbleModel(delegate
, web_contents
,
1232 if (content_type
== CONTENT_SETTINGS_TYPE_POPUPS
) {
1233 return new ContentSettingPopupBubbleModel(delegate
, web_contents
, profile
);
1235 if (content_type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
1236 return new ContentSettingDomainListBubbleModel(delegate
, web_contents
,
1237 profile
, content_type
);
1239 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
1240 return new ContentSettingMediaStreamBubbleModel(delegate
, web_contents
,
1243 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
1244 return new ContentSettingPluginBubbleModel(delegate
, web_contents
, profile
);
1246 if (content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1247 return new ContentSettingMixedScriptBubbleModel(delegate
, web_contents
,
1250 if (content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
1251 ProtocolHandlerRegistry
* registry
=
1252 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile
);
1253 return new ContentSettingRPHBubbleModel(delegate
, web_contents
, profile
,
1256 if (content_type
== CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1257 return new ContentSettingMidiSysExBubbleModel(delegate
, web_contents
,
1260 return new ContentSettingSingleRadioGroup(delegate
, web_contents
, profile
,
1264 ContentSettingBubbleModel::ContentSettingBubbleModel(
1265 WebContents
* web_contents
,
1267 ContentSettingsType content_type
)
1268 : web_contents_(web_contents
),
1270 content_type_(content_type
),
1271 setting_is_managed_(false) {
1272 registrar_
.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1273 content::Source
<WebContents
>(web_contents
));
1274 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
1275 content::Source
<Profile
>(profile_
));
1278 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1281 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1283 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1285 ContentSettingBubbleModel::DomainList::DomainList() {}
1287 ContentSettingBubbleModel::DomainList::~DomainList() {}
1289 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1291 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1293 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1294 : radio_group_enabled(false),
1295 custom_link_enabled(false) {
1298 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1300 void ContentSettingBubbleModel::Observe(
1302 const content::NotificationSource
& source
,
1303 const content::NotificationDetails
& details
) {
1304 if (type
== content::NOTIFICATION_WEB_CONTENTS_DESTROYED
) {
1305 DCHECK_EQ(web_contents_
,
1306 content::Source
<WebContents
>(source
).ptr());
1307 web_contents_
= NULL
;
1309 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
1310 DCHECK_EQ(profile_
, content::Source
<Profile
>(source
).ptr());