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 "net/base/net_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/resource/resource_bundle.h"
42 #include "ui/resources/grit/ui_resources.h"
44 using base::UserMetricsAction
;
45 using content::WebContents
;
46 using content_settings::SettingInfo
;
47 using content_settings::SettingSource
;
48 using content_settings::SETTING_SOURCE_USER
;
49 using content_settings::SETTING_SOURCE_NONE
;
53 const int kAllowButtonIndex
= 0;
55 // These states must match the order of appearance of the radio buttons
56 // in the XIB file for the Mac port.
63 struct ContentSettingsTypeIdEntry
{
64 ContentSettingsType type
;
68 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
70 ContentSettingsType type
) {
71 for (size_t i
= 0; i
< num_entries
; ++i
) {
72 if (entries
[i
].type
== type
)
78 const content::MediaStreamDevice
& GetMediaDeviceById(
79 const std::string
& device_id
,
80 const content::MediaStreamDevices
& devices
) {
81 DCHECK(!devices
.empty());
82 for (content::MediaStreamDevices::const_iterator it
= devices
.begin();
83 it
!= devices
.end(); ++it
) {
84 if (it
->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 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&& content_settings
&&
118 content_settings
->IsContentBlocked(content_type())) {
119 set_plugin_names(content_settings
->GetBlockedPluginNames());
122 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
123 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
124 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
125 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
126 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_TITLE
},
127 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
128 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
129 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
130 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
131 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
132 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
134 // Fields as for kBlockedTitleIDs, above.
135 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
136 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
137 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
138 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
140 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
141 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
142 if (content_settings
&& content_settings
->IsContentAllowed(content_type()) &&
143 !content_settings
->IsContentBlocked(content_type())) {
144 title_ids
= kAccessedTitleIDs
;
145 num_title_ids
= arraysize(kAccessedTitleIDs
);
148 GetIdForContentType(title_ids
, num_title_ids
, content_type());
150 set_title(l10n_util::GetStringUTF8(title_id
));
153 void ContentSettingTitleAndLinkModel::SetManageLink() {
154 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
155 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
156 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
157 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
158 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
159 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
160 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
161 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
162 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
163 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
164 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
165 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
166 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
168 set_manage_link(l10n_util::GetStringUTF8(
169 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
172 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
174 delegate_
->ShowContentSettingsPage(content_type());
177 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
178 static const ContentSettingsTypeIdEntry kLearnMoreIDs
[] = {
179 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_LEARN_MORE
},
182 GetIdForContentType(kLearnMoreIDs
, arraysize(kLearnMoreIDs
),
185 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id
));
188 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
190 delegate_
->ShowLearnMorePage(content_type());
193 class ContentSettingTitleLinkAndCustomModel
194 : public ContentSettingTitleAndLinkModel
{
196 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
197 WebContents
* web_contents
,
199 ContentSettingsType content_type
);
200 ~ContentSettingTitleLinkAndCustomModel() override
{}
203 void SetCustomLink();
204 void OnCustomLinkClicked() override
{}
207 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
209 WebContents
* web_contents
,
211 ContentSettingsType content_type
)
212 : ContentSettingTitleAndLinkModel(
213 delegate
, web_contents
, profile
, content_type
) {
217 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
218 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
219 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
220 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
221 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
224 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
226 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
229 class ContentSettingSingleRadioGroup
230 : public ContentSettingTitleLinkAndCustomModel
{
232 ContentSettingSingleRadioGroup(Delegate
* delegate
,
233 WebContents
* web_contents
,
235 ContentSettingsType content_type
);
236 ~ContentSettingSingleRadioGroup() override
;
239 bool settings_changed() const;
240 int selected_item() const { return selected_item_
; }
243 void SetRadioGroup();
244 void AddException(ContentSetting setting
);
245 void OnRadioClicked(int radio_index
) override
;
247 ContentSetting block_setting_
;
251 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
253 WebContents
* web_contents
,
255 ContentSettingsType content_type
)
256 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
258 block_setting_(CONTENT_SETTING_BLOCK
),
263 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
264 if (settings_changed()) {
265 ContentSetting setting
=
266 selected_item_
== kAllowButtonIndex
?
267 CONTENT_SETTING_ALLOW
:
269 AddException(setting
);
273 bool ContentSettingSingleRadioGroup::settings_changed() const {
274 return selected_item_
!= bubble_content().radio_group
.default_item
;
277 // Initialize the radio group by setting the appropriate labels for the
278 // content type and setting the default value based on the content setting.
279 void ContentSettingSingleRadioGroup::SetRadioGroup() {
280 GURL url
= web_contents()->GetURL();
281 base::string16 display_host
;
282 net::AppendFormattedHost(
284 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
287 if (display_host
.empty())
288 display_host
= base::ASCIIToUTF16(url
.spec());
290 TabSpecificContentSettings
* content_settings
=
291 TabSpecificContentSettings::FromWebContents(web_contents());
293 !content_settings
->IsContentBlocked(content_type());
295 content_settings
->IsContentAllowed(content_type()));
297 RadioGroup radio_group
;
298 radio_group
.url
= url
;
300 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
301 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
302 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
303 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
304 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
305 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
306 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
307 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
309 // Fields as for kBlockedAllowIDs, above.
310 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
311 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
312 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
313 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
314 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
317 std::string radio_allow_label
;
319 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
320 arraysize(kAllowedAllowIDs
),
322 radio_allow_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
323 l10n_util::GetStringFUTF8(resource_id
, display_host
) :
324 l10n_util::GetStringUTF8(resource_id
);
326 radio_allow_label
= l10n_util::GetStringFUTF8(
327 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
332 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
333 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
334 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
335 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
336 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
337 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
338 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
339 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
341 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
342 // TODO(bauerb): The string should say "block".
343 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
344 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
345 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
348 std::string radio_block_label
;
350 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
351 arraysize(kAllowedBlockIDs
),
353 radio_block_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
354 l10n_util::GetStringUTF8(resource_id
) :
355 l10n_util::GetStringFUTF8(resource_id
, display_host
);
357 radio_block_label
= l10n_util::GetStringUTF8(
358 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
362 radio_group
.radio_items
.push_back(radio_allow_label
);
363 radio_group
.radio_items
.push_back(radio_block_label
);
364 ContentSetting setting
;
365 SettingSource setting_source
= SETTING_SOURCE_NONE
;
366 bool setting_is_wildcard
= false;
368 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
369 CookieSettings
* cookie_settings
=
370 CookieSettings::Factory::GetForProfile(profile()).get();
371 setting
= cookie_settings
->GetCookieSetting(
372 url
, url
, true, &setting_source
);
375 HostContentSettingsMap
* map
= profile()->GetHostContentSettingsMap();
376 scoped_ptr
<base::Value
> value
=
377 map
->GetWebsiteSetting(url
, url
, content_type(), std::string(), &info
);
378 setting
= content_settings::ValueToContentSetting(value
.get());
379 setting_source
= info
.source
;
380 setting_is_wildcard
=
381 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
382 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
385 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
386 setting
== CONTENT_SETTING_ALLOW
&&
387 setting_is_wildcard
) {
388 // In the corner case of unrecognized plugins (which are now blocked by
389 // default) we indicate the blocked state in the UI and allow the user to
391 radio_group
.default_item
= 1;
392 } else if (setting
== CONTENT_SETTING_ALLOW
) {
393 radio_group
.default_item
= kAllowButtonIndex
;
394 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
396 radio_group
.default_item
= 1;
397 block_setting_
= setting
;
400 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
);
401 if (setting_source
!= SETTING_SOURCE_USER
) {
402 set_radio_group_enabled(false);
404 set_radio_group_enabled(true);
406 selected_item_
= radio_group
.default_item
;
407 set_radio_group(radio_group
);
410 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
412 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
413 bubble_content().radio_group
.url
,
414 bubble_content().radio_group
.url
,
420 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
421 selected_item_
= radio_index
;
424 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
426 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
427 WebContents
* web_contents
,
429 ContentSettingsType content_type
);
431 ~ContentSettingCookiesBubbleModel() override
;
434 void OnCustomLinkClicked() override
;
437 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
439 WebContents
* web_contents
,
441 ContentSettingsType content_type
)
442 : ContentSettingSingleRadioGroup(
443 delegate
, web_contents
, profile
, content_type
) {
444 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES
, content_type
);
445 set_custom_link_enabled(true);
448 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
449 // On some plattforms e.g. MacOS X it is possible to close a tab while the
450 // cookies settings bubble is open. This resets the web contents to NULL.
451 if (settings_changed() && web_contents()) {
452 CollectedCookiesInfoBarDelegate::Create(
453 InfoBarService::FromWebContents(web_contents()));
457 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
460 content::NotificationService::current()->Notify(
461 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
462 content::Source
<TabSpecificContentSettings
>(
463 TabSpecificContentSettings::FromWebContents(web_contents())),
464 content::NotificationService::NoDetails());
465 delegate()->ShowCollectedCookiesDialog(web_contents());
468 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
470 ContentSettingPluginBubbleModel(Delegate
* delegate
,
471 WebContents
* web_contents
,
473 ContentSettingsType content_type
);
475 ~ContentSettingPluginBubbleModel() override
;
478 void OnCustomLinkClicked() override
;
481 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
483 WebContents
* web_contents
,
485 ContentSettingsType content_type
)
486 : ContentSettingSingleRadioGroup(
487 delegate
, web_contents
, profile
, content_type
) {
488 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_PLUGINS
);
489 // Disable the "Run all plugins this time" link if the setting is managed and
490 // can't be controlled by the user or if the user already clicked on the link
491 // and ran all plugins.
492 set_custom_link_enabled(!setting_is_managed() &&
494 TabSpecificContentSettings::FromWebContents(
495 web_contents
)->load_plugins_link_enabled());
498 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
499 if (settings_changed()) {
500 // If the user elected to allow all plugins then run plugins at this time.
501 if (selected_item() == kAllowButtonIndex
)
502 OnCustomLinkClicked();
506 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
507 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
508 // Web contents can be NULL if the tab was closed while the plugins
509 // settings bubble is visible.
512 #if defined(ENABLE_PLUGINS)
513 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
514 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
515 web_contents(), true, std::string());
517 set_custom_link_enabled(false);
518 TabSpecificContentSettings::FromWebContents(web_contents())->
519 set_load_plugins_link_enabled(false);
522 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
524 ContentSettingPopupBubbleModel(Delegate
* delegate
,
525 WebContents
* web_contents
,
527 ContentSettingsType content_type
);
528 ~ContentSettingPopupBubbleModel() override
{}
532 void OnPopupClicked(int index
) override
;
535 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
537 WebContents
* web_contents
,
539 ContentSettingsType content_type
)
540 : ContentSettingSingleRadioGroup(
541 delegate
, web_contents
, profile
, content_type
) {
546 void ContentSettingPopupBubbleModel::SetPopups() {
547 std::map
<int32
, GURL
> blocked_popups
=
548 PopupBlockerTabHelper::FromWebContents(web_contents())
549 ->GetBlockedPopupRequests();
550 for (std::map
<int32
, GURL
>::const_iterator iter
= blocked_popups
.begin();
551 iter
!= blocked_popups
.end();
553 std::string
title(iter
->second
.spec());
554 // The popup may not have a valid URL.
556 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
557 PopupItem
popup_item(
558 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
559 IDR_DEFAULT_FAVICON
),
562 add_popup(popup_item
);
566 void ContentSettingPopupBubbleModel::OnPopupClicked(int index
) {
567 if (web_contents()) {
568 PopupBlockerTabHelper::FromWebContents(web_contents())->
569 ShowBlockedPopup(bubble_content().popup_items
[index
].popup_id
);
573 // The model of the content settings bubble for media settings.
574 class ContentSettingMediaStreamBubbleModel
575 : public ContentSettingTitleAndLinkModel
{
577 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
578 WebContents
* web_contents
,
581 ~ContentSettingMediaStreamBubbleModel() override
;
585 // Sets the data for the radio buttons of the bubble.
586 void SetRadioGroup();
587 // Sets the data for the media menus of the bubble.
588 void SetMediaMenus();
589 void SetCustomLink();
590 // Updates the camera and microphone setting with the passed |setting|.
591 void UpdateSettings(ContentSetting setting
);
592 // Updates the camera and microphone default device with the passed |type|
594 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
595 const std::string
& device
);
597 // ContentSettingBubbleModel implementation.
598 void OnRadioClicked(int radio_index
) override
;
599 void OnMediaMenuClicked(content::MediaStreamType type
,
600 const std::string
& selected_device
) override
;
602 // The index of the selected radio item.
604 // The content settings that are associated with the individual radio
606 ContentSetting radio_item_setting_
[2];
607 // The state of the microphone and camera access.
608 TabSpecificContentSettings::MicrophoneCameraState state_
;
611 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
613 WebContents
* web_contents
,
615 : ContentSettingTitleAndLinkModel(
616 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
618 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
620 // Initialize the content settings associated with the individual radio
622 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
623 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
625 TabSpecificContentSettings
* content_settings
=
626 TabSpecificContentSettings::FromWebContents(web_contents
);
627 state_
= content_settings
->GetMicrophoneCameraState();
628 DCHECK(state_
& (TabSpecificContentSettings::MICROPHONE_ACCESSED
|
629 TabSpecificContentSettings::CAMERA_ACCESSED
));
637 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
638 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
639 // media stream bubble is open. This resets the web contents to NULL.
643 for (MediaMenuMap::const_iterator it
= bubble_content().media_menus
.begin();
644 it
!= bubble_content().media_menus
.end(); ++it
) {
645 if (it
->second
.selected_device
.id
!= it
->second
.default_device
.id
) {
646 UpdateDefaultDeviceForType(it
->first
, it
->second
.selected_device
.id
);
650 // Update the media settings if the radio button selection was changed.
651 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
652 UpdateSettings(radio_item_setting_
[selected_item_
]);
656 void ContentSettingMediaStreamBubbleModel::SetTitle() {
657 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
, state_
);
659 if (state_
& TabSpecificContentSettings::MICROPHONE_BLOCKED
) {
660 title_id
= (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) ?
661 IDS_MICROPHONE_CAMERA_BLOCKED
: IDS_MICROPHONE_BLOCKED
;
662 } else if (state_
& TabSpecificContentSettings::CAMERA_BLOCKED
) {
663 title_id
= IDS_CAMERA_BLOCKED
;
664 } else if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
665 title_id
= (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) ?
666 IDS_MICROPHONE_CAMERA_ALLOWED
: IDS_MICROPHONE_ACCESSED
;
667 } else if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
668 title_id
= IDS_CAMERA_ACCESSED
;
670 set_title(l10n_util::GetStringUTF8(title_id
));
673 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
674 TabSpecificContentSettings
* content_settings
=
675 TabSpecificContentSettings::FromWebContents(web_contents());
676 GURL url
= content_settings
->media_stream_access_origin();
677 RadioGroup radio_group
;
678 radio_group
.url
= url
;
680 base::string16 display_host_utf16
;
681 net::AppendFormattedHost(
683 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
684 &display_host_utf16
);
685 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
686 if (display_host
.empty())
687 display_host
= url
.spec();
689 bool is_mic
= (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) != 0;
690 bool is_cam
= (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) != 0;
691 DCHECK(is_mic
|| is_cam
);
692 int radio_allow_label_id
= 0;
693 int radio_block_label_id
= 0;
694 if (state_
& (TabSpecificContentSettings::MICROPHONE_BLOCKED
|
695 TabSpecificContentSettings::CAMERA_BLOCKED
)) {
696 if (url
.SchemeIsSecure()) {
697 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
698 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
700 radio_allow_label_id
= is_cam
?
701 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
:
702 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
704 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
706 radio_allow_label_id
= is_cam
?
707 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
:
708 IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
710 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
712 radio_block_label_id
= is_cam
?
713 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
:
714 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
716 if (is_mic
&& is_cam
) {
717 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
718 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
720 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
721 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
723 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
724 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
728 (is_mic
&& content_settings
->IsContentBlocked(
729 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
)) ||
730 (is_cam
&& content_settings
->IsContentBlocked(
731 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
)) ? 1 : 0;
733 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
734 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
735 std::string radio_block_label
=
736 l10n_util::GetStringUTF8(radio_block_label_id
);
738 radio_group
.default_item
= selected_item_
;
739 radio_group
.radio_items
.push_back(radio_allow_label
);
740 radio_group
.radio_items
.push_back(radio_block_label
);
742 set_radio_group(radio_group
);
743 set_radio_group_enabled(true);
746 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
747 ContentSetting setting
) {
749 HostContentSettingsMap
* content_settings
=
750 profile()->GetHostContentSettingsMap();
751 TabSpecificContentSettings
* tab_content_settings
=
752 TabSpecificContentSettings::FromWebContents(web_contents());
753 // The same patterns must be used as in other places (e.g. the infobar) in
754 // order to override the existing rule. Otherwise a new rule is created.
755 // TODO(markusheintz): Extract to a helper so that there is only a single
757 ContentSettingsPattern primary_pattern
=
758 ContentSettingsPattern::FromURLNoWildcard(
759 tab_content_settings
->media_stream_access_origin());
760 ContentSettingsPattern secondary_pattern
=
761 ContentSettingsPattern::Wildcard();
762 if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
763 content_settings
->SetContentSetting(
764 primary_pattern
, secondary_pattern
,
765 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
767 if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
768 content_settings
->SetContentSetting(
769 primary_pattern
, secondary_pattern
,
770 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string(), setting
);
775 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
776 content::MediaStreamType type
,
777 const std::string
& device
) {
778 PrefService
* prefs
= profile()->GetPrefs();
779 if (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
780 prefs
->SetString(prefs::kDefaultAudioCaptureDevice
, device
);
782 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE
, type
);
783 prefs
->SetString(prefs::kDefaultVideoCaptureDevice
, device
);
787 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
788 TabSpecificContentSettings
* content_settings
=
789 TabSpecificContentSettings::FromWebContents(web_contents());
790 const std::string
& requested_microphone
=
791 content_settings
->media_stream_requested_audio_device();
792 const std::string
& requested_camera
=
793 content_settings
->media_stream_requested_video_device();
795 // Add microphone menu.
796 PrefService
* prefs
= profile()->GetPrefs();
797 MediaCaptureDevicesDispatcher
* dispatcher
=
798 MediaCaptureDevicesDispatcher::GetInstance();
799 const content::MediaStreamDevices
& microphones
=
800 dispatcher
->GetAudioCaptureDevices();
802 if (state_
& TabSpecificContentSettings::MICROPHONE_ACCESSED
) {
804 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
805 if (!microphones
.empty()) {
806 std::string preferred_mic
;
807 if (requested_microphone
.empty()) {
808 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
809 mic_menu
.disabled
= false;
811 // Set the |disabled| to true in order to disable the device selection
812 // menu on the media settings bubble. This must be done if the website
813 // manages the microphone devices itself.
814 preferred_mic
= requested_microphone
;
815 mic_menu
.disabled
= true;
818 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
819 mic_menu
.selected_device
= mic_menu
.default_device
;
821 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
824 if (state_
& TabSpecificContentSettings::CAMERA_ACCESSED
) {
825 const content::MediaStreamDevices
& cameras
=
826 dispatcher
->GetVideoCaptureDevices();
827 MediaMenu camera_menu
;
829 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
830 if (!cameras
.empty()) {
831 std::string preferred_camera
;
832 if (requested_camera
.empty()) {
833 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
834 camera_menu
.disabled
= false;
836 // Disable the menu since the website is managing the camera devices
838 preferred_camera
= requested_camera
;
839 camera_menu
.disabled
= true;
842 camera_menu
.default_device
=
843 GetMediaDeviceById(preferred_camera
, cameras
);
844 camera_menu
.selected_device
= camera_menu
.default_device
;
846 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
850 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
851 TabSpecificContentSettings
* content_settings
=
852 TabSpecificContentSettings::FromWebContents(web_contents());
853 if (content_settings
->IsMicrophoneCameraStateChanged()) {
854 set_custom_link(l10n_util::GetStringUTF8(
855 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE
));
859 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
860 selected_item_
= radio_index
;
863 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
864 content::MediaStreamType type
,
865 const std::string
& selected_device_id
) {
866 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
867 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
868 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
869 MediaCaptureDevicesDispatcher
* dispatcher
=
870 MediaCaptureDevicesDispatcher::GetInstance();
871 const content::MediaStreamDevices
& devices
=
872 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
873 dispatcher
->GetAudioCaptureDevices() :
874 dispatcher
->GetVideoCaptureDevices();
875 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
878 class ContentSettingDomainListBubbleModel
879 : public ContentSettingTitleAndLinkModel
{
881 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
882 WebContents
* web_contents
,
884 ContentSettingsType content_type
);
885 ~ContentSettingDomainListBubbleModel() override
{}
888 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
889 void SetDomainsAndCustomLink();
890 void OnCustomLinkClicked() override
;
893 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
895 WebContents
* web_contents
,
897 ContentSettingsType content_type
)
898 : ContentSettingTitleAndLinkModel(
899 delegate
, web_contents
, profile
, content_type
) {
900 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
901 "SetDomains currently only supports geolocation content type";
902 SetDomainsAndCustomLink();
905 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
906 const std::set
<std::string
>& hosts
, int title_id
) {
907 if (!hosts
.empty()) {
908 DomainList domain_list
;
909 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
910 domain_list
.hosts
= hosts
;
911 add_domain_list(domain_list
);
915 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
916 TabSpecificContentSettings
* content_settings
=
917 TabSpecificContentSettings::FromWebContents(web_contents());
918 const ContentSettingsUsagesState
& usages
=
919 content_settings
->geolocation_usages_state();
920 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
921 unsigned int tab_state_flags
= 0;
922 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
923 // Divide the tab's current geolocation users into sets according to their
925 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
926 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
928 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
929 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
931 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
932 set_custom_link(l10n_util::GetStringUTF8(
933 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
934 set_custom_link_enabled(true);
935 } else if (tab_state_flags
&
936 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
937 set_custom_link(l10n_util::GetStringUTF8(
938 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
942 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
945 // Reset this embedder's entry to default for each of the requesting
946 // origins currently on the page.
947 const GURL
& embedder_url
= web_contents()->GetURL();
948 TabSpecificContentSettings
* content_settings
=
949 TabSpecificContentSettings::FromWebContents(web_contents());
950 const ContentSettingsUsagesState::StateMap
& state_map
=
951 content_settings
->geolocation_usages_state().state_map();
952 HostContentSettingsMap
* settings_map
=
953 profile()->GetHostContentSettingsMap();
955 for (ContentSettingsUsagesState::StateMap::const_iterator it
=
956 state_map
.begin(); it
!= state_map
.end(); ++it
) {
957 settings_map
->SetContentSetting(
958 ContentSettingsPattern::FromURLNoWildcard(it
->first
),
959 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
960 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
962 CONTENT_SETTING_DEFAULT
);
966 class ContentSettingMixedScriptBubbleModel
967 : public ContentSettingTitleLinkAndCustomModel
{
969 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
970 WebContents
* web_contents
,
972 ContentSettingsType content_type
);
974 ~ContentSettingMixedScriptBubbleModel() override
{}
977 void OnCustomLinkClicked() override
;
980 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
982 WebContents
* web_contents
,
984 ContentSettingsType content_type
)
985 : ContentSettingTitleLinkAndCustomModel(
986 delegate
, web_contents
, profile
, content_type
) {
987 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
);
988 content_settings::RecordMixedScriptAction(
989 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE
);
990 set_custom_link_enabled(true);
993 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
994 content_settings::RecordMixedScriptAction(
995 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW
);
996 DCHECK(web_contents());
997 web_contents()->SendToAllFrames(
998 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE
, true));
999 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1000 web_contents()->GetMainFrame()->GetRoutingID()));
1003 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1005 WebContents
* web_contents
,
1007 ProtocolHandlerRegistry
* registry
,
1008 ContentSettingsType content_type
)
1009 : ContentSettingTitleAndLinkModel(
1010 delegate
, web_contents
, profile
, content_type
),
1012 registry_(registry
),
1013 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1014 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1015 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, content_type
);
1017 TabSpecificContentSettings
* content_settings
=
1018 TabSpecificContentSettings::FromWebContents(web_contents
);
1019 pending_handler_
= content_settings
->pending_protocol_handler();
1020 previous_handler_
= content_settings
->previous_protocol_handler();
1022 base::string16 protocol
;
1023 if (pending_handler_
.protocol() == "mailto") {
1024 protocol
= l10n_util::GetStringUTF16(
1025 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1026 } else if (pending_handler_
.protocol() == "webcal") {
1027 protocol
= l10n_util::GetStringUTF16(
1028 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1030 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1033 // Note that we ignore the |title| parameter.
1034 if (previous_handler_
.IsEmpty()) {
1035 set_title(l10n_util::GetStringFUTF8(
1036 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1037 base::UTF8ToUTF16(pending_handler_
.url().host()),
1040 set_title(l10n_util::GetStringFUTF8(
1041 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1042 base::UTF8ToUTF16(pending_handler_
.url().host()),
1044 base::UTF8ToUTF16(previous_handler_
.url().host())));
1047 std::string radio_allow_label
=
1048 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
);
1049 std::string radio_deny_label
=
1050 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY
);
1051 std::string radio_ignore_label
=
1052 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE
);
1054 GURL url
= web_contents
->GetURL();
1055 RadioGroup radio_group
;
1056 radio_group
.url
= url
;
1058 radio_group
.radio_items
.push_back(radio_allow_label
);
1059 radio_group
.radio_items
.push_back(radio_deny_label
);
1060 radio_group
.radio_items
.push_back(radio_ignore_label
);
1061 ContentSetting setting
=
1062 content_settings
->pending_protocol_handler_setting();
1063 if (setting
== CONTENT_SETTING_ALLOW
)
1064 radio_group
.default_item
= RPH_ALLOW
;
1065 else if (setting
== CONTENT_SETTING_BLOCK
)
1066 radio_group
.default_item
= RPH_BLOCK
;
1068 radio_group
.default_item
= RPH_IGNORE
;
1070 selected_item_
= radio_group
.default_item
;
1071 set_radio_group_enabled(true);
1072 set_radio_group(radio_group
);
1075 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index
) {
1076 if (selected_item_
== radio_index
)
1079 selected_item_
= radio_index
;
1081 if (radio_index
== RPH_ALLOW
)
1082 RegisterProtocolHandler();
1083 else if (radio_index
== RPH_BLOCK
)
1084 UnregisterProtocolHandler();
1085 else if (radio_index
== RPH_IGNORE
)
1086 IgnoreProtocolHandler();
1091 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1092 // The user has one chance to deal with the RPH content setting UI,
1093 // then we remove it.
1094 TabSpecificContentSettings::FromWebContents(web_contents())->
1095 ClearPendingProtocolHandler();
1096 content::NotificationService::current()->Notify(
1097 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
1098 content::Source
<WebContents
>(web_contents()),
1099 content::NotificationService::NoDetails());
1102 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1103 // A no-op if the handler hasn't been ignored, but needed in case the user
1104 // selects sequences like register/ignore/register.
1105 registry_
->RemoveIgnoredHandler(pending_handler_
);
1107 registry_
->OnAcceptRegisterProtocolHandler(pending_handler_
);
1108 TabSpecificContentSettings::FromWebContents(web_contents())->
1109 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW
);
1112 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1113 registry_
->OnDenyRegisterProtocolHandler(pending_handler_
);
1114 TabSpecificContentSettings::FromWebContents(web_contents())->
1115 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK
);
1116 ClearOrSetPreviousHandler();
1119 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1120 registry_
->OnIgnoreRegisterProtocolHandler(pending_handler_
);
1121 TabSpecificContentSettings::FromWebContents(web_contents())->
1122 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT
);
1123 ClearOrSetPreviousHandler();
1126 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1127 if (previous_handler_
.IsEmpty()) {
1128 registry_
->ClearDefault(pending_handler_
.protocol());
1130 registry_
->OnAcceptRegisterProtocolHandler(previous_handler_
);
1134 class ContentSettingMidiSysExBubbleModel
1135 : public ContentSettingTitleAndLinkModel
{
1137 ContentSettingMidiSysExBubbleModel(Delegate
* delegate
,
1138 WebContents
* web_contents
,
1140 ContentSettingsType content_type
);
1141 ~ContentSettingMidiSysExBubbleModel() override
{}
1144 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1145 void SetDomainsAndCustomLink();
1146 void OnCustomLinkClicked() override
;
1149 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1151 WebContents
* web_contents
,
1153 ContentSettingsType content_type
)
1154 : ContentSettingTitleAndLinkModel(
1155 delegate
, web_contents
, profile
, content_type
) {
1156 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, content_type
);
1157 SetDomainsAndCustomLink();
1160 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1161 const std::set
<std::string
>& hosts
, int title_id
) {
1162 if (!hosts
.empty()) {
1163 DomainList domain_list
;
1164 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
1165 domain_list
.hosts
= hosts
;
1166 add_domain_list(domain_list
);
1170 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1171 TabSpecificContentSettings
* content_settings
=
1172 TabSpecificContentSettings::FromWebContents(web_contents());
1173 const ContentSettingsUsagesState
& usages_state
=
1174 content_settings
->midi_usages_state();
1175 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
1176 unsigned int tab_state_flags
= 0;
1177 usages_state
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
1178 // Divide the tab's current MIDI sysex users into sets according to their
1179 // permission state.
1180 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
1181 IDS_MIDI_SYSEX_BUBBLE_ALLOWED
);
1183 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
1184 IDS_MIDI_SYSEX_BUBBLE_DENIED
);
1186 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1187 set_custom_link(l10n_util::GetStringUTF8(
1188 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK
));
1189 set_custom_link_enabled(true);
1190 } else if (tab_state_flags
&
1191 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1192 set_custom_link(l10n_util::GetStringUTF8(
1193 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1197 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1198 if (!web_contents())
1200 // Reset this embedder's entry to default for each of the requesting
1201 // origins currently on the page.
1202 const GURL
& embedder_url
= web_contents()->GetURL();
1203 TabSpecificContentSettings
* content_settings
=
1204 TabSpecificContentSettings::FromWebContents(web_contents());
1205 const ContentSettingsUsagesState::StateMap
& state_map
=
1206 content_settings
->midi_usages_state().state_map();
1207 HostContentSettingsMap
* settings_map
=
1208 profile()->GetHostContentSettingsMap();
1210 for (ContentSettingsUsagesState::StateMap::const_iterator it
=
1211 state_map
.begin(); it
!= state_map
.end(); ++it
) {
1212 settings_map
->SetContentSetting(
1213 ContentSettingsPattern::FromURLNoWildcard(it
->first
),
1214 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
1215 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
,
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
, profile
,
1232 if (content_type
== CONTENT_SETTINGS_TYPE_POPUPS
) {
1233 return new ContentSettingPopupBubbleModel(delegate
, web_contents
, profile
,
1236 if (content_type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
1237 return new ContentSettingDomainListBubbleModel(delegate
, web_contents
,
1238 profile
, content_type
);
1240 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
1241 return new ContentSettingMediaStreamBubbleModel(delegate
, web_contents
,
1244 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
1245 return new ContentSettingPluginBubbleModel(delegate
, web_contents
, profile
,
1248 if (content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1249 return new ContentSettingMixedScriptBubbleModel(delegate
, web_contents
,
1250 profile
, content_type
);
1252 if (content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
1253 ProtocolHandlerRegistry
* registry
=
1254 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile
);
1255 return new ContentSettingRPHBubbleModel(delegate
, web_contents
, profile
,
1256 registry
, content_type
);
1258 if (content_type
== CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1259 return new ContentSettingMidiSysExBubbleModel(delegate
, web_contents
,
1260 profile
, content_type
);
1262 return new ContentSettingSingleRadioGroup(delegate
, web_contents
, profile
,
1266 ContentSettingBubbleModel::ContentSettingBubbleModel(
1267 WebContents
* web_contents
,
1269 ContentSettingsType content_type
)
1270 : web_contents_(web_contents
),
1272 content_type_(content_type
),
1273 setting_is_managed_(false) {
1274 registrar_
.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1275 content::Source
<WebContents
>(web_contents
));
1276 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
1277 content::Source
<Profile
>(profile_
));
1280 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1283 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1285 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1287 ContentSettingBubbleModel::DomainList::DomainList() {}
1289 ContentSettingBubbleModel::DomainList::~DomainList() {}
1291 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1293 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1295 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1296 : radio_group_enabled(false),
1297 custom_link_enabled(false) {
1300 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1302 void ContentSettingBubbleModel::Observe(
1304 const content::NotificationSource
& source
,
1305 const content::NotificationDetails
& details
) {
1306 if (type
== content::NOTIFICATION_WEB_CONTENTS_DESTROYED
) {
1307 DCHECK_EQ(web_contents_
,
1308 content::Source
<WebContents
>(source
).ptr());
1309 web_contents_
= NULL
;
1311 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
1312 DCHECK_EQ(profile_
, content::Source
<Profile
>(source
).ptr());